Xcode構(gòu)建過程的后臺工作(一)(WWDC2018 Behind the Scenes of the Xcode Build Process字幕搬運)

Xcode構(gòu)建過程的后臺工作(WWDC2018字幕搬運)

原文傳送門

Xcode構(gòu)建過程的后臺工作(二)clang構(gòu)建
Xcode構(gòu)建過程的后臺工作(三)swift構(gòu)建
Xcode構(gòu)建過程的后臺工作(四)鏈接

什么是構(gòu)建過程

在構(gòu)建app的時候逸尖,從源代碼和項目資源開始丁稀,到提供給客戶的打包文件或者上傳到AppStore溯警,要經(jīng)過很多步驟。你要編譯和鏈接源碼沮明,復(fù)制和處理資源,比如頭文件堕油、資源目錄和storyboard女气,最后是代碼簽名及自定義腳本或者make文件,比如給框架構(gòu)建API文件捣作、運行代碼檢查和驗證工具等等誉结。大多數(shù)任務(wù)在構(gòu)建過程中由命令行工具運行,比如Clang券躁,LD惩坑,AC工具,IB工具也拜,代碼符號等以舒。這些工具等執(zhí)行,需要一組特定的實參慢哈,以特定的順序蔓钟,基于Xcode項目配置。


$ swiftc -module-name PetWall -target arm64-apple-ios12.0 -swift-version 4.2 ...

$ clang -x objective-c -arch arm64 ... PetViewController.m -o PetViewController.o

$ ld -o PetWall -framework PetKit PetViewController.o ...

$ actool --app-icon AppIcon ... Assets.xcassets

$ ...

$ [thousands more]

構(gòu)建系統(tǒng)的作用卵贱,就是將每次構(gòu)建的任務(wù)的執(zhí)行部署自動化滥沫,由于任務(wù)數(shù)量成千上萬,構(gòu)建過程更是數(shù)不勝數(shù)键俱,依賴關(guān)系十分復(fù)雜兰绣,你肯定不想手動輸入,1天敲100遍命令编振,那就讓構(gòu)建系統(tǒng)幫你做狭魂。

構(gòu)建任務(wù)執(zhí)行順序

構(gòu)建任務(wù)的執(zhí)行順序取決于信息的依賴關(guān)系,就是任務(wù)党觅,任務(wù)需要的輸入雌澄,和任務(wù)生產(chǎn)的輸出。以編譯任務(wù)為例杯瞻,它需要輸入源代碼文件镐牺,如PetViewController.m,然后輸出目標(biāo)文件魁莉,比如PetViewController.o睬涧。

image.png

同樣,鏈接服務(wù)需要幾個目標(biāo)文件旗唁,這些文件由編譯器在上個任務(wù)中生成畦浓,再生成可執(zhí)行或lib文件,比如PetWall運行文件检疫,會存到.app資源文件包讶请。

image.png

你能看到信息的依賴關(guān)系,是順著下圖的走向屎媳,最終形成執(zhí)行順序夺溢。

image.png

現(xiàn)在大家關(guān)注下圖中的編譯任務(wù)论巍,很像川流不息的馬路,你看得到編譯任務(wù)在各自的路上并行運行互不干涉风响。因為鏈接器任務(wù)需要所有的其他輸入嘉汰,所以它要在最后一位。

通過依賴關(guān)系構(gòu)建系統(tǒng)

構(gòu)建系統(tǒng)的第一步是獲取構(gòu)建描述状勤,Xcode項目文件鞋怀,解析項目中的所有文件,目標(biāo)app和依賴關(guān)系持搜,構(gòu)建設(shè)置接箫。轉(zhuǎn)換成一個樹形結(jié)構(gòu)叫做定向圖,它顯示了所有的依賴關(guān)系朵诫,項目中的輸入和輸出文件辛友,以及處理他們的執(zhí)行任務(wù)。

image.png

然后低級執(zhí)行引擎會處理這張圖剪返,研究依賴關(guān)系废累,決定執(zhí)行哪個任務(wù),執(zhí)行順序是什么脱盲,以及哪些可以平行運行邑滨,然后繼續(xù)執(zhí)行任務(wù)。這里的低級執(zhí)行引擎是新構(gòu)建系統(tǒng)的叫做llbuild钱反,他是開源的掖看,用GitHub開發(fā)。如果對構(gòu)建系統(tǒng)有興趣面哥,請隨意研究哎壳,看看它如何工作。它的鏈接和另一個關(guān)于構(gòu)建系統(tǒng)的開源模塊會在最后提到尚卫。

image.png

現(xiàn)在講講已知的依賴關(guān)系归榕。由于你無法獲取太多的依賴關(guān)系信息,構(gòu)建系統(tǒng)在任務(wù)的執(zhí)行過程中可能會找到更多信息吱涉。比如clang編譯oc文件時會生成目標(biāo)文件刹泄,但是它也會生成另一個文件,其中包含一個列出源文件中頭文件的列表怎爵,那么下次構(gòu)建時特石,構(gòu)建系統(tǒng)會使用這個文件中的信息,以保證當(dāng)你你改了其中任何頭文件時會再次編譯源文件鳖链。

image.png

這里的關(guān)系路徑是PetController.h姆蘸,PetController.d,.m直到.o文件。

image.png

構(gòu)建系統(tǒng)的主要工作就是執(zhí)行任務(wù)乞旦。當(dāng)然項目越大,構(gòu)建時間越長题山。你肯定不想在每次運行的時候把所有任務(wù)都運行一遍兰粉。構(gòu)建系統(tǒng)實際上可以只執(zhí)行定向圖上的任務(wù)子集,基于你對于項目的更改顶瞳,對比你上次的構(gòu)建玖姑,我們稱之為累加構(gòu)建。

image.png
image.png

準(zhǔn)確的依賴關(guān)系十分重要慨菱,這樣累加構(gòu)建才能正確高效的工作焰络。下面看看哪些更改會影響構(gòu)建系統(tǒng),以及與累加構(gòu)建的關(guān)系符喝。

更改檢測和任務(wù)簽名

構(gòu)建過程中的每個任務(wù)都有相應(yīng)的簽名闪彼,類似于Hash,通過計算多個任務(wù)相關(guān)信息而得出协饲。這些信息包括任務(wù)輸入的統(tǒng)計信息畏腕,比如文件路徑和更改時間標(biāo)簽,運行命令的命令行指示茉稠,以及其他有關(guān)任務(wù)的元數(shù)據(jù)描馅,比如編譯器版本。構(gòu)建系統(tǒng)會追蹤當(dāng)前和之前的任務(wù)簽名而线,所以它知道每次構(gòu)建時是否需要重新運行任務(wù)铭污。如果某個任務(wù)的簽名與上次構(gòu)建時不同,它就會重新運行這個任務(wù)膀篮,如果相同就會跳過嘹狞,這就是累加構(gòu)建的概念。

如何利用構(gòu)建系統(tǒng)

我們大概了解了構(gòu)建過程的定義和流程誓竿,那么如何利用構(gòu)建系統(tǒng)呢刁绒?先回顧下基本知識。構(gòu)建系統(tǒng)按照一定順序執(zhí)行一系列任務(wù)烤黍,但要記得構(gòu)建過程以定向圖表示知市。我們不用擔(dān)心任務(wù)執(zhí)行的順序,這是構(gòu)建系統(tǒng)的工作速蕊。作為開發(fā)者嫂丙,我們需要考慮的是任務(wù)之間的依賴關(guān)系,讓構(gòu)建系統(tǒng)根據(jù)定向圖結(jié)構(gòu)決定最佳的執(zhí)行方法规哲。這樣構(gòu)建系統(tǒng)可以正確地給任務(wù)排序跟啤,可能的時候并行運行,以完全利用多核硬件

image.png

依賴關(guān)系的來源

對于某些任務(wù),依賴關(guān)系來自構(gòu)建系統(tǒng)自帶的數(shù)據(jù)隅肥。構(gòu)建系統(tǒng)自帶一些規(guī)則竿奏,比如編譯器,鏈接器腥放,資源目錄泛啸,storyboard處理器等等。這些規(guī)則定義了哪些是輸入文件秃症,和哪些是輸出文件候址。

還有目標(biāo)依賴關(guān)系(target dependencies),大致決定了目標(biāo)構(gòu)建順序种柑。有些時候岗仑,構(gòu)建系統(tǒng)可以編譯不同目標(biāo)和平行文件,之前的Xcode要構(gòu)建一個app就要完成整個app的構(gòu)建聚请,然后才能使用荠雕。Xcode 10的新構(gòu)建系統(tǒng)就要快得多,編譯源階段會提前開始驶赏,免費提供并行舞虱。但是,如果含有任何運行腳本階段母市,這些階段完成后矾兜,并行才能開始。有關(guān)依賴的還有隱形依賴關(guān)系(Implicit dependencies)患久,例如椅寺,如果您在鏈接庫中列出目標(biāo)時,在方案編輯器中啟用了二進制構(gòu)建階段和隱式依賴項(這是默認開啟的)蒋失,那么即使它未在目標(biāo)中列出返帕,構(gòu)建系統(tǒng)也將建立對該目標(biāo)的隱式依賴關(guān)系。

接下來是構(gòu)建階段依賴(Build phase dependencies)篙挽。在目標(biāo)編輯器里荆萤,你會看到幾個構(gòu)建階段,復(fù)制頭文件铣卡、編譯源链韭、復(fù)制資源包等等。這些任務(wù)與每個階段相關(guān)煮落,通常根據(jù)階段的排列順序按組運行敞峭。如果有更好的方案,構(gòu)建系統(tǒng)也許會忽略它蝉仇,例如第三方靜態(tài)庫階段旋讹,在編譯源之前殖蚕。注意有的時候構(gòu)建階段順序不對會導(dǎo)致問題或者構(gòu)建失敗,因此請確保了解您的依賴關(guān)系并驗證構(gòu)建階段是否正確沉迹。

還有scheme順序依賴睦疫。如果在scheme設(shè)置里開啟了并行構(gòu)建檢查,構(gòu)建性能會更好鞭呕,不用擔(dān)心目標(biāo)順序蛤育。但是如果關(guān)閉并行構(gòu)建,Xcode構(gòu)建目標(biāo)時會按照你排列的構(gòu)建行動順序逐個構(gòu)建琅拌,目標(biāo)依賴關(guān)系優(yōu)先級較高缨伊,優(yōu)先決定第一個構(gòu)建目標(biāo)摘刑,但Xcode會遵從這個排列进宝。這讓人躍躍欲試,因為它給出了可預(yù)期的構(gòu)建順序枷恕,即使依賴關(guān)系有誤党晋。但這樣會犧牲大量并行空間,延緩構(gòu)建速度徐块。所以我們推薦開啟并行構(gòu)建未玻,正確設(shè)置依賴關(guān)系,不要依賴排序胡控。

最后扳剿,依賴關(guān)系取決于開發(fā)者。你可以自定義shell腳本構(gòu)建階段或規(guī)則昼激,明確告訴系統(tǒng)輸入和輸出是什么庇绽,以避免重復(fù)運行不必要的腳本任務(wù),保證正確執(zhí)行順序橙困。你可以用運行腳本階段編輯器定義輸入和輸出瞧掺,這些文件路徑將作為環(huán)境變量在腳本中激活。不要依賴項目里目標(biāo)依賴關(guān)系的自動連接凡傅。Clang編譯器里有自動關(guān)聯(lián)功能辟狈,在構(gòu)建設(shè)置中自動使用關(guān)聯(lián)框架。讓編譯器自動鏈接框架對應(yīng)導(dǎo)入的模塊夏跷,不用在鏈接庫的構(gòu)建階段再明確表示哼转。但是要注意自動關(guān)聯(lián)不會在構(gòu)建系統(tǒng)層級建立依賴關(guān)系,所以它不能保證依賴的目標(biāo)在關(guān)聯(lián)之前已經(jīng)建好槽华。所以它只適用于STK平臺的框架释簿,例如Foundation或者UIKit,因為我們知道它們在構(gòu)建前就已經(jīng)存在硼莽。你自己項目里的目標(biāo)庶溶,要保證明確的庫依賴關(guān)系煮纵。你也許需要創(chuàng)建項目引用,將另一個Xcode項目拖放到項目文件導(dǎo)航偏螺,說明與其他項目的目標(biāo)文件的依賴關(guān)系行疏。

總結(jié)來說,有了準(zhǔn)確的依賴關(guān)系套像,構(gòu)建系統(tǒng)就能更好的并行構(gòu)建任務(wù)酿联,保證每次的構(gòu)建結(jié)果一致。這樣就能減少構(gòu)建用時夺巩,給開發(fā)多點時間贞让。想知道更多快速構(gòu)建的內(nèi)容,如何最大化利用新的iMac pro內(nèi)核柳譬,推薦觀看演講《用Xcode加速構(gòu)建過程》喳张。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市美澳,隨后出現(xiàn)的幾起案子销部,更是在濱河造成了極大的恐慌,老刑警劉巖制跟,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舅桩,死亡現(xiàn)場離奇詭異,居然都是意外死亡雨膨,警方通過查閱死者的電腦和手機擂涛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來聊记,“玉大人撒妈,你說我怎么就攤上這事∩瘢” “怎么了踩身?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長社露。 經(jīng)常有香客問我挟阻,道長,這世上最難降的妖魔是什么峭弟? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任附鸽,我火速辦了婚禮,結(jié)果婚禮上瞒瘸,老公的妹妹穿的比我還像新娘坷备。我一直安慰自己,他們只是感情好情臭,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布省撑。 她就那樣靜靜地躺著赌蔑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪竟秫。 梳的紋絲不亂的頭發(fā)上娃惯,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機與錄音肥败,去河邊找鬼趾浅。 笑死,一個胖子當(dāng)著我的面吹牛馒稍,可吹牛的內(nèi)容都是我干的皿哨。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼纽谒,長吁一口氣:“原來是場噩夢啊……” “哼证膨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起佛舱,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤椎例,失蹤者是張志新(化名)和其女友劉穎挨决,沒想到半個月后请祖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡脖祈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年肆捕,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盖高。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡慎陵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出喻奥,到底是詐尸還是另有隱情席纽,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布撞蚕,位于F島的核電站润梯,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏甥厦。R本人自食惡果不足惜纺铭,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望刀疙。 院中可真熱鬧舶赔,春花似錦、人聲如沸谦秧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至锥累,卻和暖如春征懈,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背揩悄。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工卖哎, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人删性。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓亏娜,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蹬挺。 傳聞我的和親對象是個殘疾皇子维贺,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容