(WWDC) Xcode 构建过程的幕后 —— Swift

现在,让我们深入到 Swift 如何与构建系统协作查找声明代码的细节中。

首先,我们需要回顾一个要点:Clang 会分开编译每一个 Objective-C 文件。
如果你需要引用一个文件中的某个类,你必须导入声明了这个类的头文件。

然而,Swift 不需要你导入头文件。这明显减轻了初学者的负担,也避免让你重复导入声明。
不过,这就意味着编译器需要做更多的工作。

让我们回到之前的例子, PetWall App。

这个应用有一个用 Swift 编写的 ViewController,
还有一个用 Objective-C 编写的 AppDelegate,
还有用 Swift 编写的单元测试。

 

为了编译 PetViewController 这个文件,编译器需要做四种不同的操作。

  • 查找声明
    • 来自 Swift Target
    • 采用 Objective-C 编写
  • 生成接口
    • 用于 Objective-C
    • 用于其他 Swift Target

 
 

首先,在 Swift Target 中寻找声明:

在编译 PetViewController.swift 时,编译器需要找到 PetView 的初始化方法,然后才能检查这个调用。
但是在此之前,编译器需要先解析并且验证 PetView.swift 来确保 PetView 的初始化方法调用正确。

编译器不需要解析 PetView 初始化方法的函数体部分,不过也要处理 PetView.swift 的接口部分。

Clang 会解析 Target 中的所有源文件

这与 Clang 的解析过程不同,Clang 会解析这个 Target 中其他的 Swift 文件来验证这些部分和接口相关联。

在 Xcode 9 中,这会导致重复的工作,因为编译器单独编译每个文件。
这样可以使文件被并行编译,不过这也致使编译器重复解析文件。

Xcode 10 通过将文件进行分组解析来共享工作成果,这样就可以有效地减少重复解析的开销,同时尽可能最大化地允许并行化。

这些解析在分组内重用,在跨分组时才需要重复解析。
相对来说,分组的数量比较少。所以这可以显著提升增量构建(Incremental Build) 的速度。

  

然而,现在的 Swift 代码还会调用 Objective-C 代码。

让我们回到 PetWall App,我们知道 UIKit 系统库是采用 Objective-C 编写的。
Swift 采用了与其他语言不同的方式,它不需要你提供一个外部函数接口。

Swift 将大部分的 Clang 作为自己的内部库,这样就可以直接导入 Objective-C 框架。

  

那么,Objective-C 声明来自何处?

  

当你在任意的 Target 中导入一个 Objective-C 框架时,头文件中的声明会暴露 Clang 模块映射,导入器会查找这些声明。
在 Swift 和 Objective-C 混编的框架中,导入器会在伞头(umbrella header)中查找声明,伞头中定义了公开接口。
通过这种方式,同一个框架中的 Swift 代码可以调用同一个框架中的公开的 Objective-C 代码。
最后,在你的应用或者单元测试中,你可以在桥接头文件里添加导入指令(import)。

导入器会做适当的调整,比如:将使用 NSError 的 Objective-C 方法转换为抛出错误的 Swift 方法并去掉一些参数、参数名。

比如,drawPet: atPoint 方法 中的 Pet, Point 都会被移除。

你可能会猜想,编译器内部是不是有一个常用英语动词、介词表。

没错,的确有这样一个表!但是,也会有一些词没有被收录进来。

比如,feed 就没有被收录。

不过,你可以使用 NS_SWIFT_NAME 自定义转换后的方法名。

如何确认转换后的方法名符合预期呢?

 
 

现在来思考另一个问题,Objective-C 如何导入 Swift 代码呢?

 
 

实际上,编译器会为 Swift 生成一个头文件。这个头文件中会包含继承自 NSObject 的类和被 @objc 标记的方法的声明。

对于单元测试中的应用,头文件会包含公开(public)和内部(internal)的声明,这可以允许你在 Objective-C 中 使用 Swift 内部的方法和属性。
对于框架,生成的头文件中只会包含公开的声明。

你会发现,生成的 Objective-C 头文件中的 Swift 类名是乱码,其中包含了类名和模块名。
这样可以有效地避免由于不同模块定义了相同类名导致的运行时错误。

当然,你也可以显式地指定一个名称。但是,如果这样的话,你需要自己为命名冲突问题负责。

在 Swift 中,一个模块是一个可分配声明单元。

为了使用这些声明,你需要导入模块。
每个 Swift Target 产生单独的一个模块。当然,你的 App target 也是如此。
这就是为什么上面的示例代码需要在单元测试中导入 PetWall。

当导入一个模块时,编译器会反序列化一个特殊的 Swift 模块文件来检查你用到的类型。
比如在上面的单元测试代码中,编译器会加载 PetWall.swiftmodule 中 PetViewController 的部分来确保你创建 PetViewController 的代码是正确的。

这和上文中讲述的编译器如何在 Target 中查找声明的方式类似。除此之外,编译器会加载一个概述这个模块的文件,而不是单独解析每个文件。这类似于生成 Objective-C 头文件,不过这个文件的内容不是文本格式而是二进制格式。其中包含内联函数的函数体(类似于 Objective-C 中的静态内联函数或者 C++ 中的头文件实现)。

值得注意的是,这其中也包含了私有声明的名称和类型。这可以允许你在调试器中引用,确实相当方便!

对于增量构建,编译器会产生部分的 Swift 模块文件,然后合并到代表整个模块的内容的那个文件中。
这个过程使生成单个 Objective-C 头文件变成了可能。

这在很多方面类似于链接器如何将多个文件链接生成单个可执行文件的过程。

  
继续阅读 (WWDC) Xcode 构建过程的幕后 —— Linker





参考内容:
Behind the Scenes of the Xcode Build Process




转载请注明出处,谢谢~

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

推荐阅读更多精彩内容