原文链接:http://atnan.com/blog/2012/01/12/avoiding-duplicate-symbol-errors-during-linking-by-removing-classes-from-static-libraries/
假如你得xcode项目工程在编译静态库的使用使用了-all_load标志来保证objc的category加载正确,你可能会在链接的时候得到“duplicate symbol”的错误信息,这是因为静态库内包含了相同的.o文件。
假如一个第三方的静态库叫(libProprietary.a
)已经使用了KissXML,而项目中的另一个库(libBitsAndBobs.a
) 也使用了KissXML,如果你同时使用了这两个库,你就会得到 duplicate symbol的错误信息(DDXMLDocument,DDXMLElemet&DDXMLNode).
所以我们可以从静态库中移除一部分编译的类,下面就是方法。
$ lipo -thin armv6 libProprietary.a -output libProprietary-armv6.a
首先,我们得查看下这个静态库是否是一个包含多个架构的静态库(fat file),因为一个静态库可能需要在不同的cpu架构上运行,如armv6/armv7,模拟器i386等。
在终端下输入
$ lipo -info libProprietary.a
Architectures in the fat file: libProprietary.a are: armv6 i386
可以看到这个静态库是个包含多个cpu架构的静态库,我们需要分离出单个架构的.a文件
下面我们使用命令来查看下这个.a文件包含了多少个类
$ ar -t libProprietary-armv6.a
__.SYMDEF SORTED
FOOBar.o
DDXMLDocument.o
DDXMLElement.o
DDXMLElementAdditions.o
DDXMLNode.o
和我们期望的一样这个文件里面除了FOOBar.o文件,也包含了DDXML相关的.o文件,我们现在需要做的是解开这个.a文件,把里面的DDXML*.o相关文件移除,然后重新打包这个.a文件。在终端下面:
$ mkdir libProprietary-armv6
$ cd libProprietary-armv6
$ ar -x ../libProprietary-armv6.a
我们创建了一个文件夹,然后解压了.a文件,接下来:
$ ls -1
DDXMLDocument.o
DDXMLElement.o
DDXMLElementAdditions.o
DDXMLNode.o
FOOBar.o
__.SYMDEF SORTED
可以看到有不同的.o文件,然后我们删除DDXML相关的.o文件,然后重新组装.a文件:
$ rm DDXML*.o
$ libtool -static *.o -output ../libProprietary-armv6.a
最后我们确认下我们组装的.a文件包含的.o文件是否正确:
$ ar -t ../libProprietary-armv6.a
__.SYMDEF SORTED
FOOBar.o
到目前为止我们只是修改了armv6的架构,i386的我们在用这个命令操作一遍:
$ lipo -thin i386 libProprietary.a -output libProprietary-i386.a
$ mkdir libProprietary-i386 && cd libProprietary-i386
$ ar -x ../libProprietary-i386.a
$ rm DDXML*.o
$ libtool -static *.o -output ../libProprietary-i386.a
最后我们把两个架构的.a文件合并成一个.a文件:
lipo -create libProprietary-armv6.a libProprietary-i386.a -output libProprietary-noKissXML.a
假如一切正确,你可以用这个.a文件替换原来的.a 文件,这些错误信息也会消失。