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

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

构建过程:Swift构建

我们现在将深入研究Swift和构建系统如何协同工作以在项目中查找声明。Clang单独编译了每个Objective-C文件。这意味着如果要在另一个文件夹中 查找一个类,则必须导入声明该类的头文件。但Swift的设计不需要写入头文件。这使初学者更容易上手该语言。 并避免了在不同文件中重复一个声明。但这意味着编译器必须执行一些额外的记录工作。下面讲讲记录工作如何运作。让我们回到示例PetWall应用程序。


image.png

该应用程序在ViewCcontroller中 有一个Swift界面。Objective-C app代理,和Swift单元测试。 为了编译哪怕只是上面这个PetViewController部分,编译器也要执行四种不同的运算。首先,它必须找到声明,既可以在Swift目标内,也可以来自Objective-C。此外,它还要生成描述文件内容的 接口。这样它的声明就可以被Objective-C和其他Swift目标中找到并使用。 在接下来的部分中,我将通过这个例子来分别阐述这四个任务。首先是在Swift目标中查找声明。编译PetViewController.swift时,编译器会查找 PetView初始程序类型,以便检查调用。但在此之前,它要解析PetView.swift并验证它,以确保初始程序的声明是正常的。


image.png

编译器很聪明 ,它知道它不需要检查初始程序的主体。但它仍然需要做一些工作去处理文件的接口部分。这与Clang不同,编译一个Swift文件时,编译器将解析目标中的所有其他Swift文件,以检查与接口相关的部分。
image.png

在Xcode 9中,这导致了在增量调试构建中的一些重复工作。因为编译器单独编译每个文件。文件能够并行编译,但它强制编译器重复解析每个文件。解析一次作为实现文件产生一个.o,解析多次是作为接口来查找声明。


image.png

Xcode 10减少了这种开销。它通过将文件合并成组,在依旧最大化并行的同时,尽可能多地共享工作来实现。
image.png

在组中重复利用解析,只在跨组处理时重复。由于组的数量通常相对较低,因此 可以显著加快增量调试构建。
image.png

从Objective-C中查找声明

Swift代码不仅调用其他Swift代码。 它也可以调用Objective-C。回到我们的PetWall示例应用程序,我们可以看到,这是至关重要的,因为UIKit等系统框架是用Objective-C编写的。Swift与其他语言不同,它不需要外部功能 接口。例如,您必须编写Swift声明给每个Objective-C API。但是,编译器内置了Clang的一大部分,并将其用作库。这样就可以直接导入Objective-C框架。


image.png

那么Objective-C声明来自哪里?导入器会根据目标的类型查找头文件。任何目标在导入Objective-C框架时,导入器在头文件中查找声明,以显示该框架的 Clang模块映射。在Swift和Objective-C代码混编的框架内,导入器在umbrella头文件中查找声明。这个头文件定义了公共接口。这样,框架内的Swift代码可以调用同一框架中公共Objective-C代码。最后,在您的应用和 单元测试中,可以导入目标的桥接头文件,允许其中的声明被Swift调用。


image.png

当导入器找到声明时,通常会修改它们,让它们更口语化。比如它会导入Objective-C方法,用NSError惯用语作为使用Swift的内置错误处理语言功能的throwing方法。特别是它会删除动词和介词后面的参数类型名称。 例如,drawPet:atPoint方法有单词pet,和跟在一个动词draw后的pet类型的参数。


image.png

同样的单词point,代表参数类型CGPoint,后跟介词at。
Swift中省略了这些单词,只导入函数draw at。怎么做到的?编译器包含常用英语动词和介词列表。 因为它只是一个硬编码列表而且人类语言很复杂,有时候它会缺词。
image.png

此外,为了匹配Swift的命名约定,导入器会重命名方法,根据词性删除单词。 例如,动词Feed不在列表中,因此feedPet不会像我们预期的那样作为Feed导入。发生这种情况时,您可以使用 NS_Swift_Name注解让编译器导入你要的方法形式。

如果您想查看如何将Objective-C标头 导入Swift,您可以到Xcode的相关 项目弹出窗口。


image.png

它在源编辑器的左上角。选择生成的接口,就能看到接口在不同版本的Swift中的样子。这就是Swift如何导入Objective-C。

生成在Objective-C中使用的接口

Objective-C中如何导入Swift?答案是Swift会生成一个头文件,可以进行导入。这允许您在Swift中编写类并从Objective-C中调用它们。让我们看看它是如何工作的。编译器将为扩展NSObject的Swift类和@obc标记的方法生成 Objective-C声明。


image.png

对于单元测试的app,头文件会包括公共声明和内部声明。这样就能在app的Objective-C部分使用内部Swift。但是,对于框架,生成的头文件只包含公共声明,因为它包含在构建产品中,是框架的公共接口的一部分。


image.png

在上图右侧,您看到编译器将Objective-C类链接到名字变形的Swift类,该名称包含模块名称PetWall。当两个模块定义了有相同名称的类时,这可以防止运行时发生冲突。 您可以通过将标识符传递给obc属性让Swift重命名Objective-C类。但是如果你这样做,你要确保名称不冲突。在这里,我使用了PWL前缀,以减少冲突的可能性。这样就可以在Objective-C中引用这个类PWLPetCollar 。

编译器采用类似的方法生成其他Swift目标的接口。为此,Swift基于Clang的模块概念进行构建,并且更深层的融入语言。在Swift中,模块是可分布的声明单元。为了能够使用这些声明,您必须导入模块。您可以导入Objective-C模块例如XEtest。在Xcode中,每个Swift目标都会生成一个单独的模块,包括您的app target。所以要导入app的主模块,以便进行单元测试。


image.png

导入模块时, 编译器会反序列化一个特殊的Swift模块文件,在使用它时检查类型。 例如在此单元测试中,编译器将从PetWall Swift模块加载PetViewController,以确保正确创建控制器。这类似于编译器在目标中查找声明的方式。


image.png

除此之外编译器加载一个汇总模块的文件,而不是直接解析Swift 文件。
image.png

编译器生成此Swift模块文件很多就像Objective-C头文件。但它不是文本,而是二进制表示。 它包括内联函数的主体,就像Objective-C中的静态内联函数或C++中的头文件实现一样。但是,有一点需要注意的就是它包含了私有声明 的名称和类型。这让您能在调试器中引用它们,很方便,但也意味着,您不能用私人秘密来命名私有变量。


image.png

对于累加构建, 编译器会生成部分Swift模块文件,然后将它们合并到一个表示整个模块内容的文件中。这种合并过程还可以生成单个Objective-C头文件。

在许多方面,这类似于链接器将目标文件整合成单个可执行文件时所执行的操作。 下文将主要讲述连接器。

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

推荐阅读更多精彩内容