Ariver
2026-07-11 015f1089ea875a153dd2a18ef42c25145d4868f5
C1.source/privatevoice.src/scripts/build-macappstore-pkg-macos.sh
@@ -21,6 +21,8 @@
#   PRIVATEVOICE_SIGNING_KEYCHAIN
#   PRIVATEVOICE_APPSTORE_MIN_SYSTEM_VERSION (default: 13.4)
#   PRIVATEVOICE_MACAPPSTORE_BUILD_ROOT (default: build/macappstore)
#   PRIVATEVOICE_APP_VERSION (default: build/darwin/Info.plist CFBundleShortVersionString)
#   PRIVATEVOICE_APP_BUILD (default: build/darwin/Info.plist CFBundleVersion)
#
# Usage:
#   cd privatevoice.src
@@ -37,6 +39,7 @@
APPSTORE_PROVISIONING_PROFILE="${PRIVATEVOICE_APPSTORE_PROVISIONING_PROFILE:-}"
SIGNING_KEYCHAIN="${PRIVATEVOICE_SIGNING_KEYCHAIN:-}"
APPSTORE_MIN_SYSTEM_VERSION="${PRIVATEVOICE_APPSTORE_MIN_SYSTEM_VERSION:-13.4}"
APPSTORE_APP_SIGN_IDENTITY=""
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
@@ -44,12 +47,13 @@
INFO_PLIST="$PROJECT_DIR/build/darwin/Info.plist"
BASE_ENTITLEMENTS="$PROJECT_DIR/build/darwin/entitlements-appstore.plist"
PRIVACY_MANIFEST="$PROJECT_DIR/build/darwin/PrivacyInfo.xcprivacy"
GOMODCACHE="$(go env GOMODCACHE)"
SHERPA_MACOS_MODULE_VERSION="$(cd "$PROJECT_DIR" && go list -m -f '{{.Version}}' github.com/k2-fsa/sherpa-onnx-go-macos)"
VERSION="$(defaults read "$INFO_PLIST" CFBundleShortVersionString 2>/dev/null || echo "2.1.0")"
BUILD_ID="$(defaults read "$INFO_PLIST" CFBundleVersion 2>/dev/null || date +%Y%m%d.%H%M)"
BUNDLE_ID="$(defaults read "$INFO_PLIST" CFBundleIdentifier 2>/dev/null || echo "")"
VERSION="${PRIVATEVOICE_APP_VERSION:-$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "$INFO_PLIST" 2>/dev/null || echo "2.1.0")}"
BUILD_ID="${PRIVATEVOICE_APP_BUILD:-$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "$INFO_PLIST" 2>/dev/null || date +%Y%m%d.%H%M)}"
BUNDLE_ID="$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$INFO_PLIST" 2>/dev/null || echo "")"
step() {
  echo ""
@@ -76,6 +80,75 @@
  else
    security find-identity -v
  fi
}
normalize_sha1() {
  tr '[:lower:]' '[:upper:]' | tr -d ':[:space:]'
}
is_sha1_fingerprint() {
  [[ "$1" =~ ^[0-9A-Fa-f]{40}$ ]]
}
resolve_codesigning_identity_sha1() {
  local requested="$1"
  local requested_sha1=""
  local matches=()
  local line hash name
  if is_sha1_fingerprint "$requested"; then
    requested_sha1="$(printf "%s" "$requested" | normalize_sha1)"
  fi
  while IFS= read -r line; do
    hash="$(awk '{print $2}' <<<"$line")"
    [[ "$hash" =~ ^[0-9A-Fa-f]{40}$ ]] || continue
    name="${line#*\"}"
    name="${name%\"*}"
    if [[ -n "$requested_sha1" ]]; then
      [[ "$(printf "%s" "$hash" | normalize_sha1)" == "$requested_sha1" ]] &&
        matches+=("$(printf "%s" "$hash" | normalize_sha1)")
    elif [[ "$name" == "$requested" ]]; then
      matches+=("$(printf "%s" "$hash" | normalize_sha1)")
    fi
  done < <(security_find_code_identities)
  case "${#matches[@]}" in
    0)
      fail "App Store app signing identity not found: $requested"
      ;;
    1)
      printf "%s\n" "${matches[0]}"
      ;;
    *)
      fail "App Store app signing identity is ambiguous: $requested. Use the 40-character SHA1 fingerprint."
      ;;
  esac
}
profile_developer_certificate_sha1s() {
  local profile_plist="$1"
  local index=0
  local cert_der cert_sha1
  local found=0
  while :; do
    cert_der="$(mktemp)"
    if ! /usr/libexec/PlistBuddy -c "Print :DeveloperCertificates:$index" "$profile_plist" >"$cert_der" 2>/dev/null; then
      rm -f "$cert_der"
      break
    fi
    cert_sha1="$(openssl x509 -inform der -in "$cert_der" -noout -fingerprint -sha1 |
      sed 's/^.*=//' | normalize_sha1)"
    rm -f "$cert_der"
    [[ -n "$cert_sha1" ]] || fail "Unable to read DeveloperCertificates:$index SHA1 from provisioning profile"
    printf "%s\n" "$cert_sha1"
    found=1
    index=$((index + 1))
  done
  [[ "$found" -eq 1 ]] || fail "Provisioning profile has no DeveloperCertificates"
}
resolve_arch() {
@@ -109,7 +182,7 @@
  codesign --force \
    --options runtime \
    --timestamp \
    --sign "$APPSTORE_APP_IDENTITY" \
    --sign "$APPSTORE_APP_SIGN_IDENTITY" \
    "$item"
}
@@ -119,8 +192,16 @@
    --options runtime \
    --timestamp \
    --entitlements "$SIGNING_ENTITLEMENTS" \
    --sign "$APPSTORE_APP_IDENTITY" \
    --sign "$APPSTORE_APP_SIGN_IDENTITY" \
    "$item"
}
fix_binary_rpaths() {
  local binary="$1"
  # The sherpa-onnx macOS module injects its cache lib directory as an LC_RPATH
  # ahead of bundle Frameworks. MAS candidates must load bundled dylibs.
  install_name_tool -delete_rpath "$SHERPA_LIB_DIR" "$binary" 2>/dev/null || true
  install_name_tool -add_rpath @executable_path/../Frameworks "$binary" 2>/dev/null || true
}
plist_set_string() {
@@ -185,13 +266,13 @@
[[ -f "$INFO_PLIST" ]] || fail "Info.plist not found at $INFO_PLIST"
[[ -n "$BUNDLE_ID" ]] || fail "CFBundleIdentifier is missing from $INFO_PLIST"
[[ -f "$BASE_ENTITLEMENTS" ]] || fail "App Store entitlements not found at $BASE_ENTITLEMENTS"
[[ -f "$PRIVACY_MANIFEST" ]] || fail "PrivacyInfo.xcprivacy not found at $PRIVACY_MANIFEST"
[[ -f "$PROJECT_DIR/build/darwin/icon.icns" ]] || fail "icon.icns not found"
[[ -d "$SHERPA_LIB_DIR" ]] || fail "sherpa-onnx dylibs not found at $SHERPA_LIB_DIR"
ONNXRUNTIME_DYLIB="$(find "$SHERPA_LIB_DIR" -maxdepth 1 -type f -name 'libonnxruntime.*.dylib' | sort | tail -n 1)"
[[ -f "$ONNXRUNTIME_DYLIB" ]] || fail "onnxruntime dylib not found in $SHERPA_LIB_DIR"
ONNXRUNTIME_DYLIB_NAME="$(basename "$ONNXRUNTIME_DYLIB")"
security_find_code_identities | grep -Fq "$APPSTORE_APP_IDENTITY" ||
  fail "App Store app signing identity not found: $APPSTORE_APP_IDENTITY"
APPSTORE_APP_SIGN_IDENTITY="$(resolve_codesigning_identity_sha1 "$APPSTORE_APP_IDENTITY")"
security_find_installer_identities | grep -Fq "$APPSTORE_INSTALLER_IDENTITY" ||
  fail "App Store installer signing identity not found: $APPSTORE_INSTALLER_IDENTITY"
command -v productbuild >/dev/null || fail "productbuild not found"
@@ -205,10 +286,14 @@
PROFILE_APP_IDENTIFIER="$(/usr/libexec/PlistBuddy -c "Print :Entitlements:com.apple.application-identifier" "$PROFILE_PLIST" 2>/dev/null || true)"
PROFILE_TEAM_IDENTIFIER="$(/usr/libexec/PlistBuddy -c "Print :Entitlements:com.apple.developer.team-identifier" "$PROFILE_PLIST" 2>/dev/null || true)"
PROFILE_KEYCHAIN_GROUP="$(/usr/libexec/PlistBuddy -c "Print :Entitlements:keychain-access-groups:0" "$PROFILE_PLIST" 2>/dev/null || true)"
PROFILE_DEVELOPER_CERT_SHA1S="$(profile_developer_certificate_sha1s "$PROFILE_PLIST")"
PROFILE_BUNDLE_ID="${PROFILE_APP_IDENTIFIER#*.}"
[[ "$PROFILE_BUNDLE_ID" == "$BUNDLE_ID" ]] ||
  fail "Provisioning profile bundle ID mismatch: profile has $PROFILE_BUNDLE_ID, app has $BUNDLE_ID"
[[ -n "$PROFILE_TEAM_IDENTIFIER" ]] || fail "Provisioning profile missing com.apple.developer.team-identifier entitlement"
if ! grep -Fxq "$APPSTORE_APP_SIGN_IDENTITY" <<<"$PROFILE_DEVELOPER_CERT_SHA1S"; then
  fail "App Store app signing identity certificate mismatch: identity SHA1 $APPSTORE_APP_SIGN_IDENTITY is not present in provisioning profile DeveloperCertificates: $(tr '\n' ',' <<<"$PROFILE_DEVELOPER_CERT_SHA1S" | sed 's/,$//')"
fi
cp "$BASE_ENTITLEMENTS" "$SIGNING_ENTITLEMENTS"
plist_set_string "$SIGNING_ENTITLEMENTS" "com.apple.application-identifier" "$PROFILE_APP_IDENTIFIER"
@@ -236,7 +321,8 @@
  MACOSX_DEPLOYMENT_TARGET="$APPSTORE_MIN_SYSTEM_VERSION" \
  CGO_CFLAGS="${CGO_CFLAGS:-} -mmacosx-version-min=$APPSTORE_MIN_SYSTEM_VERSION" \
  CGO_LDFLAGS="${CGO_LDFLAGS:-} -mmacosx-version-min=$APPSTORE_MIN_SYSTEM_VERSION" \
  go build -tags appstore -buildvcs=false -gcflags=all="-l" -ldflags="-s -w" \
  go build -tags appstore -buildvcs=false -gcflags=all="-l" \
  -ldflags="-s -w -X main.appVersion=$VERSION -X main.appBuild=$BUILD_ID" \
  -o "$BUILD_DIR/$APP_NAME"
step "Assembling $APP_NAME.app"
@@ -245,11 +331,14 @@
mkdir -p "$APP_BUNDLE/Contents/Resources"
cp "$INFO_PLIST" "$APP_BUNDLE/Contents/Info.plist"
plist_set_string "$APP_BUNDLE/Contents/Info.plist" "CFBundleShortVersionString" "$VERSION"
plist_set_string "$APP_BUNDLE/Contents/Info.plist" "CFBundleVersion" "$BUILD_ID"
/usr/libexec/PlistBuddy -c "Set :LSMinimumSystemVersion $APPSTORE_MIN_SYSTEM_VERSION" \
  "$APP_BUNDLE/Contents/Info.plist"
cp "$APPSTORE_PROVISIONING_PROFILE" "$APP_BUNDLE/Contents/embedded.provisionprofile"
cp "$BUILD_DIR/$APP_NAME" "$APP_BUNDLE/Contents/MacOS/$APP_NAME"
cp "$PROJECT_DIR/build/darwin/icon.icns" "$APP_BUNDLE/Contents/Resources/icon.icns"
cp "$PRIVACY_MANIFEST" "$APP_BUNDLE/Contents/Resources/PrivacyInfo.xcprivacy"
find "$PROJECT_DIR/build/darwin" -maxdepth 1 -type d -name "*.lproj" \
  -exec cp -R {} "$APP_BUNDLE/Contents/Resources/" \;
cp "$SHERPA_LIB_DIR/libsherpa-onnx-c-api.dylib" "$APP_BUNDLE/Contents/Frameworks/"
@@ -264,6 +353,7 @@
step "Fixing rpaths"
install_name_tool -add_rpath @executable_path/../Frameworks \
  "$APP_BUNDLE/Contents/MacOS/$APP_NAME" 2>/dev/null || true
fix_binary_rpaths "$APP_BUNDLE/Contents/MacOS/$APP_NAME"
install_name_tool -id @rpath/libsherpa-onnx-c-api.dylib \
  "$APP_BUNDLE/Contents/Frameworks/libsherpa-onnx-c-api.dylib"
install_name_tool -id "@rpath/$ONNXRUNTIME_DYLIB_NAME" \
@@ -304,5 +394,5 @@
step "Mac App Store package complete"
echo "  App: $APP_BUNDLE"
echo "  PKG: $PKG_PATH"
echo "  App signing identity: $APPSTORE_APP_IDENTITY"
echo "  App signing identity: $APPSTORE_APP_IDENTITY ($APPSTORE_APP_SIGN_IDENTITY)"
echo "  Installer signing identity: $APPSTORE_INSTALLER_IDENTITY"