#!/bin/bash # ======================================== # MiniPlayer iOS 打包脚本 # 生成 .ipa (需要签名配置) # ======================================== set -e SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" APP_NAME="MiniPlayer" VERSION=$(date +%Y.%m.%d) BUILD_DIR="$PROJECT_DIR/.build-ios" # 签名配置 TEAM_ID="${IOS_TEAM_ID:-LR8YT5M53U}" BUNDLE_ID="com.miniplayer.ios" PROVISIONING_PROFILE="${IOS_PROVISIONING_PROFILE:-}" # 留空用 automatic signing EXPORT_METHOD="development" # development / ad-hoc / app-store echo "=== MiniPlayer iOS 打包 ===" echo "项目目录: $PROJECT_DIR" echo "版本: $VERSION" echo "Team ID: $TEAM_ID" # 1. 生成 Xcode 项目 echo "" echo "--- Step 1: 生成 Xcode 项目 ---" cd "$PROJECT_DIR" cat > project.yml << EOF name: MiniPlayer options: bundleIdPrefix: com.miniplayer deploymentTarget: iOS: "17.0" xcodeVersion: "15.0" generateEmptyDirectories: true packages: SwiftBricks: path: ../swiftbricks StreamRecorder: path: ../StreamRecorder targets: MiniPlayer: type: application platform: iOS sources: - path: Sources excludes: - "**/PlayerRecorder.swift" dependencies: - package: SwiftBricks - package: StreamRecorder product: StreamRecorderKit settings: base: PRODUCT_BUNDLE_IDENTIFIER: $BUNDLE_ID MARKETING_VERSION: $VERSION CURRENT_PROJECT_VERSION: 1 INFOPLIST_KEY_CFBundleDisplayName: "MiniPlayer" INFOPLIST_KEY_UIApplicationSceneManifest_Generation: true INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents: true INFOPLIST_KEY_UILaunchScreen_Generation: true INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad: "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight" INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone: "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight" SWIFT_VERSION: "5.9" CODE_SIGN_STYLE: Automatic DEVELOPMENT_TEAM: $TEAM_ID GENERATE_INFOPLIST_FILE: YES ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon resources: - path: Sources/Resources EOF if command -v xcodegen &> /dev/null; then xcodegen generate echo " ✓ Xcode 项目生成成功" else echo " ⚠ xcodegen 未安装,使用 xcodebuild + SPM 模式" rm -f project.yml fi # 2. Archive echo "" echo "--- Step 2: Archive ---" if [ -f "$PROJECT_DIR/MiniPlayer.xcodeproj/project.pbxproj" ]; then # 使用 xcodegen 生成的项目 SCHEME="MiniPlayer" PROJECT_FLAG="-project $PROJECT_DIR/MiniPlayer.xcodeproj" else # 使用 SPM 自动生成的项目 SCHEME="MiniPlayeriOS" PROJECT_FLAG="" fi ARCHIVE_PATH="$BUILD_DIR/$APP_NAME.xcarchive" mkdir -p "$BUILD_DIR" xcodebuild archive \ $PROJECT_FLAG \ -scheme "$SCHEME" \ -destination "generic/platform=iOS" \ -archivePath "$ARCHIVE_PATH" \ -allowProvisioningUpdates \ 2>&1 | tail -30 ARCHIVE_EXIT=${PIPESTATUS[0]} if [ $ARCHIVE_EXIT -ne 0 ]; then echo " ✗ Archive 失败 (exit code: $ARCHIVE_EXIT)" echo " 提示: 确保 Team ID 和签名配置正确" exit 1 fi echo " ✓ Archive 完成" # 3. Export .ipa echo "" echo "--- Step 3: 导出 .ipa ---" # 生成 ExportOptions.plist cat > "$BUILD_DIR/ExportOptions.plist" << EOF method $EXPORT_METHOD teamID $TEAM_ID compileBitcode stripSwiftSymbols thinning <none> EOF IPA_OUTPUT="$BUILD_DIR/ipa" mkdir -p "$IPA_OUTPUT" xcodebuild -exportArchive \ -archivePath "$ARCHIVE_PATH" \ -exportPath "$IPA_OUTPUT" \ -exportOptionsPlist "$BUILD_DIR/ExportOptions.plist" \ -allowProvisioningUpdates \ 2>&1 | tail -10 IPA_FILE=$(find "$IPA_OUTPUT" -name "*.ipa" -type f | head -1) if [ -n "$IPA_FILE" ]; then # 复制到项目根目录(Finder/Xcode Add App 弹窗可见) cp "$IPA_FILE" "$PROJECT_DIR/$APP_NAME.ipa" echo "" echo "==============================" echo " iOS 打包完成!" echo "==============================" echo " .ipa: $PROJECT_DIR/$APP_NAME.ipa" echo " 大小: $(du -h "$PROJECT_DIR/$APP_NAME.ipa" | cut -f1)" echo "" echo " 安装方式:" echo " - Xcode: Window > Devices > Add App → 选择项目根目录下的 .ipa" echo " - AltStore / SideStore: 直接导入 .ipa" echo " - TestFlight: 使用 app-store 签名方式" else echo " ✗ .ipa 导出失败" echo " 提示: 检查签名配置和 ExportOptions.plist" fi # 清理临时文件 rm -f "$PROJECT_DIR/project.yml"