赞
踩
Apple Developer Documentation Archive 是 Apple 已归档的开发者文档,具有很大的参考价值。adat 项目选取了一些典型文章进行翻译,摒弃了部分过时的内容,并在 Xcode 13.0 上进行实践。这是该项目的第一篇文章,后续文章将会逐步深入,探究使用命令行工具进行企业级构建的最佳实践。
命令行工具包是一个小型的自包含工具包,可以独立下载,可以在 macOS 上进行命令行开发。它由 macOS SDK 和命令行工具(例如 Clang,位于 /Library/Developer/CommandLineTools)组成。
在 macOS 10.9 及以后的版本上,Xcode 的偏好设置中的下载面板不再支持命令行工具直接下载,可以使用下面任意一种方式来安装:
Xcode 已经包含命令行工具,因此只要安装了 Xcode,就无需额外安装命令行工具。
下载地址:https://developer.apple.com/download/all/,需要使用 Membership Account 登录,搜索并下载和系统版本匹配的命令行工具版本。
在 macOS 10.9 及以后,当有新的命令行版本可用时,将会收到软件更新的通知。
在 Terminal 中执行如下命令进行安装:
xcode-select --install
macOS 自带 xcode-select 命令,在 /usr/bin 目录下。
在 Terminal 中执行如下命令:
xcode-select --print-path
示例:
$ xcode-select --print-path
/Applications/Xcode.app/Contents/Developer
表示当前命令行工具使用的Xcode位于 /Applications/Xcode.app
在 Terminal 中执行如下命令:
sudo xcode-select -switch <path/to/>Xcode.app
示例:
$ sudo xcode-select -switch /Applications/Xcode.app
使用 xcodebuild 命令,它可以对 Xcode 项目和工作空间进行编译、查询、分析、测试和归档。如果操作的是 Xcode 项目,需要指定至少一个 target 或一个 scheme,而如果是工作空间,则只需指定一个 scheme。在 Terminal 中执行 man xcodebuild 可以查看 xcodebuild 使用手册。xcodebuild 执行的结果默认存储位置定义在:Xcode > Preferences > Locations。
注意:在执行命令前,要先切换到包含项目或工作空间的目录下,或指定完整的项目或工作空间的路径。
下面是一些用法举例:
xcodebuild -list -workspace <your_workspace_name>.xcworkspace
示例:
$ cd /Users/username/Desktop/MyApplication
$ xcodebuild -list -workspace MyApplication.xcworkspace
Information about workspace "MyApplication":
Schemes:
iOSApp
tvOSApp
macOSApp
iOSWithWatchApp
iOSWithWatchApp WatchKit App
xcodebuild -list -project MyProject.xcodeproj
示例:
$ cd /Users/username/Desktop/MyProject $ xcodebuild -list -project MyProject.xcodeproj Information about project "MyProject": Targets: iOS iOSTests iOSUITests watchOS App watchOS App Extension tvOS tvOSTests tvOSUITests macOS macOSTests macOSUITests Build Configurations: Debug Release If no build configuration is specified and -scheme is not passed then "Debug" is used. Schemes: iOS watchOS App tvOS macOS
xcodebuild -scheme <your_scheme_name> build
示例:
$ xcodebuild -scheme tvOS build
=== BUILD TARGET tvOS OF PROJECT MyProject WITH CONFIGURATION Debug ===
...
注意:xcodebuild 支持编译、分析、测试和归档等操作,当不指定任何操作时,默认执行编译操作。
xcodebuild -target <your_target_name> -xcconfig <your_configuration_file>.xcconfig
示例:
$ xcodebuild -target iOS -xcconfig configuration.xcconfig
Build settings from configuration file 'configuration.xcconfig':
IPHONEOS_DEPLOYMENT_TARGET = 10
SWIFT_TREAT_WARNINGS_AS_ERRORS = YES
=== BUILD TARGET watchOS Extension OF PROJECT MyProject WITH THE DEFAULT CONFIGURATION (Debug) ===
...
=== BUILD TARGET watchOS App OF PROJECT MyProject WITH THE DEFAULT CONFIGURATION (Debug) ===
...
=== BUILD TARGET iOS OF PROJECT MyProject WITH THE DEFAULT CONFIGURATION (Debug) ===
...
可以在命令行中指定 SYMROOT(构建路径,存放 debug 包和 .dSYM 文件)和 DSTROOT(安装位置,存放 release 包和 .dSYM 文件)的值来达到修改目的。
修改 debug 版本的输出位置:
$ xcodebuild -scheme iOS SYMROOT="/Users/username/Desktop/DebugLocation"
Build settings from command line:
SYMROOT = "/Users/username/Desktop/DebugLocation"
=== BUILD TARGET watchOS Extension OF PROJECT MyProject WITH CONFIGURATION Debug ===
...
=== BUILD TARGET watchOS App OF PROJECT MyProject WITH CONFIGURATION Debug ===
...
=== BUILD TARGET iOS OF PROJECT MyProject WITH CONFIGURATION Debug ===
...
修改 release 版本的输出位置:
$ xcodebuild -scheme iOS DSTROOT="/Users/username/Desktop/ReleaseLocation" archive
Build settings from command line:
DSTROOT = /Users/username/Desktop/ReleaseLocation
=== BUILD TARGET watchOS Extension OF PROJECT MyProject WITH CONFIGURATION Release ===
...
=== BUILD TARGET watchOS App OF PROJECT MyProject WITH CONFIGURATION Release ===
...
=== BUILD TARGET iOS OF PROJECT MyProject WITH CONFIGURATION Release ===
...
导航到 Project > Info > Configurations ,选择一个 configuration 即可:
xcodebuild 也支持单元测试,使用如下命令实现:
xcodebuild test [-workspace <your_workspace_name>]
[-project <your_project_name>]
-scheme <your_scheme_name>
-destination <destination-specifier>
[-only-testing:<test-identifier>]
[-skip-testing:<test-identifier>]
test
操作需要同时指定 scheme
和 destination
。
-workspace
指向 .xcworkspace
文件路径。
-project
指向 .xcodeproj
文件路径。
-destination
确定了单元测试的运行环境, <destination-specifier>
是对用于测试的设备、模拟器或 Mac 的描述,用 key=value
来确定,多个键值对以逗号分隔。
-only-testing
是可选的,指定了只测试哪些用例,-skip-testing
也是可选的,指定了跳过测试哪些用例,<test-identifier>
是对测试用例的描述,格式为:
TestTarget[/TestClass[/TestMethod]]
TestTarget
是测试 Target 的名称,必须要指定。TestClass
和 TestMethod
都是可选的,表示要进行测试的类和方法。
Key | Description | Value |
---|---|---|
platform | 测试运行的平台 | macOS |
arch | 测试使用的架构 | i386 或 x86_64 |
示例,在 macOS 平台的 x86_64 架构上进行测试:
xcodebuild test -scheme macOS -destination 'platform=macOS,arch=x86_64'
Key | Description | Value |
---|---|---|
platform | 测试运行的平台 | iOS(针对 iOS 应用),tvOS(针对 tvOS 应用) |
name | 测试使用的设备全称 | Xcode 设备管理器中显示的设备名称 |
id | 测试使用的设备ID | Xcode 设备管理器中显示的设备ID |
示例,在 ID 为 965058a1c30d845d0dcec81cd6b908650a0d701c 的 iOS 设备上进行测试:
xcodebuild test -workspace MyApplication.xcworkspace -scheme iOSApp -destination 'platform=iOS,id=965058a1c30d845d0dcec81cd6b908650a0d701c'
示例,在名为 iPhone 的 iOS 设备上进行测试:
$ xcodebuild test -workspace MyApplication.xcworkspace -scheme iOSApp -destination 'platform=iOS,name=iPhone' ... === BUILD TARGET iOSApp OF PROJECT iOSApp WITH CONFIGURATION Debug === ... === BUILD TARGET iOSAppTests OF PROJECT iOSApp WITH CONFIGURATION Debug === ... === BUILD TARGET iOSAppUITests OF PROJECT iOSApp WITH CONFIGURATION Debug === ... Test Suite 'All tests' started at ... Test Suite 'iOSAppTests.xctest' started at ... Test Suite 'SecondTestClass' started at ... Test Case '-[iOSAppTests.SecondTestClass testExampleA]' started. Test Case '-[iOSAppTests.SecondTestClass testExampleB]' started. Test Suite 'SecondTestClass' passed at ... ... Test Suite 'iOSAppTests' started at ... Test Case '-[iOSAppTests.iOSAppTests testExample]' started. Test Case '-[iOSAppTests.iOSAppTests testPerformanceExample]' started. Test Suite 'iOSAppTests' passed at ... ... Test Suite 'iOSAppUITests.xctest' started at ... Test Suite 'iOSAppUITests' started at ... Test Case '-[iOSAppUITests.iOSAppUITests testLabels]' started. Test Case '-[iOSAppUITests.iOSAppUITests testToolbar]' started. ... ** TEST SUCCEEDED **
示例,在名为 iPhone 的 iOS 设备上进行测试,但跳过对 iOSAppUITests 的测试:
xcodebuild test -workspace MyApplication.xcworkspace -scheme iOSApp -destination 'platform=iOS,name=iPhone' -skip-testing:iOSAppUITests
示例,在名为 iPhone 的 iOS 设备上进行测试,但只测试 iOSAppTests 中的 SecondTestClass 类的 testExampleB 方法:
$ xcodebuild test -workspace MyApplication.xcworkspace -scheme iOSApp -destination 'platform=iOS,name=iPhone' -only-testing:iOSAppTests/SecondTestClass/testExampleB ... === BUILD TARGET iOSApp OF PROJECT iOSApp WITH CONFIGURATION Debug === ... === BUILD TARGET iOSAppTests OF PROJECT iOSApp WITH CONFIGURATION Debug === ... === BUILD TARGET iOSAppUITests OF PROJECT iOSApp WITH CONFIGURATION Debug === ... Test Suite 'Selected tests' started at ... Test Suite 'iOSAppTests.xctest' started at ... Test Suite 'SecondTestClass' started at ... Test Case '-[iOSAppTests.SecondTestClass testExampleB]' started. Test Case '-[iOSAppTests.SecondTestClass testExampleB]' passed (0.007 seconds). Test Suite 'SecondTestClass' passed at ... ... ** TEST SUCCEEDED **
Key | Description | Value |
---|---|---|
platform | 测试运行的平台 | iOS Simulator(针对 iOS 应用),tvOS Simulator(针对 tvOS 应用) |
name | 测试使用的模拟器全称 | Xcode 设备管理器中显示的模拟器名称 |
id | 测试使用的模拟器ID | Xcode 设备管理器中显示的模拟器ID |
OS | iOS 或 tvOS 的版本号,或 latest 字符串 | 具体的 iOS 版本、 tvOS 版本,或者是 latest |
示例,在名为 iPad Pro (12.9 inch)、版本号为 10.2 的 iOS 模拟器上进行测试:
xcodebuild test -scheme iOS -destination 'platform=iOS Simulator,name=iPad Pro (12.9-inch),OS=10.2'
示例,在 ID 为 D6FA2C2A-E297-406A-AA22-624B4834ACB2 的 tvOS 模拟器上进行测试:
xcodebuild test -scheme tvOS -destination 'platform=tvOS Simulator,id=D6FA2C2A-E297-406A-AA22-624B4834ACB2'
一个测试用例允许指定多个 -destination
选项,xcodebuild 将会按顺序在每个 -destination
指定的环境上测试。
示例,在 iOS 模拟器和 iPod touch 上依次进行测试:
xcodebuild test -scheme iOS -destination 'platform=iOS Simulator,name=iPhone 6s,OS=10.3' -destination 'platform=iOS,name=iPod touch'
具体命令:
xcodebuild build-for-testing [-workspace <your_workspace_name>]
[-project <your_project_name>]
-scheme <your_scheme_name>
-destination <destination-specifier>
示例,在 ID 为 D6FA2C2A-E297-406A-AA22-624B4834ACB2 的 tvOS 模拟器上构建一个测试:
xcodebuild build-for-testing -scheme tvOS -destination 'platform=tvOS Simulator,id=D6FA2C2A-E297-406A-AA22-624B4834ACB2'
build-for-testing 操作会生成一个 xctestrun 文件,保存在 DerivedData 目录下。
指定 scheme 的用法:
xcodebuild test-without-building [-workspace <your_workspace_name>]
[-project <your_project_name>]
-scheme <your_scheme_name>
-destination <destination-specifier>
[-only-testing:<test-identifier>]
[-skip-testing:<test-identifier>]
test-without-building 在指定 scheme 进行测试时,它会在构建根目录(SYMROOT)寻找可以测试的包,因此请确保项目已经编译过或构建根目录已经存在可以测试的包。
示例,在名为 iPhone SE、版本为 10.1 的 iOS 模拟器上执行 test-without-building 测试:
xcodebuild test-without-building -workspace MyApplication.xcworkspace -scheme iOSApp -destination 'platform=iOS Simulator,name=iPhone SE,OS=10.1'
指定 xctestrun 文件的用法:
xcodebuild test-without-building -xctestrun <your_xctestrun_name>.xctestrun
-destination <destination-specifier>
[-only-testing:<test-identifier>]
[-skip-testing:<test-identifier>]
test-without-building 在指定 xctestrun 进行测试时,它会寻找 xctestrun 文件中指定的包,因此请确保这些包存在。
示例,在 ID 为 6DC4A7BA-EA7F-40D6-A327-A0A9DF82F7F6 的 iOS 模拟器上测试iOSApp_iphonesimulator.xctestrun 文件指定的包:
$ cat iOSApp_iphonesimulator.xctestrun <?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>iOSAppTests</key> <dict> <key>BundleIdentifiersForCrashReportEmphasis</key> <array> <string>com.myapps.iOSApp</string> <string>com.myapps.iOSAppTests</string> <string>com.myapps.iOSAppUITests</string> </array> … <key>TestBundlePath</key> <string>__TESTHOST__/PlugIns/iOSAppTests.xctest</string> <key>TestHostBundleIdentifier</key> <string>com.myapps.iOSApp</string> <key>TestHostPath</key> <string>__TESTROOT__/Debug-iphonesimulator/iOSApp.app</string> … </dict> <key>iOSAppUITests</key> … </dict> </plist> $ xcodebuild test-without-building -xctestrun iOSApp_iphonesimulator.xctestrun -destination 'platform=iOS Simulator,id=6DC4A7BA-EA7F-40D6-A327-A0A9DF82F7F6'
示例,在 ID 为 3D95DF14-E8B7-4A05-B65B-78F381B74B22 的 iOS 模拟器上测试iOSApp_iphonesimulator.xctestrun 文件指定的所有包,但跳过对 iOSAppUITests 的测试:
xcodebuild test-without-building -xctestrun iOSApp_iphonesimulator.xctestrun -destination 'platform=iOS Simulator,id=3D95DF14-E8B7-4A05-B65B-78F381B74B22' -skip-testing:iOSAppUITests
注意:build-for-testing 和 test-without-building 也支持持续集成系统。
在 Terminal 中执行如下命令进行查看:
xcodebuild -help
示例:
$ xcodebuild -help Usage: xcodebuild [-project <projectname>] [[-target <targetname>]...|-alltargets] [-configuration <configurationname>] [-arch <architecture>] ... Available keys for -exportOptionsPlist: compileBitcode : Bool ... embedOnDemandResourcesAssetPacksInBundle : Bool ... iCloudContainerEnvironment ... manifest : Dictionary ... method : String ... onDemandResourcesAssetPacksBaseURL : String ... teamID : String ... thinning : String ... uploadBitcode : Bool ... uploadSymbols : Bool
示例:
xcodebuild -project <xcodeprojpath> -scheme <scheme_name> -archivePath <xcarchivepath> archive
<xcodeprojpath>
指向工程的 .xcodeproj
文件路径。如果操作的是工作空间,将 -project
替换为 -workspace
即可。
<scheme_name>
是工程中定义的 scheme
名称,它确定了具体要操作的 target
和 configuration
等信息。
<xcarchivepath>
是导出的归档文件路径,包含 .app
和 dSYM
等文件,它也是下一步操作的参数。
示例:
$ xcodebuild -project iOSApp.xcodeproj -scheme iOSApp -archivePath iOSApp.xcarchive archive Command line invocation: /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -project iOSApp.xcodeproj -scheme iOSApp -archivePath iOSApp.xcarchive archive User defaults from command line: IDEArchivePathOverride = /Users/username/iOSApp/iOSApp.xcarchive IDEPackageSupportUseBuiltinSCM = YES note: Using new build system note: Building targets in parallel note: Planning build note: Analyzing workspace note: Constructing build description note: Build preparation complete ... ** ARCHIVE SUCCEEDED **
xcodebuild -exportArchive -archivePath <xcarchivepath> -exportPath <destinationpath> -exportOptionsPlist <path>
<xcarchivepath>
指向第一步中归档后的文件。
<destinationpath>
指向即将导出的 .ipa 文件路径。
<path>
指向 ExportOptions.plist
文件路径。ExportOptions.plist
文件可以在 Xcode 中手动 Archive 并 Export 一次获得。
示例:
$ xcodebuild -exportArchive -archivePath iOSApp.xcarchive -exportPath Release/MyApp -exportOptionsPlist ExportOptions.plist
...
Exported iOSApp to: /Users/virusbee/Desktop/iOSApp/Release/MyApp
** EXPORT SUCCEEDED **
英文原文:https://developer.apple.com/library/archive/technotes/tn2339
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。