examples/ios/RunAnywhereAI/docs/RELEASE_INSTRUCTIONS.md
This guide covers iOS and macOS releases of the shared RunAnywhereAI Xcode
target. It prepares and validates local archives for App Store Connect. Upload
or submission is a separate, explicit action.
17.5 or later and macOS at 14.5 or later, matching
Package.swift.CURRENT_PROJECT_VERSION for every uploaded build. Update
MARKETING_VERSION only when publishing a new user-facing version.L86FH3K93L.RunAnywhereAI/App/RunAnywhereAIApp.swift owns the credential selection flow:
Resources/RunAnywhereLocalSecrets.plist.Release initialization fails loudly when no usable credentials exist. Verify the local plist and both required keys without printing their values:
SECRETS="RunAnywhereAI/Resources/RunAnywhereLocalSecrets.plist"
test -f "$SECRETS"
plutil -lint "$SECRETS"
/usr/libexec/PlistBuddy -c 'Print :apiKey' "$SECRETS" >/dev/null
/usr/libexec/PlistBuddy -c 'Print :baseURL' "$SECRETS" >/dev/null
The Release archive must contain both configuration files:
test -f "$APP/Contents/Resources/RunAnywhereLocalSecrets.plist" || \
test -f "$APP/RunAnywhereLocalSecrets.plist"
test -f "$APP/Contents/Resources/RunAnywhereConfig-Release.plist" || \
test -f "$APP/RunAnywhereConfig-Release.plist"
From examples/ios/RunAnywhereAI/:
PROJECT="RunAnywhereAI.xcodeproj"
SCHEME="RunAnywhereAI"
xcodebuild -project "$PROJECT" -scheme "$SCHEME" \
-configuration Release -showBuildSettings \
| rg 'MARKETING_VERSION|CURRENT_PROJECT_VERSION|IPHONEOS_DEPLOYMENT_TARGET|MACOSX_DEPLOYMENT_TARGET'
Confirm:
IPHONEOS_DEPLOYMENT_TARGET is 17.5.MACOSX_DEPLOYMENT_TARGET is 14.5.Apple accepts one to ten screenshots per device family. Screenshots must show the real app experience and use an accepted pixel size. Confirm current values in Apple's screenshot specification.
Recommended master sizes for this app:
| Platform | Orientation | Master size |
|---|---|---|
| iPhone 6.9-inch | Portrait | 1320x2868 |
| macOS | Landscape, 16:10 | 2880x1800 |
Use sRGB PNG or JPEG without transparency. Keep the real UI as the dominant content. Branded backgrounds and short factual captions are acceptable, but do not imply that a capability was tested when it was not.
For the July 2026 release capture, the prepared assets are under:
build/screenshots/app-store-2026-07-09/
ios-6.9/ # raw iPhone Simulator captures
ios-6.9-voice-refresh/ # tested llama.cpp and ONNX/Sherpa captures
ios-marketing-6.9-voice/ # recommended six-image 1320x2868 iPhone set
ios-marketing-6.9/ # previous generic iPhone set
macos-raw/ # raw macOS window captures
macos-marketing/ # five branded 2880x1800 screenshots
contact-sheets/ # review overviews; do not upload these
The recommended iPhone set uses real simulator evidence from llama.cpp LFM2 350M, Sherpa-ONNX Whisper Tiny, and Piper TTS. MLX may be mentioned elsewhere as a supported runtime, but do not present it as tested evidence unless it is separately verified for that build.
The iOS archive consumes immutable XCFrameworks whose metadata already declares
the canonical MinimumOSVersion of 17.5.
JOBS="$(sysctl -n hw.logicalcpu)"
# 1. Build the final Release inputs.
xcodebuild \
-project RunAnywhereAI.xcodeproj \
-scheme RunAnywhereAI \
-configuration Release \
-destination 'generic/platform=iOS' \
-skipPackagePluginValidation \
-jobs "$JOBS" \
build
# 2. Archive into Xcode Organizer's standard folder.
ARCHIVE_DIR="$HOME/Library/Developer/Xcode/Archives/$(date +%Y-%m-%d)"
ARCHIVE="$ARCHIVE_DIR/RunAnywhereAI iOS $(date +%Y-%m-%d\ %H.%M.%S).xcarchive"
mkdir -p "$ARCHIVE_DIR"
xcodebuild \
-project RunAnywhereAI.xcodeproj \
-scheme RunAnywhereAI \
-configuration Release \
-destination 'generic/platform=iOS' \
-archivePath "$ARCHIVE" \
-allowProvisioningUpdates \
-skipPackagePluginValidation \
-jobs "$JOBS" \
archive
open -a Xcode "$ARCHIVE"
The Mac App Store build must include App Sandbox, Hardened Runtime, the app
privacy manifest, and the production configuration. The project supplies these
through RunAnywhereAI.entitlements, Release build settings, and
PrivacyInfo.xcprivacy.
JOBS="$(sysctl -n hw.logicalcpu)"
ARCHIVE_DIR="$HOME/Library/Developer/Xcode/Archives/$(date +%Y-%m-%d)"
ARCHIVE="$ARCHIVE_DIR/RunAnywhereAI macOS $(date +%Y-%m-%d\ %H.%M.%S).xcarchive"
mkdir -p "$ARCHIVE_DIR"
xcodebuild \
-project RunAnywhereAI.xcodeproj \
-scheme RunAnywhereAI \
-configuration Release \
-destination 'generic/platform=macOS' \
-archivePath "$ARCHIVE" \
-allowProvisioningUpdates \
-skipPackagePluginValidation \
-jobs "$JOBS" \
archive
open -a Xcode "$ARCHIVE"
An archive stored elsewhere may not appear automatically in Organizer. Put it
under ~/Library/Developer/Xcode/Archives/YYYY-MM-DD/ or open the .xcarchive
directly with Xcode.
Set ARCHIVE to the new archive, then locate the app:
APP="$ARCHIVE/Products/Applications/RunAnywhereAI.app"
BIN="$APP/Contents/MacOS/RunAnywhereAI" # macOS
# BIN="$APP/RunAnywhereAI" # iOS
test -d "$APP"
codesign --verify --deep --strict --verbose=2 "$APP"
lipo -archs "$BIN"
test -f "$APP/Contents/Resources/PrivacyInfo.xcprivacy" || \
test -f "$APP/PrivacyInfo.xcprivacy"
test -f "$APP/Contents/Resources/RunAnywhereLocalSecrets.plist" || \
test -f "$APP/RunAnywhereLocalSecrets.plist"
test -f "$APP/Contents/Resources/RunAnywhereConfig-Release.plist" || \
test -f "$APP/RunAnywhereConfig-Release.plist"
test ! -e "$APP/Contents/Resources/RunAnywhereExportedSymbols.txt"
test ! -e "$APP/RunAnywhereExportedSymbols.txt"
For macOS, verify sandbox and Hardened Runtime without changing the signature:
codesign -d --entitlements :- "$APP" 2>/dev/null \
| plutil -p - \
| rg 'app-sandbox|application-groups|camera|microphone|network.client|files.user-selected'
codesign -dvvv "$APP" 2>&1 | rg 'flags=.*runtime'
! xattr -p com.apple.quarantine "$APP" >/dev/null 2>&1
Expected macOS entitlements include App Sandbox, the RunAnywhere app group,
camera, microphone, outbound network, and user-selected file access. A locally
created development archive can contain get-task-allow; the App Store export
must be distribution-signed and must not retain it.
The linked binary must export every C symbol referenced by the Swift SDK. Failure here causes startup errors such as:
Native proto ABI is not exported by the linked RACommons binary: rac_sdk_init_phase1_proto
Run this against either the iOS or macOS archived binary. The expected set is derived from the products actually linked on that platform: iOS links core, llama.cpp, ONNX/Sherpa, and MLX; macOS currently links core and MLX.
nm -gjU "$BIN" 2>/dev/null \
| rg '^_(rac|ra_mlx)_' \
| sed 's/^_//' \
| sort -u > /tmp/runanywhere_archive_exported_symbols.txt
if [[ "$BIN" == */Contents/MacOS/* ]]; then
SRC_DIRS=(
../../../sdk/runanywhere-swift/Sources/RunAnywhere
../../../sdk/runanywhere-swift/Sources/MLXRuntime
)
REQUIRED_SYMBOLS=(
rac_proto_buffer_free
rac_backend_mlx_register
rac_backend_mlx_unregister
rac_mlx_set_callbacks
ra_mlx_register_runtime
ra_mlx_runtime_is_available
ra_mlx_runtime_is_registered
ra_mlx_unregister_runtime
)
else
SRC_DIRS=(
../../../sdk/runanywhere-swift/Sources/RunAnywhere
../../../sdk/runanywhere-swift/Sources/LlamaCPPRuntime
../../../sdk/runanywhere-swift/Sources/ONNXRuntime
../../../sdk/runanywhere-swift/Sources/MLXRuntime
)
REQUIRED_SYMBOLS=(
rac_proto_buffer_free
rac_backend_llamacpp_register
rac_backend_llamacpp_unregister
rac_backend_onnx_register
rac_backend_onnx_unregister
rac_plugin_entry_sherpa
rac_plugin_register
rac_plugin_unregister
rac_backend_mlx_register
rac_backend_mlx_unregister
rac_mlx_set_callbacks
ra_mlx_register_runtime
ra_mlx_runtime_is_available
ra_mlx_runtime_is_registered
ra_mlx_unregister_runtime
)
fi
rg -No '"(rac|ra_mlx)_[A-Za-z0-9_]+"' "${SRC_DIRS[@]}" --glob '*.swift' \
| perl -ne 'while (/"((?:rac|ra_mlx)_[A-Za-z0-9_]+)"/g) { print "$1\n" }' \
| sort -u > /tmp/runanywhere_expected_swift_native_symbols.from_strings
{
cat /tmp/runanywhere_expected_swift_native_symbols.from_strings
printf '%s\n' "${REQUIRED_SYMBOLS[@]}"
} | sort -u > /tmp/runanywhere_expected_swift_native_symbols.txt
comm -23 \
/tmp/runanywhere_expected_swift_native_symbols.txt \
/tmp/runanywhere_archive_exported_symbols.txt \
> /tmp/runanywhere_missing_swift_native_symbols.txt
test ! -s /tmp/runanywhere_missing_swift_native_symbols.txt
The final command must pass. If it fails, rebuild the native XCFrameworks and fix the Release linker/export settings before uploading.
Command-line export is optional and still does not upload:
xcodebuild -exportArchive \
-archivePath "$ARCHIVE" \
-exportPath "../../../build/archives/$(basename "$ARCHIVE" .xcarchive)-export" \
-exportOptionsPlist "../../../build/archives/ExportOptions-app-store-connect.plist" \
-allowProvisioningUpdates
Confirm the archive is under Xcode's standard folder and open it directly:
find "$HOME/Library/Developer/Xcode/Archives" -name '*.xcarchive' -maxdepth 3 -print
open -a Xcode "$ARCHIVE"
Rebuild the canonical XCFrameworks; do not mutate DerivedData. Confirm the app and every embedded framework declare the expected deployment floor.
Do not retry or upload the same archive. Run the native ABI gate, rebuild the
XCFrameworks, and confirm the Release target still uses -all_load, the
exported-symbols list, and STRIP_STYLE = non-global.
Confirm the Apple Developer account can manage signing and has a valid Apple
Distribution certificate and App Store provisioning profile for
com.runanywhere.RunAnywhere. A development-signed archive is sufficient for
local validation but not for the final App Store export.
[ ] Marketing version and build number are correct
[ ] Production secrets and Release config are present without being printed
[ ] Release build succeeds at iOS 17.5
[ ] Every packaged framework declares `MinimumOSVersion = 17.5`
[ ] Archive appears in Organizer
[ ] Native ABI gate reports zero missing symbols
[ ] 1320x2868 screenshots are reviewed in upload order
[ ] Validate App passes before upload
[ ] Marketing version and build number are correct
[ ] Production secrets and Release config are present without being printed
[ ] Release build succeeds at macOS 14.5
[ ] App Sandbox, required entitlements, and Hardened Runtime are present
[ ] PrivacyInfo.xcprivacy is bundled
[ ] Archive appears in Organizer
[ ] codesign, architecture, quarantine, and native ABI checks pass
[ ] 2880x1800 screenshots are reviewed in upload order
[ ] App Store Connect Validate App passes before upload