前言
我以往的工作经验主要是基于Android平台进行应用开发,Android平台的APK打包流程主要依赖于Gradle实现编译Debug/Release包,通过配置项目下的build.gradle.kts
文件,可以很方便的完成打包和签名的操作。
Android打包依赖于gradle
构建工具:
- Debug打包
./gradlew assembleDebug
: 编译Debug包,一般使用debug.keystore
(Android Debug包签名密钥)进行签名./gradlew bundleDebug
: 编译Bundle包,一般用于Google Play应用商店的包发布
- Release打包
./gradlew assembleRelease
: 编译Release包,一般使用relese.jks
(自行生成的签名密钥)进行签名./gradlew bundleRelease
: 编译Bundle的Release签名包,一般用于正式版本的发布
iOS打包依赖于xcodebuild
构建工具:
xcodebuild build
编译项目生成可执行的.app
文件(可用于编译检查、本地调试) -> 类似 Android 的./gradlew build
构建生成Debug包之类的xcodebuild archive
+-configuration Debug
或-configuration Release
生成归档文件iosApp.xcarchive
-> 类似 Android 的./gradlew assembleDebug
或者./gradlew assembleRelease
生成.apk
包xcodebuild -exportArchive
将iosApp.xcarchive
导出为.ipa
文件并签名(通过配置ExportOptions.plist
) -> 类似 Android 的.apk
或.aab
的安装包
xcodebuild
与 gradle
指令对比:
功能描述 | xcodebuild 指令 |
gradlew 指令 |
说明 |
---|---|---|---|
清理构建 | xcodebuild clean |
./gradlew clean |
清除之前的构建产物 |
构建调试版 | xcodebuild -configuration Debug |
./gradlew assembleDebug |
构建用于调试的版本 |
构建发布版 | xcodebuild -configuration Release |
./gradlew assembleRelease |
构建用于发布的版本 |
生成归档文件 | xcodebuild archive -archivePath <path> |
./gradlew bundleRelease |
iOS生成xcarchive ,Android生成aab |
运行测试 | xcodebuild test |
./gradlew test |
执行单元测试 |
构建并安装 | xcodebuild install |
./gradlew installDebug |
构建并安装到设备 |
查看依赖 | xcodebuild -list |
./gradlew dependencies |
查看项目依赖信息 |
检查签名 | codesign --verify --deep --verbose=4 example.app 或 codesign --display -vvv example.app |
./gradlew signingReport |
验证签名信息 |
如果你刚好有一些Android的开发工作经验,对比上图基本上就能搞清楚iOS构建工具的使用了,虽然很相似,其实也差不多。
下面的内容主要是关于 iOS 应用编译的一些指令的说明,如果你看完上面的内容并且理解了,就可以直接基于实际的项目进行实践测试。毕竟实践出真知,每个人的环境都不一样~
xcodebuild 相关指令
列出iOS应用构建信息
主要功能
- 解析项目的 Swift Package 依赖(显示在 Resolved source packages 部分)
- 列出工作区所有可用 Scheme(显示在 Information about workspace 部分)
对于iOS项目,可以运行以下命令(如果应用更复杂且使用工作区,只需将 -project
替换为 -workspace <project>.xcworkspace
即可):
示例展示
执行之后的结果如下:
以上是使用xcodebuild -list -project iosApp.xcodeproj
的执行输出结果,下面我们来试一下使用iosApp.xcworkspace
为目标来执行以下指令
执行之后的结果如下:
可以看到这两个指令得到的结果是一致的,这个指令可以用于在CI的流程中获取当前项目的引入的包依赖及版本信息
关于以上输出内容,可以查看下面的技术分析
技术分析
以下是 xcodebuild -list
命令输出的详细技术解析,按模块分类说明:
- 命令核心作用
执行的 xcodebuild -list -project iosApp.xcodeproj
和 xcodebuild -list -workspace iosApp.xcworkspace
主要完成两个任务:
- 解析项目的 Swift Package 依赖(显示在
Resolved source packages
部分) - 列出工作区所有可用 Scheme(显示在
Information about workspace
部分)
-
依赖包解析结果
关键包及作用
包名 来源 典型用途 GTMSessionFetcher Google 官方库 OAuth 网络请求基础组件 GoogleSignIn Google 登录 SDK 应用内集成 Google 账号登录 Firebase* Firebase 系列服务 数据分析、崩溃监控、认证等功能 RevenueCat 第三方订阅管理平台 应用内购买与订阅系统集成 MobileVLCKit VLC 开源播放器核心 视频播放功能支持 ffmpeg-kit FFmpeg 多媒体框架封装 高级音视频编解码处理 -
版本锁定机制
@ 3.5.0
等后缀表示 精确版本锁定,常见于以下情况:- 项目
Package.swift
中指定了精确版本(如.exact("3.5.0")
) - CocoaPods 的
Podfile.lock
版本固化 - 手动强制解析特定 commit
- 项目
-
Scheme 清单分析
Scheme 分类
类型 示例 Scheme 说明 主应用 Scheme iosApp
你的应用核心构建目标,对应 Xcode 中可运行的入口 CocoaPods 生成 Pods-iosApp
CocoaPods 集成时自动生成的聚合 Scheme,用于统一构建所有 Pod 依赖 第三方库原生 Scheme FirebaseAnalytics
、GoogleSignIn
依赖库自带的构建目标(通常用于库的独立测试或 Demo) 隐私清单 Scheme FirebaseAuth-FirebaseAuth_Privacy
Xcode 15+ 新特性,自动生成的隐私清单校验目标(用于 App Store 提交) 模块化子组件 FirebaseCoreExtension
大型库(如 Firebase)拆分的子模块 Scheme -
开发者关注重点
-
构建选择
- 日常开发:只需关注
iosApp
Scheme,其他 Scheme 通常由系统自动管理 - 特殊场景示例:
- 日常开发:只需关注
-
依赖冲突排查
若遇到类似错误:
Multiple commands produce 'GTMSessionFetcher.framework'
需检查是否存在以下问题:- CocoaPods 与 Swift Package Manager 重复导入同一库
- 不同库依赖同一子库但版本不兼容(如 Firebase 和 RevenueCat 对 Protobuf 版本的要求冲突)
-
隐私清单合规
所有含
_Privacy
后缀的 Scheme 对应 Xcode 15 的 隐私清单强制校验(App Store 中新增的隐私功能),需确保:- 第三方库已提供隐私清单(如 RevenueCat 已适配)
- 未适配的库需要手动添加隐私声明
关于更多隐私合规的问题可以查看 App Store 即将实行的要求
-
-
CI/CD 优化建议
-
构建加速
在
xcodebuild archive
命令中添加参数排除无用构建: -
依赖缓存
对解析结果中的仓库 URL(如
https://github.com/google/gtm-session-fetcher.git
)做镜像缓存,防止因网络问题导致解析失败:
-
通过这份解析,你可以清晰掌握项目的依赖结构和构建入口,同时为后续的持续集成与代码审计提供基础数据支撑。
清理指令
如果你想确保项目的构建从零开始,可以使用以下单行命令来清理之前的构建工件:
xcodebuild clean
指令可以理解为类似于Android编译中的 ./gradlew clean
操作
执行xcodebuild clean
指令后,将获得如下输出结果:
编译指令
xcodebuild build
- 用途
- 编译项目并生成可执行文件(如
.app
),主要用于本地测试或调试。
- 编译项目并生成可执行文件(如
- 输出结果
- 生成二进制文件(.app)和调试符号(.dSYM,仅限某些配置),存储在 DerivedData(
~/Library/Developer/Xcode/DerivedData
)目录中。 - 不会生成分发包或归档文件。
- 生成二进制文件(.app)和调试符号(.dSYM,仅限某些配置),存储在 DerivedData(
- 典型场景
- 在模拟器或真机上运行应用。
- 快速验证代码变更是否编译通过。
- 项目案例
- 指令特点
- 默认使用
Debug
配置(可手动指定为Release
)。 - 不强制验证代码签名(如为
Debug
模式使用开发证书)。
- 默认使用
xocdebuild archive
- 用途
- 编译项目并生成
.xcarchive
归档文件,专为分发应用(如提交至 App Store 或 TestFlight)或生成 IPA 包设计。
- 编译项目并生成
- 输出结果
- 生成 .xcarchive 文件,包含:
- 应用二进制文件(.app)。
- 调试符号(.dSYM)。
- 资源文件(如图标、资产)。
- 元数据(版本号、构建配置等)。
- 归档文件默认存储在
~/Library/Developer/Xcode/Archives
。
- 生成 .xcarchive 文件,包含:
- 典型场景
- 准备提交到 App Store Connect。
- 生成 Ad Hoc 或 Enterprise 分发的 IPA 文件。
- 项目案例
- 指令特点
- 通常要求
Release
配置。 - 强制验证代码签名(需正确的分发证书和配置文件)。
- 支持后续通过
-exportArchive
生成 IPA 包。
- 通常要求
关键区别总结
维度 | xcodebuild build |
xcodebuild archive |
---|---|---|
主要目的 | 本地运行、调试 | 分发应用(App Store、TestFlight 等) |
输出产物 | .app (在 DerivedData 目录) |
.xcarchive 归档文件 |
代码签名验证 | 可选(依赖配置) | 强制(需有效分发证书) |
典型配置 | Debug (默认) |
Release |
后续步骤 | 直接安装到设备 | 通过 -exportArchive 生成 IPA 文件 |
进阶说明
-
归档与 IPA 生成: 执行
archive
后,通常需要配合xcodebuild -exportArchive
将.xcarchive
转换为.ipa
文件,例如:其中
ExportOptions.plist
定义了分发方式(App Store、Ad Hoc 等)。 -
调试支持:
.xcarchive
包含的.dSYM
文件可用于符号化崩溃日志,是线上问题排查的关键。
通过合理选择命令,可高效完成开发调试与分发包准备工作。
生成 .ipa
包
配置 ExportOptions.plist
文件
最终,你需要创建iOS App 的 .ipa
文件,但是你需要一个 ExportOptions.plist
文件。
这个文件是通过XCode进行应用编译和归档后生成的。大致上的结构如下:
这是一个 Xcode 导出选项配置文件(ExportOptions.plist),主要用于在 自动化构建 或 CI/CD 流程 中定义 iOS/Mac 应用的打包和签名规则。
以下是关键参数的解析:
-
核心作用
该文件通过 xcodebuild -exportOptionsPlist 参数使用,控制以下行为:
-
参数详解
参数名称 值 说明 compileBitcode false
禁用 Bitcode 编译,加速构建,但提交 App Store 时必须设为 true
method debugging
导出方式:调试模式(仅限设备调试,不能上架) signingStyle automatic
自动签名(Xcode 自动选择证书和描述文件) stripSwiftSymbols true
移除 Swift 符号,减小包体积(Release 建议开启) teamID YOUR_TEAM_ID
开发者团队 ID(需替换为实际值,如 ABCDE12345
)testFlightInternalTestingOnly false
禁用仅限 TestFlight 内部测试成员分发(设为 true
限制测试范围)uploadSymbols false
不上传调试符号文件(Release 需设为 true
以支持崩溃分析) -
典型使用场景
- 本地调试构建 禁用 Bitcode 和符号上传,快速生成调试包。
- CI/CD 测试环境 配合自动化工具(如 Fastlane/Jenkins),确保每次构建签名配置一致。
- 内部分发限制 若需限制 TestFlight 测试范围,可将
testFlightInternalTestingOnly
设为true
。
-
注意事项
- 签名方式选择
- 若需手动指定证书,应将
signingStyle
改为manual
并添加signingCertificate
参数。 - 自动签名依赖本地或 CI 环境的钥匙串中存在有效证书。
- 若需手动指定证书,应将
- App Store 提交要求
- 正式包必须开启
compileBitcode=true
和uploadSymbols=true
method
需改为app-store
- 正式包必须开启
- 多环境配置 建议为不同环境(Debug/Release)创建多个 plist 文件,例如:
ExportOptions-Debug.plist
ExportOptions-Release.plist
- 签名方式选择
-
扩展配置项
可添加更多参数实现高级控制:
建议通过 Xcode 生成标准模板:
Product > Archive > Distribute App > Export > 选择选项后生成 ExportOptions.plist
示例展示
执行指令:
生成结果:
以下是通过 xcodebuild -exportArchive
操作后生成的四个核心文件的解析,按实际使用场景分类说明:
-
DistributionSummary.plist
- 定位: 分发元数据报告
- 内容结构:
- 使用场景:
- 验证构建参数是否符合预期(如是否误用开发证书签名发布包)
- 审计历史构建记录时快速查看关键配置
- 通过
plutil -p DistributionSummary.plist
快速查看内容
-
ExportOptions.plist
- 定位: 构建参数镜像文件
- 特殊点: 该文件是 构建时实际使用的参数副本,而非原始输入文件。若通过 Xcode GUI 修改过选项,此文件会与初始传入的不同
- 风险点: CI/CD 环境中需对比此文件与源码库中的版本,防止因 GUI 操作导致配置漂移
-
Packaging.log
- 定位: 二进制级构建日志
- 关键信息示例:
- 调试技巧:
- 搜索
error:
或failed
关键词定位问题 - 结合
codesign --verify
验证签名步骤是否完整 - 检查资源文件路径是否正确(常见于 Asset Catalog 路径错误)
- 搜索
-
example.ipa
- 文件结构 (解压后):
- 质量检查命令:
CI/CD 集成建议
- 产物保留策略:
- 永久存档
.ipa
+ExportOptions.plist
(用于后续重新导出) - 临时保留
Packaging.log
(建议保存至日志系统如Splunk) - 可删除
DistributionSummary.plist
(其信息已包含在日志中)
- 永久存档
- 自动化验证步骤:
- 安全扫描: 对
.ipa
进行静态分析(使用 OWASP ZAP 或 AppScan),重点检查:Info.plist
中是否开启不必要权限(如NSAllowsArbitraryLoads
)- 动态库是否包含已知漏洞版本
- 是否包含测试环境 API 配置
通过以上文件组合分析,可快速定位如「测试包误用生产证书」、「资源文件签名遗漏」等典型问题。
签名验证
在这个产物的路径 Products/Applications/
下,能看到编译之后的 *.app
产物,接下来可以通过 codesign
来测试输出的结果:
输出结果如下:
以下是对iOS应用包信息的逐项技术解析,关键参数已用粗体标注:
-
基础信息
Executable
:iosApp.xcarchive/Products/Applications/example.app/example
应用二进制文件路径,由Xcode归档(Archive)生成,通常用于发布或测试Identifier
:com.example.app
Bundle ID,唯一标识应用,需与开发者账号配置和App Store Connect中的ID一致Format
:app bundle with Mach-O thin (arm64)
应用格式为Mach-O单架构(arm64),适用于64位iOS设备
-
代码签名与安全
CodeDirectory v=20400
: 代码签名目录版本为20400,包含签名的哈希值和元数据Hash type=sha256
: 使用SHA-256算法生成代码哈希,用于验证文件完整性CDHash
:YOUR_HASH_VALUE...
代码目录哈希(Code Directory Hash),用于快速验证签名一致性,匹配codesign -dv
输出CMSDigest
: 与CandidateCDHashFull
一致 签名证书的摘要值,用于验证证书链合法性
-
证书与签名
-
Authority
链:签名证书链,表明应用由开发者「YOUR_NAME」的证书(类型:开发证书)签发,并通过苹果两级CA认证
-
TeamIdentifier
:YOUR_TEAM_ID
开发者团队ID,需与Apple Developer账号中的Team ID匹配,用于防止证书盗用 -
Signed Time
:Mar 9, 2025 at 23:19:22
签名时间戳,若系统时间超过证书有效期(通常开发证书1年),应用将无法运行 -
应用资源配置
-
Info.plist entries=38
: Info.plist中共有38个配置项,包含Bundle ID、版本号、权限声明等关键参数 -
Sealed Resources
:资源密封机制防止篡改,规则由Xcode自动生成
-
-
关键验证点
- 签名有效性:
Authority
链完整且包含苹果官方CA证书(Apple Root CA),表明签名合法。 - 证书类型: 当前使用开发证书(Apple Development),若需发布到App Store需替换为Distribution证书。
- 时间戳: 签名时间为2025年,需确认证书实际有效期(开发证书通常为1年),防止过期失效。
- 签名有效性:
此信息表明应用签名配置正常,但需注意证书类型和有效期是否符合分发场景要求(如TestFlight需Distribution证书)。
分发 ipa
文件
Ad Hoc
- 企业内部测试渠道(内部测试人员)
要通过 Ad Hoc
方式分发 .ipa
文件,需要确保应用正确签名且 目标设备的UUID 已注册到Devices List配置文件中。以下是完整的配置流程:
准备证书与配置文件
- 证书要求:
- 签名证书:Apple 开发者账号中的
Ad Hoc
分发证书(需提前在 Apple Developer Portal 生成)。 - 配置文件:创建
Ad Hoc
类型的Provisioning Profile
,并包含以下内容:- 关联
Ad Hoc
证书 - 明确指定
App Bundle Identifier
- 添加所有目标测试设备的 UUID(最多100台设备)
- 关联
- 操作步骤:
- 登录 Apple Developer Portal → Certificates, Identifiers & Profiles。
- 创建/下载 Ad Hoc 证书和配置文件(
.mobileprovision
)。 - 在 Xcode 中导入证书和配置文件(或通过 xcodebuild 自动管理)。
- 签名证书:Apple 开发者账号中的
生成Ad Hoc分发的 .ipa
文件
- 关键配置
- 在生成
.ipa
时,必须通过-exportOptionsPlist
指定Ad Hoc
分发模式。以下是典型配置:
ExportOptions.plist
文件内容:
- 在生成
验证 .ipa
签名
分发 .ipa
文件
对于 Ad Hoc
包,我们可以通过配置 mainifest.plist
文件然后将相关的版本发布到线上的静态链接地址上,提供可供下载的链接/二维码给到公司内部的测试人员。
配置ADHoc包的下载地址: Example App ADHoc
配置地址为一般为: itms-services://?action=download-manifest&url=
+ https://download.example.app/ios/manifest.plist
TestFlight
- 外部测试渠道(外部内测用户)
环境准备
- 必要条件:
- Apple 开发者账号(付费账号,个人或组织)。
- 应用已配置 App Store 分发证书(非
Ad Hoc
)。 - Xcode 项目设置中:
Bundle Identifier
在开发者后台已注册。- 版本号(
CFBundleShortVersionString
)和 构建号(CFBundleVersion
)符合递增规则。
构建与上传
- 构建步骤:
- 生成归档文件(Archive)
- 配置
ExportOptions.plist
文件内容(本文导出的路径为当前项目的archive/iOS/ExportOptions.plist
下)
- 执行
Export
导出.ipa
文件
- 上传到 App Store
- 前置准备:
- 在上传文件到App Store之前,我们需要先安装软件: iTMSTransporter
- 下载 App Store Connect Api Key 至本地
- 从 App Store Connect API 下载后将文件放在本地的
~/private_keys/
路径下
- 从 App Store Connect API 下载后将文件放在本地的
- 运行上传指令
- 前置准备:
注意事项
- 在上传AppStore之后苹果后台会初步给出一个邮件提醒,告知上传的结果,成功或者失败。
- 一般会遇到错误:“二进制文件无效”,这种大部分都是因为发布的App中缺少所需的权限声明,基于苹果的隐私政策要求,只需要补充对应的
Info.plist
中权限的声明,重新编译后重新上传App - 上传App之后AppStore上的待审核版本并不会立刻更新,而是要等待片刻,等待更新之后苹果会发送一封邮件提示App上传成功 “The following build has completed processing”
- 收到邮件之后,就可以将当前的版本加入到
TestFlight
中进行公司内部开发测试用户测试 - 如果要提供给外部的内测用户使用,则需要提交
TestFlight
版本给到苹果进行审核,审核通过之后TestFlight
版本才能正常通过链接下载。
AppStore
- 线上测试渠道(所有用户)
在上传App到AppStore
之前,请务必仔细阅读苹果官方文档 App 审核指南 在提交版本之前尽量避免指南中所禁止的问题。
环境准备
-
应用配置要求
- 确保
App Store Distribution
证书签名 - 确保
ExportOptions.plist
设置包含:
- 完整的应用隐私声明(
Info.plist
)
- 确保
-
App Store Connect 配置
- 在 App Store Connect 创建应用
- 准备应用介绍、截图、预览视频
- 配置价格与销售范围
- 填写隐私政策链接
构建与上传
发布流程
- 构建处理
- 等待邮件通知:"Processing has completed"
- 在 App Store Connect 检查构建版本是否可用
- 提交审核
- 选择要发布的构建版本
- 填写"What's New"版本说明
- 确认所有必填项(年龄分级、版权信息等)
- 提交审核
- 审核阶段
- 一般审核周期 24-48 小时
- 可能的审核状态
Waiting for Review
: 等待审核In Review
: 审核中Pending Developer Release
: 审核通过待发布Ready for Sale
: 已上架销售
注意事项
-
关键检查项
- 确保所有使用的
API
符合苹果审核指南 - 隐私相关功能需提供完整说明
- 应用图标和启动图需符合尺寸规范
- 所有付费功能必须使用
In-App Purchase
- 确保所有使用的
-
常见拒绝原因处理
- 功能不完整或存在崩溃问题
- 缺少隐私政策或数据使用说明
- 应用描述与实际功能不符
- 违反人机界面准则
- 使用私有
API
-
发布后监控
- 通过 App Analytics 监控下载量
- 关注用户评价和反馈
- 跟踪崩溃报告
- 准备必要的应用更新
CI/CD 集成建议
这样的发布流程可以确保 App 顺利通过审核并上架 App Store。要特别注意苹果的各项规范要求,这样可以减少审核被拒的概率。