207 lines · 6.8 KB · Text
RawDownload
#!/usr/bin/env bash set -euo pipefail usage() {  echo "Usage: $0 [--release] [--device [name-or-udid]] [--identity identity] [simulator]"  echo ""  echo "Builds the gpui_ios todos example, assembles an app bundle, and installs"  echo "and launches it on a simulator (default) or a connected physical device."  echo ""  echo "Arguments:"  echo "  --release    Build the example in release mode"  echo "  --device     Run on a physical device instead of a simulator. Takes an"  echo "               optional devicectl device name or UDID; without one, the"  echo "               single connected device is used"  echo "  --identity   Codesigning identity for device builds (defaults to the"  echo "               first 'Apple Development' identity in the keychain)"  echo "  simulator    Simulator device name or UDID (default: iPhone 17 Pro)"  exit 1} profile=debugcargo_flags=()run_on=simulatorsimulator="iPhone 17 Pro"device=""identity="" while [[ $# -gt 0 ]]; do  case "$1" in  --release)    profile=release    cargo_flags+=(--release)    ;;  --device)    run_on=device    if [[ $# -gt 1 && "$2" != -* ]]; then      device="$2"      shift    fi    ;;  --identity)    [[ $# -gt 1 ]] || usage    identity="$2"    shift    ;;  -h | --help)    usage    ;;  *)    simulator="$1"    ;;  esac  shiftdone bundle_id=dev.zed.gpui.todos if [[ "$run_on" == device ]]; then  target=aarch64-apple-ios  supported_platform=iPhoneOSelse  target=aarch64-apple-ios-sim  supported_platform=iPhoneSimulatorfi cargo build -p gpui_ios --example todos --target "$target" "${cargo_flags[@]+"${cargo_flags[@]}"}" target_dir="target/$target/$profile"app_dir="$target_dir/Todos.app"rm -rf "$app_dir"mkdir -p "$app_dir"cp "$target_dir/examples/todos" "$app_dir/todos" cat >"$app_dir/Info.plist" <<PLIST<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict>    <key>CFBundleExecutable</key>    <string>todos</string>    <key>CFBundleIdentifier</key>    <string>$bundle_id</string>    <key>CFBundleName</key>    <string>Todos</string>    <key>CFBundleDisplayName</key>    <string>Todos</string>    <key>CFBundlePackageType</key>    <string>APPL</string>    <key>CFBundleVersion</key>    <string>1</string>    <key>CFBundleShortVersionString</key>    <string>1.0</string>    <key>MinimumOSVersion</key>    <string>17.0</string>    <key>UIDeviceFamily</key>    <array>        <integer>1</integer>        <integer>2</integer>    </array>    <key>CFBundleSupportedPlatforms</key>    <array>        <string>$supported_platform</string>    </array>    <key>UILaunchScreen</key>    <dict/></dict></plist>PLIST if [[ "$run_on" == simulator ]]; then  if [[ "$simulator" =~ ^[0-9A-Fa-f-]{36}$ ]]; then    udid="$simulator"  else    udid=$(xcrun simctl list devices available | grep -F "$simulator (" | head -1 | sed -E 's/.*\(([0-9A-Fa-f-]{36})\).*/\1/')    if [[ -z "$udid" ]]; then      echo "error: no available simulator device named '$simulator'" >&2      exit 1    fi  fi   if ! xcrun simctl list devices | grep -F "$udid" | grep -q Booted; then    xcrun simctl boot "$udid"  fi  xcrun simctl bootstatus "$udid" -b   xcrun simctl install "$udid" "$app_dir"  xcrun simctl launch --terminate-running-process "$udid" "$bundle_id"  exit 0fi # Device mode: sign the bundle with a development provisioning profile, then# install and launch it with devicectl. if [[ -z "$device" ]]; then  device_identifiers=$(xcrun devicectl list devices | grep -oE '[0-9A-Fa-f]{8}(-[0-9A-Fa-f]{4}){3}-[0-9A-Fa-f]{12}' || true)  if [[ -z "$device_identifiers" ]]; then    echo "error: no paired devices found by 'xcrun devicectl list devices'" >&2    exit 1  fi  if [[ $(wc -l <<<"$device_identifiers") -gt 1 ]]; then    echo "error: multiple paired devices; pass one with --device <name-or-udid>:" >&2    xcrun devicectl list devices >&2    exit 1  fi  device="$device_identifiers"fi if [[ -z "$identity" ]]; then  identity=$(security find-identity -v -p codesigning | grep -F "Apple Development" | head -1 | awk '{print $2}')  if [[ -z "$identity" ]]; then    echo "error: no 'Apple Development' codesigning identity in the keychain;" >&2    echo "pass one with --identity <name-or-hash>" >&2    exit 1  fifi # Find the newest non-expired development provisioning profile covering the# bundle ID. The application-identifier entitlement is "<prefix>.<app ID>"# where the app ID is either the explicit bundle ID or a wildcard ("*").provisioning_profile=""provisioning_profile_creation=""provisioning_profile_prefix=""now=$(date -u +%Y-%m-%dT%H:%M:%SZ)for profile_path in \  "$HOME/Library/Developer/Xcode/UserData/Provisioning Profiles"/*.mobileprovision \  "$HOME/Library/MobileDevice/Provisioning Profiles"/*.mobileprovision; do  [[ -f "$profile_path" ]] || continue  decoded=$(security cms -D -i "$profile_path")  application_identifier=$(plutil -extract Entitlements.application-identifier raw -o - - <<<"$decoded" 2>/dev/null || true)  prefix="${application_identifier%%.*}"  app_id="${application_identifier#*.}"  [[ "$app_id" == "$bundle_id" || "$app_id" == "*" ]] || continue  expiration=$(plutil -extract ExpirationDate raw -o - - <<<"$decoded")  [[ "$expiration" > "$now" ]] || continue  creation=$(plutil -extract CreationDate raw -o - - <<<"$decoded")  if [[ -z "$provisioning_profile" || "$creation" > "$provisioning_profile_creation" ]]; then    provisioning_profile="$profile_path"    provisioning_profile_creation="$creation"    provisioning_profile_prefix="$prefix"  fidone if [[ -z "$provisioning_profile" ]]; then  echo "error: no valid provisioning profile for '$bundle_id' found in" >&2  echo "  ~/Library/Developer/Xcode/UserData/Provisioning Profiles/" >&2  echo "  ~/Library/MobileDevice/Provisioning Profiles/" >&2  echo "Build any Xcode app project with that bundle ID for 'generic/platform=iOS'" >&2  echo "with -allowProvisioningUpdates once (signed into your team in Xcode) to" >&2  echo "register the device and download a development profile." >&2  exit 1fi cp "$provisioning_profile" "$app_dir/embedded.mobileprovision" entitlements_path=$(mktemp -t todos_entitlements)security cms -D -i "$provisioning_profile" |  plutil -extract Entitlements xml1 -o "$entitlements_path" -# Wildcard profiles carry "<prefix>.*"; the signed app must claim the concrete# application-identifier the wildcard authorizes.plutil -replace application-identifier -string "$provisioning_profile_prefix.$bundle_id" "$entitlements_path" codesign --force --sign "$identity" --entitlements "$entitlements_path" --timestamp=none "$app_dir"rm -f "$entitlements_path" xcrun devicectl device install app --device "$device" "$app_dir"xcrun devicectl device process launch --terminate-existing --device "$device" "$bundle_id"