在打包静态库给第三方使用时,使用者提出编译报错,原因是在静态库中和项目中同时使用了rsa签名的文件,存在了冲突duplicate symbol,通过几种方法尝试解决了这个错误。
错误信息如下:
这种情况一般都是文件里面使用C语言定义的全局变量名或是函数名,在导入的时候因为重复产生了冲突。
解决的方法:
1.修改静态库中冲突的函数名或全局变量名(第三方静态库提供者修改)
2.对项目buildsetting里的other linker flags进行修改(第三方静态库引用者修改)
详见下面博客内容
3.重新打包三方库
other linker flags:
它的设置关乎到项目编译时的链接方式。
根据一篇博客内容顺便补脑下编译过程:
“
从C代码到可执行文件经历的步骤是:源代码 > 预处理器 > 编译器 > 汇编器 > 机器码 > 链接器 > 可执行文件
在最后一步需要把.o文件和C语言运行库链接起来,这时候需要用到ld命令。源文件经过一系列处理以后,会生成对应的.obj文件,然后一个项目必然会有许多.obj文件,并且这些文件之间会有各种各样的联系,例如函数调用。链接器做的事就是把这些目标文件和所用的一些库链接在一起形成一个完整的可执行文件。Other linker flags设置的值实际上就是ld命令执行时后面所加的参数
下面逐个介绍3个常用参数:
-ObjC:加了这个参数后,链接器就会把静态库中所有的Objective-C类和分类都加载到最后的可执行文件中
-all_load:会让链接器把所有找到的目标文件都加载到可执行文件中,但是千万不要随便使用这个参数!假如你使用了不止一个静态库文件,然后又使用了这个参数,那么你很有可能会遇到ld: duplicate symbol错误,因为不同的库文件里面可能会有相同的目标文件,所以建议在遇到-ObjC失效的情况下使用-force_load参数。
-force_load:所做的事情跟-all_load其实是一样的,但是-force_load需要指定要进行全部加载的库文件的路径,这样的话,你就只是完全加载了一个库文件,不影响其余库文件的按需加载
”
对于出现的问题我们一个个分析。
Q1:为什么不加-ObjC时,CorePlot会崩,出现“selector not recognized”情况?
“-Objc这个标志,和Objective-C的一个重要特性:类别(category)有关。根据这里的解释,Unix的标准静态库实现和Objective-C的动态特性之间有一些冲突:Objective-C没有为每个函数(或者方法)定义链接符号,它只为每个类创建链接符号。这样当在一个静态库中使用类别来扩展已有类的时候,链接器不知道如何把类原有的方法和类别中的方法整合起来,就会导致你调用类别中的方法时,出现”selector not recognized”,也就是找不到方法定义的错误。为了解决这个问题,引入了-ObjC标志,它的作用就是将静态库中所有的和对象相关的文件都加载进来。”
简单的说就是,在没有添加-ObjC的情况下,某些静态库中的Category函数是没有被识别的,调用该函数时没找到这个函数的指针,就报错了。
Q2:真机编译,为什么加-ObjC时,自身的SDK会出现duplicate symbol冲突?
在加入-ObjC标志后,编译时会把所有OC文件都加载到可执行文件中,这样的情况下,假如有2个OC文件中都用到同一个名字命名的变量或函数,就会出现重复定义的编译错误。
Q3:如何解决有无-ObjC的矛盾?
使用-force_load加载特定的库。
所以,目前对于真机的编译问题我已经解决了,使用-force_load 路径+.a文件两条规则来加载特定的.a文件,防止他们的部分函数符号没建立的情况。
Q4:对于模拟器情况下两个库之间的.a文件冲突,有无解决办法?
假如对other linker flag都未设置,却出现了duplicate symbol的情况,那通过设置该标志只会让情况更糟糕。
建议对.a库重新打包,删除部分重复的symbol。