iOS静态库的链接与加载
引言:研究iOS静态库的链接与加载是源自这个问题:为何引用同一个SDK,在真机可以编译成功,而在模拟器在出现duplicate symbol?
,一时间无法理解,按道理说如果出现duplicate symbol,说明代码中应该有重复定义的部分,而为何真机又ok,难道真机屏蔽了部分代码?带着这些疑问和猜想,进行如下实验
实验
实践才是检验真理的唯一标准
- Demo
- Testlib1
void hello() { printf("Testlib1: hello\n"); } void hello2() { printf("Testlib1: hello1\n"); }
- Testlib2
void hello() { printf("Testlib2: hello\n"); } void hello2() { printf("Testlib2: hello2\n"); }
- Testlib1
PS: 以上是测试DEMO工程框架, Demo为主工程,包含2个静态库工程:Testlib1, Testlib2
编号 | CPU架构 | 链接标识 | 库链接顺序 | 测试代码 | Symbol | 输出 | 备注 |
---|---|---|---|---|---|---|---|
1 | arm64 | 空 | Testlib1.framework Testlib2.framework |
hello() | T _hello T _hello1 |
Testlib1: hello | 原始 |
2 | arm64 | 空 | Testlib2.framework Testlib1.framework |
hello() | T _hello T _hello2 |
Testlib2: hello | 调整库链接顺序 |
3 | arm64 | 空 | Testlib1.framework Testlib2.framework |
hello();hello1() | T _hello T _hello1 |
Testlib1: hello;Testlib1: hello1 | 打印hello1 |
4 | arm64 | 空 | Testlib1.framework Testlib2.framework |
hello();hello2() | T _hello T _hello1 T _hello2 |
Testlib2: hello;Testlib2: hello2 | 打印hello2 |
5 | arm64 | -all_load | Testlib1.framework Testlib2.framework |
hello();hello2() | 报错:duplicate symbol _hello | 链接标识+打印hello2 | |
11 | x86_64 | 空 | Testlib1.framework Testlib2.framework |
hello() | T _hello T _hello1 |
Testlib1: hello | 模拟器 |
12 | x86_64 | 空 | Testlib2.framework Testlib1.framework |
hello() | T _hello T _hello2 |
Testlib2: hello | 模拟器+调整库链接顺序 |
13 | x86_64 | 空 | Testlib1.framework Testlib2.framework |
hello();hello1() | T _hello T _hello1 |
Testlib1: hello;Testlib1: hello1 | 模拟器+打印hello1 |
14 | x86_64 | 空 | Testlib1.framework Testlib2.framework |
hello();hello2() | 报错:duplicate symbol _hello | 模拟器+打印hello2 |
结论
- 库加载是通过配置的顺序进行加载,当发现需要调用的接口都已经定义,则不在继续加载,否则继续加载(根据1、2、3得出)
- 后者加载的接口会覆盖前面库的接口(根据4得出)
- 模拟器下不允许重复定义(根据14得出)
- -all_load下不允许接口重定义(根据5得出)
总结
通过上述结论,可以更好的解释:为何引用同一个SDK,在真机可以编译成功,而在模拟器在出现duplicate symbol?
,当然以上测试是在XCode 8.0及iPhone 5s 10.0.1上进行的.我并未找到官方说明,若哪位童鞋有找到apple文档,可以告知我.