本文翻譯自 CFHipsterRef
轉(zhuǎn)載自:http://chaosky.me/2017/01/04/Xcode-Toolchain/
寫在前面的話
雖然我們來自不同背景、有不同觀點(diǎn),經(jīng)歷不同;雖然我們做事動(dòng)機(jī)不同,信念、偏見和意見使我們彼此分離,有一件事我們是在一起的:
不管好壞,我們都必須使用 Xcode。
Xcode 不僅僅只是一個(gè)應(yīng)用程序,在 GUI 之下是一個(gè)應(yīng)用程序和命令行工具的結(jié)合,它們與開發(fā)人員的工作流程一樣是編輯器的核心。
Xcode Tools
xcode-select
每個(gè)人與 Xcode 的旅程從一個(gè)選擇開始。xcode-select提供了這個(gè)選擇,盡管是一個(gè)永恒的問題:『蛋糕或死亡?』
從 Mavericks 開始,在 Mac 上的開發(fā)者從執(zhí)行一條命令開始:
$ xcode-select --install
將安裝命令行工具,編譯 Objective-C 代碼必備的。
xcrun
xcrun 是 Xcode 基本的命令行工具。使用它可以調(diào)用其他工具。
$ xcrun xcodebuild
除運(yùn)行命令之外,xcrun 可以查找文件和顯示 SDK 的路徑:
$ xcrun --find clang
$ xcrun --sdk iphoneos --find pngcrush
$ xcrun --sdk macosx --show-sdk-path
因?yàn)?xcrun 的執(zhí)行是基于當(dāng)前的 Xcode 版本環(huán)境(通過 xcode-select設(shè)置),所以在系統(tǒng)中能存在多個(gè)版本的 Xcode 工具鏈?zhǔn)欠浅H菀椎摹?/p>
在腳本和其他外部工具中使用 xcrun 能確保在不同環(huán)境中保證一致性。比如,Xcode 附帶了代碼分發(fā)工具 Git。通過調(diào)用 $ xcrun git 而不是 $ git,構(gòu)建系統(tǒng)可以保證運(yùn)行正確。
xcodebuild
第二個(gè)最重要的 Xcode 工具是 xcodebuild,顧名思義,構(gòu)建 Xcode project 和 workspace。
不用傳遞任何構(gòu)建參數(shù),xcodebuild 默認(rèn)為 Xcode.app 最近使用的 scheme 和 配置:
$ xcodebuild
然而,任何 scheme、targets、配置、目標(biāo)設(shè)備、SDK和導(dǎo)出數(shù)據(jù)位置都可以配置:
$ xcodebuild -workspace NSHipster.xcworkspace -scheme "NSHipster"
有六個(gè)可以依次調(diào)用的構(gòu)建操作:
| 操作 | 描述 |
|---|---|
| build | 在構(gòu)建根路徑(SYMROOT)構(gòu)建target。默認(rèn)構(gòu)建操作。 |
| analyze | 在構(gòu)建根路徑(SYMROOT)構(gòu)建和分析target或者scheme。需要指定 scheme。 |
| archive | 在構(gòu)建根路徑(SYMROOT)打包 scheme。需要指定 scheme。 |
| test | 在構(gòu)建根路徑(SYMROOT)測(cè)試 scheme。需要指定 scheme和可選指定目標(biāo)設(shè)備。 |
| installsrc | 拷貝工程源到源根路徑(SRCROOT)。 |
| install | 構(gòu)建target、安裝到target在目標(biāo)設(shè)備根路徑(DSTROOT)的安裝目錄 |
| clean | 從構(gòu)建根路徑(SYMROOT)移除構(gòu)建的產(chǎn)品和中間文件 |
genstrings
genstrings 工具從指定的C或者Objective-C源文件生成 .strings 文件。在不同的 locale 本地化應(yīng)用程序使用 .strings 文件。在蘋果的 Cocoa Core Competencies 中的 [Internationalization](https://developer.apple.com/library/mac/documentation/general/conceptual/devpedia-cocoacore/- Internationalization.html) 有相關(guān)的描述。
$ genstrings -a /path/to/source/files/*.m
每次在源文件中使用 NSLocalizedString,genstrings 將會(huì)追加 key 和 comment 到目標(biāo)文件中。然后由開發(fā)人員為每個(gè)目標(biāo) locale 創(chuàng)建文件的副本, 并將該文件翻譯。
fr.lproj/Localizable.strings
/* No comment provided by engineer. */
"Username"="nom d'utilisateur";
/* {User First Name}'s Profile */
"%@'s Profile"="profil de %1$@";
ibtool
正如 genstrings 作用于源代碼,而 ibtool 作用于 XIB 文件。
$ ibtool --generate-strings-file Localizable.strings en.lpoj/Interface.xib
本地化是它的主要功能,ibtool 還擁有對(duì) Interface Builder 文檔有效的其他幾個(gè)功能。
-
--convert: 更改所有對(duì)類名的引用 -
--upgrade: 將文檔升級(jí)到最新版 -
--enable-auto-layout:?jiǎn)⒂米詣?dòng)布局 -
--update-frames:更新框架 -
--update-constraints:更新約束
iprofiler
iprofiler 測(cè)量應(yīng)用程序的性能,而不啟動(dòng) Instruments.app:
$ iprofiler -allocations -leaks -T 15s -o perf -a NSHipster
上面的命令將附加到 NSHipster 程序,運(yùn)行15秒,分析內(nèi)存分配和泄露,然后將結(jié)果寫入perf文件。之后輸出結(jié)果可以通過 Instruments.app 讀取和顯示。
xed
這個(gè)命令可以簡(jiǎn)單地打開 Xcode。
$ xed NSHipster.xcworkspace
通過傳遞 -w 參數(shù),xed 將等待直到所有打開的窗口關(guān)閉。對(duì)于腳本化用戶交互非常有用,例如提示用戶編輯文件并繼續(xù)一旦完成。
agvtool
agvtool 用于讀取和寫入 Xcode工程 Info.plist 中的版本號(hào)。
$ agvtool what-version
返回當(dāng)前版本
$ agvtool next-version
累加 CURRENT_PROJECT_VERSION 和 DYLIB_CURRENT_VERSION。傳遞 -all 選項(xiàng)將更新 Info.plist 中的 CFBundleVersion。
其他工具
除了上述的 Xcode 工具以外,還有一些其他用 xcrun 調(diào)用的程序:
編譯 & 匯編
- clang: 編譯 C、C++、Objective-C和 Objective-C 源文件。
- lldb: 調(diào)試C、C++、Objective-C 和 Objective-C 程序
- nasm: 匯編文件
- ndisasm: 反匯編文件
- symbols: 顯示一個(gè)文件或者進(jìn)程的符號(hào)信息。
- strip: 刪除或修改符號(hào)表附加到匯編器和鏈接編輯器的輸出。
- atos: 將數(shù)字內(nèi)存地址轉(zhuǎn)換為二進(jìn)制映像或進(jìn)程的符號(hào)。
處理器
-
unifdef: 從代碼中移除條件宏
#ifdef。 - ifnames: 在 C++ 文件中找出所有條件。
庫
- ld: 將目標(biāo)文件和庫合并成一個(gè)文件。
- otool: 顯示目標(biāo)文件或庫的指定部分。
- ar: 創(chuàng)建和維護(hù)庫文檔。
-
libtool: 使用鏈接器
ld創(chuàng)建庫。 - ranlib: 更新歸檔庫的目錄。
- mksdk: 創(chuàng)建和更新 SDK。
- lorder: 列出目標(biāo)文件的依賴。
腳本
- sdef: 腳本定義提取器
- sdp: 腳本定義處理器
- desdp: 腳本定義生成器
- amlint: 檢查 Automator 對(duì)問題的操作
打包
- installer: 安裝 OS X 包。
- pkgutil: 讀取和操縱 OS X 包。
- lsbom: 列出 bom(Bill of Mterials)內(nèi)容。
文檔
- headerdoc: 處理頭文檔。
-
gatherheaderdoc: 編譯和鏈接
headerdoc輸出。 -
headerdoc2html: 從
headerdoc輸出生成 HTML。 -
hdxml2manxml: 從
headerdocXML 輸出翻譯成被xml2man使用的文件。 -
xml2man: 將
Man Page Generation Language(MPGL)XML文件轉(zhuǎn)換為手冊(cè)頁。
Core Data
-
momc: 編譯
Managed Object Model(.mom)文件 -
mapc: 編譯
Core Data Mapping Model(.xcmappingmodel)文件
第三方工具
appledoc
Cocoa 開發(fā)人員認(rèn)為 Objective-C 的冗長(zhǎng)有助于自注釋代碼。在 longMethodNamesWithNamedParameters: 和 明確的參數(shù)類型。Objective-C 方法不會(huì)留下太多的想象力。
但是即使自注釋代碼也可以通過文檔來改進(jìn),只用少量的努力就能夠?qū)λ水a(chǎn)生顯著的益處。
在 Objective-C 中,選擇的文檔工具是 appledoc。使用 javadoc 類似的語法,appledoc 能夠從 .h文件生成 HTML 和 Xcode 兼容的 .docset 文檔,看起來幾乎和蘋果官方文檔完全相同。
Objective-C 文檔由任何 @interface 或 @protocol 之前的 /** */ 注釋塊(注意額外的初始星號(hào))以及任何方法或 @property 聲明指定。文檔還可能包含系統(tǒng)字段的標(biāo)簽,如參數(shù)或返回值:
- @param [param] [Description]: 描述應(yīng)傳遞什么值或此參數(shù)
- @return [Description]: 描述方法的返回值
- @see [selector]: 提供 『參見』相關(guān)項(xiàng)目的參考
- @discussion [Discussion]: 提供額外的背景資料
- @warning [Description]: 調(diào)用異?;驖撛诘奈kU(xiǎn)行為
appledoc 可以通過以下命令安裝:
$ brew install appledoc
要生成文檔,需要在 Xcode 工程的根目錄下執(zhí)行 appledoc 命令,傳遞元數(shù)據(jù)比如工程名和公司名:
$ appledoc --project-name CFHipsterRef --project-company "NSHipster" --company-id com.nshipster --output ~/Documents .
從目標(biāo)目錄中找到的頭文件中生成并安裝一個(gè)Xcode .docset文件。
通過傳遞 --help 參數(shù)可以找到其他配置選項(xiàng)(包括HTML輸出):
$ appledoc --help
xctool
它可以直接替代 xcodebuild,也就是 Xcode.app 自己所依賴的底層工具。
我們自己作為蘋果硬件和軟件的消費(fèi)者,都清楚設(shè)計(jì)的重要性怎么強(qiáng)調(diào)都不為過。在這個(gè)方面,xctool 做得非常漂亮。構(gòu)建過程的每一步都經(jīng)過清晰的組織,使用 ANSI 彩色字符和一系列 Unicode 裝飾字符,使得表現(xiàn)的方式既容易理解又具有視覺吸引力,同時(shí) xctool 的美麗不僅僅體現(xiàn)了表面:構(gòu)建過程同樣支持以其他工具可讀取的格式進(jìn)行輸出:
$ xctool -reporter plain:output.txt build
- pretty: (默認(rèn)) 一個(gè)文字化的輸出器,使用 ANSI 顏色和 unicode 符號(hào)來進(jìn)行美化輸出。
- plain: 類似 pretty, 不過沒有顏色和 Unicode。
- phabricator: 把構(gòu)建/測(cè)試的結(jié)果輸出為 JSON 數(shù)組,它可以被 Phabricator 的代碼評(píng)審工具讀取。
- junit: 把測(cè)試結(jié)果輸出成和 JUnit/xUnit 兼容的 XML 文件。
- json-stream: 一個(gè)由構(gòu)建/測(cè)試事件組成的 JSON 字典流,每行一個(gè)(示例輸出)。
- json-compilation-database: 輸出構(gòu)建事件的 JSON Compilation Database ,它可以用于基于 Clang Tooling 的工具,例如 OCLint.
xctool 相對(duì)于 xcodebuild 另一個(gè)主要的進(jìn)步是,xctool 可以和 Xcode.app 一樣執(zhí)行應(yīng)用測(cè)試(xcodebuild 不能區(qū)分項(xiàng)目 scheme 中哪些是測(cè)試使用的 target,更不用說在模擬器中執(zhí)行測(cè)試了)。
僅僅因?yàn)檫@一個(gè)原因,xctool 就深刻地影響了 Objective-C 社區(qū)中新興的持續(xù)集成測(cè)試的規(guī)范。
通過以下命令安裝 xctool:
$ brew install xctool
OCLint
OCLint 是一個(gè)靜態(tài)代碼分析工具,可以檢查 Objective-C(也支持 C 和 C++)代碼中常見的問題,例如空的 if/else/try/catch/finally 語句,未使用的本地變量和參數(shù),大量復(fù)雜的沒有注釋的(NCSS),具有圈復(fù)雜度或者 NPath 復(fù)雜度的代碼,冗余的代碼,代碼“異味”,以及其他的不好的代碼實(shí)踐。
安裝 OCLint 最好的方式是通過 Homebrew Cask:
$ brew cask install oclint
還記得 xctool 的 json-compilation-database 輸出選項(xiàng)嗎?它的輸出可以直接 被 OCLint 讀取,供它進(jìn)行魔法一般的靜態(tài)分析。
$ xctool -workspace NSHipster.xcworkspace -scheme "NSHipster" -reporter json-compilation-database build > compile_commands.json
$ oclint-json-compilation-database
xcpretty
xcpretty 類似于 xctool,改進(jìn)了 xcodebuild 的構(gòu)建輸出,但是 xcpretty 不是嘗試替換 xcodebuild,而是擴(kuò)展并改進(jìn)它。
實(shí)際上,xcpretty 通過獲取 xcodebuild 的管道輸出而不是直接調(diào)用,充分體現(xiàn)了 Unix的可組合性理念:
$ xcodebuild [flags] | xcpretty -c
這種方法的一個(gè)主要好處是它真的很快——事實(shí)上,在某些情況下,xcpretty 實(shí)際上比直接調(diào)用 xcodebuild 快一點(diǎn),因?yàn)樗?jié)省了打印到控制臺(tái)的時(shí)間。
與 xctool 的另一個(gè)共性是報(bào)告器功能,其具有格式化輸出到JUnit風(fēng)格的XML、HTML或上述OCTool 兼容的 json編譯數(shù)據(jù)庫格式。
xcpretty 通過 RubyGems 安裝:
$ gem install xcpretty
Nomad
Nomad 是用于 iOS 和 OS X 開發(fā)的世界級(jí)命令行實(shí)用程序的集合。它自動(dòng)化常見的管理任務(wù),以便開發(fā)人員可以專注于構(gòu)建和傳輸軟件。
每個(gè)工具可以單獨(dú)安裝,也可以一起安裝:
$ gem install nomad-cli
Cupertino
應(yīng)用程序 Provisioning 流程普遍被蘋果開發(fā)人員厭惡。
除了整個(gè)過程是一個(gè)從開始到完成的噩夢(mèng),許多操作需要通過 Web 界面進(jìn)行交互。不僅需要大量的額外點(diǎn)擊,但使得它非常不自動(dòng)化。
Cupertino 提供一個(gè)命令行工具管理設(shè)備、provisioning pro?le、app ID 和證書。
$ ios devices:list
+------------------------------+---------------------------------------+
|
Listing 2 devices. You can register 98 additional devices.
|
+---------------------------+------------------------------------------+
| Device Name
| Device Identifier
|
+---------------------------+------------------------------------------+
| Johnny Appleseed iPad
| 0123456789012345678901234567890123abcdef |
| Johnny Appleseed iPhone
| abcdef0123456789012345678901234567890123 |
+---------------------------+------------------------------------------+
$ ios devices:add "iPad 1"=abc123
$ ios devices:add "iPad 2"=def456 "iPad 3"=ghi789 ...
通過以下命令單獨(dú)安裝:
$ gem install cupertino
Shenzhen
Web 開發(fā)人員在 iOS 上的對(duì)應(yīng)部分是能夠在幾秒鐘內(nèi)持續(xù)部署代碼,而不是等待幾天 Capertino 批準(zhǔn)(有時(shí)拒絕?。└隆?/p>
幸運(yùn)的是,一個(gè)圍繞著開發(fā)和企業(yè)分發(fā)的新興產(chǎn)業(yè)已經(jīng)興起。第三方服務(wù)像 HockeyApp、DeployGate 和 TestFlight 提供給開發(fā)者更容易的范式注冊(cè)測(cè)試用戶和發(fā)送最新構(gòu)建給QA。
Shenzhen 是進(jìn)一步自動(dòng)化此過程的工具,通過構(gòu)建 .ipa文件,然后發(fā)布到 FTP/SFTP服務(wù)器、S3 存儲(chǔ)或者其他任何上述第三方服務(wù)。
$ cd /path/to/iOS Project/
$ ipa build
$ ipa distribute:sftp --host HOST -u USER -p PASSWORD -P FTP_PATH
Houston
Houston 是一個(gè)簡(jiǎn)單的工具發(fā)送蘋果推送通知。傳遞憑據(jù)、構(gòu)造消息并將其發(fā)送到設(shè)備。
$ apn push "<token>" -c /path/to/apple_push_notification.pem -m "Hello from the command line!"
這個(gè)工具對(duì)測(cè)試遠(yuǎn)程推送非常有用——尤其是在新應(yīng)用中實(shí)現(xiàn)該功能。
Venice
不管怎樣應(yīng)用內(nèi)購買已經(jīng)成為app開發(fā)者最有利的商業(yè)模式。有了這么多,對(duì)某人的生活而言確保這些購買的有效性是首要的。
Venice 是一個(gè)命令行程序,用于驗(yàn)證 Apple 應(yīng)用內(nèi)購買收據(jù),并檢索與收據(jù)數(shù)據(jù)相關(guān)的信息。
$ iap verify /path/to/receipt
+-----------------------------+-------------------------------+
|
Receipt
|
+-----------------------------+-------------------------------+
| app_item_id
|
|
| bid
| com.foo.bar
|
| bvrs
| 20120427
|
| original_purchase_date
| Sun, 01 Jan 2013 12:00:00 GMT |
| original_transaction_id
| 1000000000000001
|
| product_id
| com.example.product
|
| purchase_date
| Sun, 01 Jan 2013 12:00:00 GMT |
| quantity
| 1
|
| transaction_id
| 1000000000000001
|
| version_external_identifier |
|
+-----------------------------+-------------------------------+
像 Houston、Venice有一個(gè)客戶端庫組件,允許它部署在 Rails或 Sinatra應(yīng)用程序上。驗(yàn)證服務(wù)器上的收據(jù)允許保留他們自己的過去購買記錄,這對(duì)于最新的指標(biāo)和歷史分析是有用的。因此,任何人關(guān)于IAP需要認(rèn)真對(duì)待是推薦的做法。
Dubai
Passbook 管理登機(jī)牌、電影票、零售優(yōu)惠券和會(huì)員卡。使用 PassKit API,開發(fā)人員可以注冊(cè) Web 服務(wù)自動(dòng)更新 Passbook的內(nèi)容,例如登機(jī)牌上的登機(jī)口更改或會(huì)員卡添加積分。
Dubai可以很容易地從腳本或命令行生成 .pkpass 文件,允許快速迭代你的 pass 的設(shè)計(jì)和內(nèi)容,或者在空中生成一次性的。
$ pk generate Example.pass -T boarding-pass
一旦生成了通行證,它可以用 Dubai 創(chuàng)建本地 HTTP 服務(wù),允許通行證在 iOS 模擬器中實(shí)時(shí)預(yù)覽:
$ pk serve Example.pass -c /path/to/certificate.p12
$ open http://localhost:4567/pass.pkpass