Jacky's blog
首页
  • Android
  • Web
  • Server
  • Python
  • iOS
  • Java
  • Vue
  • 计算机基础
  • 工具链
  • AI
  • 个人成长
  • 博客
  • 分类
  • 标签
  • 归档
收藏
GitHub (opens new window)

Jack Yang

编程; 随笔
首页
  • Android
  • Web
  • Server
  • Python
  • iOS
  • Java
  • Vue
  • 计算机基础
  • 工具链
  • AI
  • 个人成长
  • 博客
  • 分类
  • 标签
  • 归档
收藏
GitHub (opens new window)
  • iOS 开发完整指南
  • Swift 语法与最佳实践
  • oc语法
  • iOS 运行时
  • xcode的使用
  • xcrun 与 Xcode 命令行工具
  • pod
  • xcodebuild 命令行构建
    • xcodebuild 是什么
    • 帮助与自查体系
    • 核心概念(先搞清楚再敲命令)
    • 基础查询命令
    • destination 写法(最高频踩坑区)
    • 构建
      • 基本构建
      • 覆盖 build settings(不改工程文件)
      • 指定产物目录(CI 必备)
    • 测试
    • 打包上架(archive → ipa)
      • 第一步:archive 归档
      • 第二步:导出 ipa
    • 静态库 / xcframework
    • CI 常用技巧
    • 常见问题排查
      • error: does not contain a scheme named "Xxx"
      • Unable to find a destination / Multiple matches for destination
      • 签名相关报错(requires a provisioning profile / Signing for X requires a development team)
      • 构建结果与 GUI 不一致(本地好的 CI 挂了)
      • 卡在 "Waiting for first launch" / 首次安装弹窗
      • 产物路径找不到
    • 与其他工具的关系
    • 链接
  • Xcode 工程文件说明
  • ios
Jacky
2026-09-22
目录

xcodebuild 命令行构建

# xcodebuild 命令行构建(iOS 常用实测版)

实测环境:Xcode 27.0 (Build 27A266a) / macOS Apple Silicon 重点内容:构建 / 测试 / 打包归档 / CI 脚本 / 常见报错排查

# xcodebuild 是什么

xcodebuild 是 Xcode 的命令行构建入口:Xcode GUI 里按 Command - R 时,底层跑的就是它。所有 CI(fastlane、Jenkins、GitLab CI)构建 iOS 项目最终都落到这条命令。

三个核心价值:

  1. 自动化——脚本 / CI 无人值守构建、测试、打包
  2. 可复现——参数固定后构建结果不依赖任何人本机的 Xcode GUI 状态
  3. 可定制——命令行可覆盖任意 build settings,不用改工程文件
xcodebuild -version          # Xcode 27.0 / Build version 27A266a
xcrun xcodebuild -version   # 等价写法(经 xcrun 入口)
1
2

未设置 DEVELOPER_DIR 时,系统工具通过 xcode-select 选择开发者目录;设置该环境变量可覆盖当前命令及其子进程的选择,不改变系统默认目录。多版本共存时同时检查环境变量与工具版本(见 xcrun)。

# 帮助与自查体系

命令细节不用背,按需查:

xcodebuild -help        # 完整帮助(选项极多,配合 grep 用)
xcodebuild -usage       # 简要用法
man xcodebuild          # 手册(含 destination 语法说明)
1
2
3

# 核心概念(先搞清楚再敲命令)

概念 说明 命令行对应
project .xcodeproj 工程文件,可独立构建 -project MyApp.xcodeproj
workspace .xcworkspace,多 project + Pod 依赖的容器(用了 CocoaPods 必须用它) -workspace MyApp.xcworkspace
scheme 构建方案:包含哪些 target、跑哪些测试、用什么配置 -scheme MyApp
configuration 构建配置,默认 Debug / Release -configuration Release
destination 构建目标:模拟器 / 真机 / 泛平台 -destination '...'

两条铁律:

  1. workspace 和 scheme 几乎总是成对出现(-workspace 必配 -scheme)
  2. destination 不写会随机挑一台可用设备,CI 上必须显式指定

# 基础查询命令

# 查工程里有哪些 scheme / target / configuration
xcodebuild -list -workspace MyApp.xcworkspace
# 实测输出示例:
#     Schemes:
#         MyApp
#         MyAppTests
#         Pods-MyApp

# 查已装 SDK
xcodebuild -showsdks

# 查 scheme 支持哪些 destination(报"找不到 destination"时先跑这个)
xcodebuild -showdestinations -workspace MyApp.xcworkspace -scheme MyApp

# 查 build settings 生效值(排查签名/路径问题的第一入口)
xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -showBuildSettings | grep -E "PRODUCT_BUNDLE_IDENTIFIER|DEVELOPMENT_TEAM|PROVISIONING"
# 加 -json 输出机器可读格式(脚本解析用)
xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -showBuildSettings -json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# destination 写法(最高频踩坑区)

# 模拟器:按名称指定(推荐,CI 稳定)
-destination 'platform=iOS Simulator,name=iPhone 15 Pro'
# 模拟器:按 UDID 指定(多开时最精确,UDID 来自 xcrun simctl list)
-destination 'platform=iOS Simulator,id=80CCEF25-6BD0-4C3A-9A4E-896064E088F7'
# 真机:按 UDID
-destination 'platform=iOS,id=00008130-00162C3C2891401C'
# 真机:泛平台(不需要插真机,打包/签名场景必用)
-destination 'generic/platform=iOS'
# macOS
-destination 'platform=macOS'
1
2
3
4
5
6
7
8
9
10

多个 key 用逗号连接:platform=iOS Simulator,name=iPhone 15 Pro,OS=17.0。

真机 vs 模拟器架构不同:模拟器产物在 Debug-iphonesimulator/(含模拟器 slice),真机产物在 Debug-iphoneos/,两者互不通用——装包时对应关系见 xcrun 章节。

# 构建

# 基本构建

# 标准构建(模拟器)
xcodebuild -workspace MyApp.xcworkspace -scheme MyApp \
  -configuration Debug \
  -destination 'platform=iOS Simulator,name=iPhone 15 Pro' \
  build

# 单 project 工程(没用 CocoaPods 时)
xcodebuild -project MyApp.xcodeproj -scheme MyApp build

# 清理后重建(排查诡异缓存问题)
xcodebuild ... clean build
1
2
3
4
5
6
7
8
9
10
11

成功最后一行是 ** BUILD SUCCEEDED **,失败是 ** BUILD FAILED **——脚本里用退出码 $? 判断即可(成功为 0)。

# 覆盖 build settings(不改工程文件)

# 任意 build setting 都可以用 key=value 在命令行覆盖
xcodebuild ... build \
  CODE_SIGN_IDENTITY="iPhone Distribution" \
  DEVELOPMENT_TEAM=XXXXXXXXXX \
  COMPILER_INDEX_STORE_ENABLE=NO     # 关索引写入,CI 提速
1
2
3
4
5

# 指定产物目录(CI 必备)

# 固定 DerivedData 路径,方便脚本取产物 / 复用缓存
xcodebuild ... build -derivedDataPath build/DerivedData
# 产物位置:build/DerivedData/Build/Products/<configuration>-<platform>/MyApp.app
1
2
3

不指定时产物在默认 DerivedData:~/Library/Developer/Xcode/DerivedData/<工程名>-<hash>/,路径带 hash 不稳定,脚本里一律用 -derivedDataPath 或 -showBuildSettings 查 BUILT_PRODUCTS_DIR。

# 测试

# 跑单测(scheme 需包含测试 target)
xcodebuild test -workspace MyApp.xcworkspace -scheme MyAppTests \
  -destination 'platform=iOS Simulator,name=iPhone 15 Pro'

# 只跑指定用例
xcodebuild test ... -only-testing:MyAppTests/LoginTests
xcodebuild test ... -only-testing:MyAppTests/LoginTests/testLoginSuccess

# 排除某些用例
xcodebuild test ... -skip-testing:MyAppTests/UITests

# 指定 test plan
xcodebuild test ... -testPlan UnitTests

# 失败自动重试(CI 拦偶现失败)
xcodebuild test ... -retry-tests-on-failure

# 只测不构建(复用已有产物,配合 build-for-testing)
xcodebuild build-for-testing ...
xcodebuild test-without-building ...

# 测试报告:xcresult(Xcode 13+ 默认 v3)
xcodebuild test ... -resultBundlePath build/Test.xcresult
# 用 GUI 看:open build/Test.xcresult
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 打包上架(archive → ipa)

# 第一步:archive 归档

xcodebuild archive \
  -workspace MyApp.xcworkspace -scheme MyApp \
  -configuration Release \
  -destination 'generic/platform=iOS' \
  -archivePath build/MyApp.xcarchive \
  -allowProvisioningUpdates        # 自动管理签名时,允许联网更新描述文件
1
2
3
4
5
6

产物 MyApp.xcarchive 是目录,内含 Products/Applications/MyApp.app(真机架构、已签名)。

# 第二步:导出 ipa

# 需要 ExportOptions.plist 描述导出方式
xcodebuild -exportArchive \
  -archivePath build/MyApp.xcarchive \
  -exportPath build/ipa \
  -exportOptionsPlist ExportOptions.plist
# 产物:build/ipa/MyApp.ipa
1
2
3
4
5
6

ExportOptions.plist 最小可用模板(App Store 渠道):

<?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>method</key>
    <string>app-store-connect</string>
    <key>teamID</key>
    <string>XXXXXXXXXX</string>
    <key>signingStyle</key>
    <string>automatic</string>
    <key>uploadSymbols</key>
    <true/>
</dict>
</plist>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

method 常用值对照:

method 用途
app-store-connect App Store / TestFlight 上架
ad-hoc 内测分发(需设备注册在描述文件内)
enterprise 企业证书分发
development 开发证书

手动签名时把 signingStyle 换成 manual,并加 provisioningProfiles / signingCertificate 字段。

# 静态库 / xcframework

# 构建 framework / 静态库:换 target 即可
xcodebuild -workspace MyLib.xcworkspace -scheme MyLib \
  -destination 'generic/platform=iOS' -configuration Release build

# 合并模拟器 + 真机架构为 xcframework(跨平台分发标准产物)
xcodebuild -create-xcframework \
  -framework build/sim/MyLib.framework \
  -framework build/device/MyLib.framework \
  -output build/MyLib.xcframework
1
2
3
4
5
6
7
8
9

# CI 常用技巧

# 1. 日志降噪:只输出警告和错误
xcodebuild ... build -quiet

# 2. 日志美化(xcodebuild 原始日志极难读)
brew install xcbeautify
xcodebuild ... build 2>&1 | xcbeautify
# 旧工具 xcpretty 同类,xcbeautify 更快更准

# 3. 关闭索引写入(CI 无人用 IDE,省 20%+ 时间)
COMPILER_INDEX_STORE_ENABLE=NO

# 4. 并行构建
-parallelizeTargets -jobs 8

# 5. 跳过不可用的 scheme action(如 scheme 配了 run 但 CI 只想构建)
-skipUnavailableActions

# 6. SPM 依赖固定目录(CI 缓存 SPM checkout)
-resolvePackageDependencies -clonedSourcePackagesDirPath .spm-cache
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 常见问题排查

# error: does not contain a scheme named "Xxx"

  • scheme 名先用 xcodebuild -list 核对,注意大小写
  • scheme 标记为 hidden:Xcode → Product → Scheme → Manage Schemes 勾选 Shared(CI 上必须 Shared,否则 .xcscheme 不入库)
  • workspace / project 传错了:Pods 工程必须用 -workspace,单独构建某个 Pod 用 -project Pods/Pods.xcodeproj

# Unable to find a destination / Multiple matches for destination

# 先看 scheme 实际支持哪些 destination
xcodebuild -showdestinations -workspace MyApp.xcworkspace -scheme MyApp
1
2
  • 模拟器名拼错(如系统没有 iPhone 15 Pro 这台设备):用 xcrun simctl list devices available 核对
  • 多台设备匹配同名称:改用 id=<UDID> 精确指定
  • 真机未插 / 未信任 / 未开开发者模式:连接问题见 xcrun 章节排查

# 签名相关报错(requires a provisioning profile / Signing for X requires a development team)

# 自动签名 + 联网更新描述文件
xcodebuild ... -allowProvisioningUpdates

# 命令行显式覆盖(CI 常用)
xcodebuild ... build \
  CODE_SIGN_IDENTITY="iPhone Distribution" \
  DEVELOPMENT_TEAM=XXXXXXXXXX \
  PROVISIONING_PROFILE_SPECIFIER="match AppStore com.example.MyApp"
1
2
3
4
5
6
7
8
  • 先 -showBuildSettings | grep -E "CODE_SIGN|DEVELOPMENT_TEAM|PROVISIONING" 看当前生效值
  • CI 上建议 security unlock-keychain 解锁钥匙串,否则签名会卡住或失败

# 构建结果与 GUI 不一致(本地好的 CI 挂了)

  • GUI 走的 scheme / configuration / destination 与命令行不同——用 -showBuildSettings 对比 CONFIGURATION、PLATFORM_NAME、SDKROOT
  • 缓存脏了:xcodebuild clean 或直接删 -derivedDataPath 指定的目录(GUI 是 Command Shift - K)
  • Xcode 版本不同:CI 与本机各跑一次 xcodebuild -version 对比

# 卡在 "Waiting for first launch" / 首次安装弹窗

新装 Xcode 首次 CLI 构建需要完成首次启动协议:

xcodebuild -runFirstLaunch      # 安装组件并同意 license
xcodebuild -license status      # 单查 license 状态
1
2

# 产物路径找不到

# 查产物目录的权威方式
xcodebuild ... -showBuildSettings | grep -E "BUILT_PRODUCTS_DIR|TARGET_BUILD_DIR"
1
2

规则:BUILT_PRODUCTS_DIR = <DerivedData>/Build/Products/<configuration>-<platform>/,其中 platform 为 iphonesimulator / iphoneos。

# 与其他工具的关系

工具 关系
Xcode GUI GUI 构建就是调 xcodebuild,日志在 Report Navigator 里
fastlane gym/scan 底层就是拼 xcodebuild archive/test 参数
xcrun xcodebuild 本身也是经 xcrun 定位执行的(见 xcrun 章节)
xcode-select 多 Xcode 版本切换后,xcodebuild 版本跟着变

# 链接

  • xcodebuild man page (opens new window)
  • xcodebuild 官方说明 (opens new window)
  • xcbeautify (opens new window)
#iOS#xcodebuild#Xcode
上次更新: 2026/10/09, 15:51:11
pod
Xcode 工程文件说明

← pod Xcode 工程文件说明→

最近更新
01
GitHub CLI(gh)工作流与 CI 排查
10-08
02
Xcode 工程文件说明
09-28
03
osascript
09-23
更多文章>
Theme by Vdoing | Copyright © 2019-2026 Jacky | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式