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

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

构建过程:链接

这是 Xcode构建过程的最后一步。

首先浏览一下我们要讨论的内容。我们将讨论链接器是 什么,它所采用的输入,即dylib和目标文件及其定义。还会讲到符号及其内容。最后会举例总结,因为内容比较难懂。

链接器是什么

链接器是构建中的最后一个过程。我们所做的是将两个编译器构建的所有.o文件 组合成一个可执行文件。它所做的就是移动和修补代码。 它无法创建代码,这 很重要,我将在示例中显示。我们有两种输入文件。第一个是目标文件(.o),在构建过程中产生。第二个是库,包括dylib,tbd和.a文件或静态文档。

符号(symbols)

符号是一个代表代码或数据片段的名称。当一个函数调用另一个函数,这些片段可能会指向其他符号。符号可以有很多影响链接器行为方式的属性。我只举一个 弱符号的例子。弱符号的注释表示当我们在系统上运行或者执行文件时它可能不存在。还有可用性标记,标记这个API用于iOS12,那个API用于iOS11.这就引出了现在的主题链接器。链接器可以确定哪些符号肯定会出现和哪些符号可以在运行时处理。如前所述,语言可以通过命名修饰将数据编码为符号。在C++和Swift中都能看到。所以符号就是指代码和数据的名称。

目标文件

目标文件就是代码和数据的集合。它们不可执行。因为是编译代码,所以还没有完成。还有缺失就需要链接器整合和修复。每个文件的片段都用符号表示。例如对于printf函数,就以符号代替代码。对于PetKit的代码后文会展示。

片段可能引用未定义的符号。 因此,如果您的.o文件引用另一个.o文件中的函数,那么.o文件是未定义的。链接器将找到那些未定义的符号并进行匹配。所以目标文件是编译器操作的输出。那么什么是库?库是定义符号的文件,但不属于构建的目标。我们有动态库,那些Mach-O文件,显示了可执行文件的代码和数据片段。这些是系统的一部分。这就是我们的框架。你也可能会用自己的框架。

还有TBD文件,基于文本的dylib文件。在为iOS和macOS制作SDK时,会有所有这些dylibs和以及您可能想要使用的功能,如MapKit和WebKit。但是我们不想把所有这些跟SDK一起加载,因为它会很大而且编译器和链接器不需要它,它只在运行程序时有用。因此,我们创建了stub dylib,删除所有符号的主体,只留下名称。完成之后,转用文本表示,这对我们来说更容易使用。目前,它们仅用于分发SDK以减小大小。所以你在项目中看到它们时不必担心,它们只是符号。

最后是静态库(static archives)。静态库是使用AR工具构建的.o文件的集合,也可能是lib,它是lib工具的包装器。根据AR操作文档,AR创建并维护的文件组,将它们合并为一个库。听起来很像TAR文件或ZIP文件,这正是它的本质。实际上,.a格式是UNIX在使用更强大的工具之前使用的原始库格式。但是现在的编译器和连接器可以完全理解它们,所以继续使用它们。它就只是个档案 文件。值得注意的是,它们孕育了动态链接,在过去所有代码都会被存档。因此, 不能使用的是一个函数涵盖所有C库 。所以行为是,如果.o文件中有符号,我们会将整个.o文件从库中拉出来。但是不会引入其他.o文件。如果你在它们之间引用符号,只要带入即可。如果你是非符号行为,比如静态初始化程序,或者将它们重新导出为您自己的dylib的一部分,您要明确地用到强制加载,或定制加载让链接器提取所有或者这些文件,即便之间没有关联。我们通过一个例子串联起这些内容。

image.png

上面是playSound函数的例子,只看宠物不听声音有什么乐趣?cat上有一个调用playSound的函数。上图右边是生成的程序集。输出文件是cat.o。字符串purr.aac,是AAC声音文件。这会被复制到cat.o. 您会注意到名称purr文件不见了。因为它是静态的。如果你熟悉C语言,这是非导出命名。没有其他人可以引用它。既然如此,我们不需要它,排除掉。


image.png

然后我们看到Cat purr变成了符号:-[Cat purr]。跟预想的差不多。


image.png

然后我们要把这个变量传递给playSound。这里出现了两个指令,这是因为我们不知道这个字符串最后在可执行文件中的位置,我们没有具体的地址 。 但是我们知道RM64就是这个程序集,它最多可能需要两条指令。所以编译器给我们留下了两条指令。它留下符号偏移量,值为PAGE和PAGEOFF,链接器之后回来修复。 最后,既然已经将字符串加载到x0中,我们可以调用playSound,我们写入__z9playSoundPKc。这是一个变形的符号,如果仔细看会看到cat.mm,这是Objective-C++。playSound实际上是一个C++函数。所以如果你不熟悉,你可以在终端输入命令。
image.png

如果运行Swift-demangle并传入符号,然后反修饰。没有用,它不是swift的符号。但是C++ 反修饰器C++ filts告诉我们这实际上是playSound的符号。 除了playSound,它还有一个实参。这个参数是一个const char* 因为C++会将更多信息编入修饰符号中。现在有了.o文件,实际构建中会有更多。那我们该怎么做呢?
image.png

首先,构建系统将把所有.o作为输入传递给链接器。链接器会创建一个文件来放入它们 。这里构建的PetKit,是PetWall的内嵌框架。 因此,我们只要复制,创建一个文本片段用来保存app的所有代码的。然后复制cat.o到这里。但是要分成两部分,一个用于字符串,一个用于可执行代码。现在已知这些东西的绝对地址,因此 链接器可以重写cat.o,以从特定偏移量加载。 你会注意到第二条指令就消失了。它被一个null指令代替,没有任何行动。但我们无法删除 指令,因为我们无法创建或删除代码,这会打乱所有已完成的工作。所以与其删除,不如替换为无行动。

最后是分支。我们有一个未定义的符号,我们将继续浏览所有已经导入的.o文件。


image.png

所以我们将开始查看静态库,上图是PetSupport.a。在PetSupport.a中有几个文件,包括PetSounds.o。大家能看到匹配playSound的符号。 所以我们把它拉进来。PetCare.o不能被引入,因为.o文件没有任何符号能被app的其他部分引用。我们把它拉进来,但现在需要_open,但是我们没有定义。拉入的对话已经变成_open $stub。为什么呢?因为我们发现open的副本在lib系统的TBD文件中。


image.png

我们知道这不是系统库的一部分,我不会其复制到我的app中。但是我需要在app中加入足够的信息 以便调用它。

image.png

因此,我们创建了一个假函数 ,它只是一个模板,用来代替从lib系统拿走的函数,这里就是open。观察该函数,它实际上是来自指针open$pointer,然后跳到它。这需要一个函数指针,就像任何普通的C函数指针一样。然后在数据段中 创建它,如果有全局变量,那么就会出现在这里。但它只是设置为零,如果如果空引用会导致崩溃。然后我们添加一个LINKEDIT部分。
image.png

LINKEDIT是链接器工具用于为操作系统保留信息的元数据,这就是在运行时解决问题的动态链接器。有关这方面的更多信息,请查看2016年的 Optimizing App Startup Time 演讲。

相关信息:
Swift
Clang
llbuild

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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

推荐阅读更多精彩内容