StaticLib的编译命令
在上文Target和Link的关系中我们可以得知,Static Lib在编译后使用的是 Create Static 而不是真正的Link
1 | XcodeDefault.xctoolchain/usr/bin/libtool -static ..... |
得到的符号表,可以通过符号表文章的对比得知,是一堆.o文件的压缩包
1 | ...../Library/Developer/Xcode/DerivedData/...../libStaticLib.a(StaticLib.o): <====看这里 |
不会Duplicated的原因
仔细观察符号表,我们可以发现一些规律
- StaticLib内部的 .o 文件是互相独立的
- 每一个 .o 文件都是从 0000000000000000 地址开始计数
当StaticLib真正执行Link命令成为 Target.app 或者 Dynamic.framework 时,符号表则变成了一个连续地址的Mach-O文件
也就是说 两个 StaticLib.a 中存在相同的 .o 文件,他们两个也是完全一样的,会在Link时的只有一个被Link
就像拷贝文件一样,如果存在一个同名的 .o 文件,后一个相同的 .o 文件就会拷贝失败,只使用了第一个
验证
如果存在以下Link模型,按照上述理论,StaticLib.a 的 .o 会在 A 和 B 中共同存在,在最终进入App时,因为互相覆盖不报错
为了验证,我们
- 将StaticLib.a的类 Object 文件拷贝进入 Duplicate-A
- 取消掉StaticLib.a 对 A 的Link
- 更改Duplicated-A内 Object.m 内方法的NSLog日志
再次Build,发现执行的是 StaticLib.a 中的方法日志
1 | 2017-11-12 20:57:05.908741+0800 Static Lib Obj 0x60c000000fe0 init.... |
然后我们更改App中 Link 顺序,再次Build运行,发现执行了 Duplicated-A中 Object.m的方法
1 | 2017-11-12 20:30:29.373910+0800 Duplicated Static Lib Obj 0x608000018390 init.... |
结论
根据日志分析,App会使用第一次Object.o文件,而不是后一个
- 当使用了 StaticLib.a 中的NSLog时,Link顺序为
1 | ....../usr/bin/clang -arch x86_64 -lDuplicateB -lDuplicateA ....... |
- 当使用了 Duplicate-A 中的NSLog时,Link顺序为
1 | ....../usr/bin/clang -arch x86_64 -lDuplicateA -lDuplicateB ....... |