194 lines
6.9 KiB
Bash
Executable File
194 lines
6.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Chanora iOS build helper.
|
|
#
|
|
# Run this on a macOS host that has already completed §4 of
|
|
# docs/release/ios-build.md:
|
|
# - Xcode 26+ with Command Line Tools
|
|
# - Rust stable with aarch64-apple-ios, aarch64-apple-ios-sim,
|
|
# x86_64-apple-ios targets
|
|
# - Flutter 3.41.9 stable on PATH
|
|
# - CocoaPods on PATH
|
|
# - Pre-built libopus.a for each iOS arch (the script in §4.3 of the
|
|
# docs leaves them in /tmp/opus-ios-<arch>-wrap/lib/libopus.a)
|
|
#
|
|
# Usage (from the repo root ~/chanora):
|
|
# ./tools/build-ios.sh
|
|
# ./tools/build-ios.sh --no-codesign # unsigned Runner.app only
|
|
# ./tools/build-ios.sh --regenerate-bindings # rerun FRB codegen first
|
|
# ./tools/build-ios.sh --version v0.2.0-beta.1
|
|
#
|
|
# Produces:
|
|
# target/aarch64-apple-ios/release/libchanora_bridge.a
|
|
# target/aarch64-apple-ios-sim/release/libchanora_bridge.a
|
|
# target/x86_64-apple-ios/release/libchanora_bridge.a
|
|
# target/universal-ios-sim/libchanora_bridge.a
|
|
# target/ChanoraBridge.xcframework/
|
|
# apps/chanora_flutter/build/ios/iphoneos/Runner.app/
|
|
# apps/chanora_flutter/build/ios/ipa/chanora_flutter.ipa (if signed)
|
|
# chanora-<version>-ios.ipa (renamed copy)
|
|
|
|
set -euo pipefail
|
|
|
|
VERSION="v0.2.0-beta.1"
|
|
SKIP_CODESIGN=0
|
|
REGEN=0
|
|
EXPORT_METHOD="development"
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--version) VERSION="$2"; shift 2;;
|
|
--no-codesign) SKIP_CODESIGN=1; shift;;
|
|
--regenerate-bindings) REGEN=1; shift;;
|
|
--export-method) EXPORT_METHOD="$2"; shift 2;;
|
|
*) echo "unknown arg: $1" >&2; exit 2;;
|
|
esac
|
|
done
|
|
|
|
cd "$(dirname "$0")/.."
|
|
REPO_ROOT="$(pwd)"
|
|
|
|
bar() { printf '%s\n' '========================================================================'; }
|
|
|
|
bar
|
|
echo "Chanora iOS build"
|
|
echo "Repo root : $REPO_ROOT"
|
|
echo "Version : $VERSION"
|
|
echo "Sign : $([ "$SKIP_CODESIGN" = 1 ] && echo no || echo "yes (export-method=$EXPORT_METHOD)")"
|
|
bar
|
|
|
|
# ---------- 1. Verify toolchain ----------
|
|
echo "[1/7] Verify toolchain"
|
|
for cmd in xcodebuild xcrun cargo rustc flutter pod lipo; do
|
|
if ! command -v "$cmd" >/dev/null; then
|
|
echo " ERROR: '$cmd' not on PATH. See docs/release/ios-build.md §4." >&2
|
|
exit 1
|
|
fi
|
|
printf " %-10s : %s\n" "$cmd" "$($cmd --version 2>&1 | head -1)"
|
|
done
|
|
|
|
# Verify the three Rust iOS targets are installed.
|
|
for tgt in aarch64-apple-ios aarch64-apple-ios-sim x86_64-apple-ios; do
|
|
if ! rustup target list --installed | grep -q "^$tgt$"; then
|
|
echo " Adding rustup target $tgt..."
|
|
rustup target add "$tgt"
|
|
fi
|
|
done
|
|
|
|
# Verify the pre-built libopus.a for each arch is available.
|
|
for arch in arm64 arm64-simulator x86_64; do
|
|
if [[ ! -f "/tmp/opus-ios-${arch}-wrap/lib/libopus.a" ]]; then
|
|
echo " ERROR: /tmp/opus-ios-${arch}-wrap/lib/libopus.a not found." >&2
|
|
echo " See §4.3 of docs/release/ios-build.md to build libopus first." >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# ---------- 2. (Optional) regenerate FRB bindings ----------
|
|
if [[ $REGEN -eq 1 ]]; then
|
|
echo "[2/7] Regenerate flutter_rust_bridge bindings"
|
|
if ! command -v flutter_rust_bridge_codegen >/dev/null; then
|
|
echo " flutter_rust_bridge_codegen not on PATH; cargo install it first." >&2
|
|
exit 1
|
|
fi
|
|
flutter_rust_bridge_codegen generate
|
|
else
|
|
echo "[2/7] Skipping FRB codegen (use --regenerate-bindings if api.rs changed)"
|
|
fi
|
|
|
|
# ---------- 3. Add ios/ platform folder if missing ----------
|
|
FLUTTER_APP="$REPO_ROOT/apps/chanora_flutter"
|
|
if [[ ! -d "$FLUTTER_APP/ios" ]]; then
|
|
echo "[3/7] Add iOS platform to apps/chanora_flutter"
|
|
(cd "$FLUTTER_APP" && flutter create --platforms=ios .)
|
|
echo " NOTE: edit ios/Podfile to pin platform :ios, '13.0' (DEC-003)"
|
|
echo " NOTE: edit ios/Runner/Info.plist to add NSMicrophoneUsageDescription"
|
|
echo " NOTE: set Team + Bundle Identifier in Xcode Signing & Capabilities"
|
|
else
|
|
echo "[3/7] iOS platform already present in apps/chanora_flutter"
|
|
fi
|
|
|
|
# ---------- 4. Build Rust libs for the three iOS triples ----------
|
|
echo "[4/7] Build Rust libs for iOS"
|
|
export LIBOPUS_STATIC=1
|
|
export LIBOPUS_NO_PKG=1
|
|
|
|
build_one() {
|
|
local TARGET=$1
|
|
local OPUS_DIR=$2
|
|
echo " -> $TARGET"
|
|
export LIBOPUS_LIB_DIR="$OPUS_DIR"
|
|
export CMAKE_POLICY_VERSION_MINIMUM=3.5
|
|
export IPHONEOS_DEPLOYMENT_TARGET=13.0
|
|
rm -rf "target/$TARGET/release/build/audiopus_sys-"*
|
|
cargo build --release --target "$TARGET" -p chanora_bridge
|
|
}
|
|
|
|
build_one aarch64-apple-ios /tmp/opus-ios-arm64-wrap
|
|
build_one aarch64-apple-ios-sim /tmp/opus-ios-arm64-simulator-wrap
|
|
build_one x86_64-apple-ios /tmp/opus-ios-x86_64-wrap
|
|
|
|
# ---------- 5. lipo + xcodebuild -create-xcframework ----------
|
|
echo "[5/7] lipo simulator libs + create XCFramework"
|
|
mkdir -p target/universal-ios-sim
|
|
lipo -create \
|
|
target/aarch64-apple-ios-sim/release/libchanora_bridge.a \
|
|
target/x86_64-apple-ios/release/libchanora_bridge.a \
|
|
-output target/universal-ios-sim/libchanora_bridge.a
|
|
echo " Universal sim: $(file target/universal-ios-sim/libchanora_bridge.a)"
|
|
|
|
rm -rf target/ChanoraBridge.xcframework
|
|
xcodebuild -create-xcframework \
|
|
-library target/aarch64-apple-ios/release/libchanora_bridge.a \
|
|
-library target/universal-ios-sim/libchanora_bridge.a \
|
|
-output target/ChanoraBridge.xcframework
|
|
echo " XCFramework at: $REPO_ROOT/target/ChanoraBridge.xcframework"
|
|
|
|
# ---------- 6. flutter build ios / ipa ----------
|
|
echo "[6/7] flutter pub get + pod install + flutter build"
|
|
cd "$FLUTTER_APP"
|
|
flutter pub get
|
|
(cd ios && pod install)
|
|
|
|
if [[ $SKIP_CODESIGN -eq 1 ]]; then
|
|
flutter build ios --release --no-codesign
|
|
APP_PATH="$FLUTTER_APP/build/ios/iphoneos/Runner.app"
|
|
echo " Unsigned .app: $APP_PATH"
|
|
else
|
|
flutter build ipa --release --export-method "$EXPORT_METHOD"
|
|
IPA_PATH="$FLUTTER_APP/build/ios/ipa/chanora_flutter.ipa"
|
|
if [[ ! -f "$IPA_PATH" ]]; then
|
|
echo " ERROR: expected $IPA_PATH, did not find one." >&2
|
|
ls -la "$FLUTTER_APP/build/ios/ipa/" 2>/dev/null || true
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# ---------- 7. Rename signed ipa, print final paths ----------
|
|
echo "[7/7] Package release artefact"
|
|
cd "$REPO_ROOT"
|
|
FINAL_IPA="$HOME/chanora-$VERSION-ios.ipa"
|
|
if [[ $SKIP_CODESIGN -ne 1 ]]; then
|
|
cp "$FLUTTER_APP/build/ios/ipa/chanora_flutter.ipa" "$FINAL_IPA"
|
|
shasum -a 256 "$FINAL_IPA"
|
|
fi
|
|
|
|
bar
|
|
echo "iOS build complete."
|
|
bar
|
|
echo "Artefacts:"
|
|
echo " Rust libs:"
|
|
echo " target/aarch64-apple-ios/release/libchanora_bridge.a"
|
|
echo " target/aarch64-apple-ios-sim/release/libchanora_bridge.a"
|
|
echo " target/x86_64-apple-ios/release/libchanora_bridge.a"
|
|
echo " target/universal-ios-sim/libchanora_bridge.a"
|
|
echo " XCFramework:"
|
|
echo " target/ChanoraBridge.xcframework/"
|
|
if [[ $SKIP_CODESIGN -eq 1 ]]; then
|
|
echo " Unsigned app bundle:"
|
|
echo " apps/chanora_flutter/build/ios/iphoneos/Runner.app/"
|
|
else
|
|
echo " Signed .ipa:"
|
|
echo " apps/chanora_flutter/build/ios/ipa/chanora_flutter.ipa"
|
|
echo " $FINAL_IPA"
|
|
fi
|