Xcode构建过程的后台工作(一)(WWDC2018 Behind the Scenes of the Xcode Build Process字幕搬运)

Xcode构建过程的后台工作(WWDC2018字幕搬运)

原文传送门

Xcode构建过程的后台工作(二)clang构建
Xcode构建过程的后台工作(三)swift构建
Xcode构建过程的后台工作(四)链接

什么是构建过程

在构建app的时候,从源代码和项目资源开始,到提供给客户的打包文件或者上传到AppStore,要经过很多步骤。你要编译和链接源码,复制和处理资源,比如头文件、资源目录和storyboard,最后是代码签名及自定义脚本或者make文件,比如给框架构建API文件、运行代码检查和验证工具等等。大多数任务在构建过程中由命令行工具运行,比如Clang,LD,AC工具,IB工具,代码符号等。这些工具等执行,需要一组特定的实参,以特定的顺序,基于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]

构建系统的作用,就是将每次构建的任务的执行部署自动化,由于任务数量成千上万,构建过程更是数不胜数,依赖关系十分复杂,你肯定不想手动输入,1天敲100遍命令,那就让构建系统帮你做。

构建任务执行顺序

构建任务的执行顺序取决于信息的依赖关系,就是任务,任务需要的输入,和任务生产的输出。以编译任务为例,它需要输入源代码文件,如PetViewController.m,然后输出目标文件,比如PetViewController.o。

image.png

同样,链接服务需要几个目标文件,这些文件由编译器在上个任务中生成,再生成可执行或lib文件,比如PetWall运行文件,会存到.app资源文件包。

image.png

你能看到信息的依赖关系,是顺着下图的走向,最终形成执行顺序。

image.png

现在大家关注下图中的编译任务,很像川流不息的马路,你看得到编译任务在各自的路上并行运行互不干涉。因为链接器任务需要所有的其他输入,所以它要在最后一位。

通过依赖关系构建系统

构建系统的第一步是获取构建描述,Xcode项目文件,解析项目中的所有文件,目标app和依赖关系,构建设置。转换成一个树形结构叫做定向图,它显示了所有的依赖关系,项目中的输入和输出文件,以及处理他们的执行任务。

image.png

然后低级执行引擎会处理这张图,研究依赖关系,决定执行哪个任务,执行顺序是什么,以及哪些可以平行运行,然后继续执行任务。这里的低级执行引擎是新构建系统的叫做llbuild,他是开源的,用GitHub开发。如果对构建系统有兴趣,请随意研究,看看它如何工作。它的链接和另一个关于构建系统的开源模块会在最后提到。

image.png

现在讲讲已知的依赖关系。由于你无法获取太多的依赖关系信息,构建系统在任务的执行过程中可能会找到更多信息。比如clang编译oc文件时会生成目标文件,但是它也会生成另一个文件,其中包含一个列出源文件中头文件的列表,那么下次构建时,构建系统会使用这个文件中的信息,以保证当你你改了其中任何头文件时会再次编译源文件。

image.png

这里的关系路径是PetController.h,PetController.d,.m直到.o文件。

image.png

构建系统的主要工作就是执行任务。当然项目越大,构建时间越长。你肯定不想在每次运行的时候把所有任务都运行一遍。构建系统实际上可以只执行定向图上的任务子集,基于你对于项目的更改,对比你上次的构建,我们称之为累加构建。

image.png
image.png

准确的依赖关系十分重要,这样累加构建才能正确高效的工作。下面看看哪些更改会影响构建系统,以及与累加构建的关系。

更改检测和任务签名

构建过程中的每个任务都有相应的签名,类似于Hash,通过计算多个任务相关信息而得出。这些信息包括任务输入的统计信息,比如文件路径和更改时间标签,运行命令的命令行指示,以及其他有关任务的元数据,比如编译器版本。构建系统会追踪当前和之前的任务签名,所以它知道每次构建时是否需要重新运行任务。如果某个任务的签名与上次构建时不同,它就会重新运行这个任务,如果相同就会跳过,这就是累加构建的概念。

如何利用构建系统

我们大概了解了构建过程的定义和流程,那么如何利用构建系统呢?先回顾下基本知识。构建系统按照一定顺序执行一系列任务,但要记得构建过程以定向图表示。我们不用担心任务执行的顺序,这是构建系统的工作。作为开发者,我们需要考虑的是任务之间的依赖关系,让构建系统根据定向图结构决定最佳的执行方法。这样构建系统可以正确地给任务排序,可能的时候并行运行,以完全利用多核硬件

image.png

依赖关系的来源

对于某些任务,依赖关系来自构建系统自带的数据。构建系统自带一些规则,比如编译器,链接器,资源目录,storyboard处理器等等。这些规则定义了哪些是输入文件,和哪些是输出文件。

还有目标依赖关系(target dependencies),大致决定了目标构建顺序。有些时候,构建系统可以编译不同目标和平行文件,之前的Xcode要构建一个app就要完成整个app的构建,然后才能使用。Xcode 10的新构建系统就要快得多,编译源阶段会提前开始,免费提供并行。但是,如果含有任何运行脚本阶段,这些阶段完成后,并行才能开始。有关依赖的还有隐形依赖关系(Implicit dependencies),例如,如果您在链接库中列出目标时,在方案编辑器中启用了二进制构建阶段和隐式依赖项(这是默认开启的),那么即使它未在目标中列出,构建系统也将建立对该目标的隐式依赖关系。

接下来是构建阶段依赖(Build phase dependencies)。在目标编辑器里,你会看到几个构建阶段,复制头文件、编译源、复制资源包等等。这些任务与每个阶段相关,通常根据阶段的排列顺序按组运行。如果有更好的方案,构建系统也许会忽略它,例如第三方静态库阶段,在编译源之前。注意有的时候构建阶段顺序不对会导致问题或者构建失败,因此请确保了解您的依赖关系并验证构建阶段是否正确。

还有scheme顺序依赖。如果在scheme设置里开启了并行构建检查,构建性能会更好,不用担心目标顺序。但是如果关闭并行构建,Xcode构建目标时会按照你排列的构建行动顺序逐个构建,目标依赖关系优先级较高,优先决定第一个构建目标,但Xcode会遵从这个排列。这让人跃跃欲试,因为它给出了可预期的构建顺序,即使依赖关系有误。但这样会牺牲大量并行空间,延缓构建速度。所以我们推荐开启并行构建,正确设置依赖关系,不要依赖排序。

最后,依赖关系取决于开发者。你可以自定义shell脚本构建阶段或规则,明确告诉系统输入和输出是什么,以避免重复运行不必要的脚本任务,保证正确执行顺序。你可以用运行脚本阶段编辑器定义输入和输出,这些文件路径将作为环境变量在脚本中激活。不要依赖项目里目标依赖关系的自动连接。Clang编译器里有自动关联功能,在构建设置中自动使用关联框架。让编译器自动链接框架对应导入的模块,不用在链接库的构建阶段再明确表示。但是要注意自动关联不会在构建系统层级建立依赖关系,所以它不能保证依赖的目标在关联之前已经建好。所以它只适用于STK平台的框架,例如Foundation或者UIKit,因为我们知道它们在构建前就已经存在。你自己项目里的目标,要保证明确的库依赖关系。你也许需要创建项目引用,将另一个Xcode项目拖放到项目文件导航,说明与其他项目的目标文件的依赖关系。

总结来说,有了准确的依赖关系,构建系统就能更好的并行构建任务,保证每次的构建结果一致。这样就能减少构建用时,给开发多点时间。想知道更多快速构建的内容,如何最大化利用新的iMac pro内核,推荐观看演讲《用Xcode加速构建过程》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容