如果你在工程中使用静态库,并且指定了编译选项为-all_load(为了让Objective-C的类别加载正确),静态库中,你的工程包含了一样的class名字,或者跟其他静态库中,有相同的class名字。在链接静态库,肯定遇到过类似于这样的错误“duplicate symbol”错误。
例如,一个三方库(libProprietary.a),库中使用KissXML解析和生成XML,你的工程中内置一个静态库(libBitsAndBobs.a)也使用KissXML。如果你使用两个库,你将会得到KissXML 的duplicate symbol错误。
一个粗暴并且快捷的办法是,将相同的class名字从其中一个库中移除。下面将介绍一下怎么实现:大致步骤:
1.查看是否是fat的静态库
2.拆成armv6 和i386的两个静态库
3. 解出静态库中的目标文件(.o文件)
4. 删除多余的目标文件
5. 合成armv6或者i386的静态库
6.重新合成fat库。
意思是:是否包含了多个架构。你会发现很多iOS静态库是fat files,目的是让它们同时可以在真机和模拟器上运行。
$ lipo -info libProprietary.a
Architectures in the fat file: libProprietary.a are: armv6 i386
正如我们说的,这个库就是一个fat file(armv6 和i386两个架构)。
为了这么做。我们还需要使用lipo命令
$ lipo -thin armv6 libProprietary.a -output libProprietary-armv6.a
$ ar -t libProprietary-armv6.a
__.SYMDEF SORTED
FOOBar.o
DDXMLDocument.o
DDXMLElement.o
DDXMLElementAdditions.o
DDXMLNode.o
首先,解包:
$ mkdir libProprietary-armv6
$ cd libProprietary-armv6
$ ar -x ../libProprietary-armv6.a
现在,我们有一个包含目标文件的文件夹 libProprietary-armv6
$ ls -1
DDXMLDocument.o
DDXMLElement.o
DDXMLElementAdditions.o
DDXMLNode.o
FOOBar.o
__.SYMDEF SORTED
$ rm DDXML*.o
$ libtool -static *.o -output ../libProprietary-armv6.a
为了确认我们移除了目标文件,可以再次list一下;
$ 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
lipo -create libProprietary-armv6.a libProprietary-i386.a -output libProprietary-noKissXML.a
如果,一切正确的话,你可以使用 libProprietary-noKissXML.a代替libProprietary.a了,并且不再有duplicate symbol的错误了。
原文地址http://atnan.com/blog/2012/01/12/avoiding-duplicate-symbol-errors-during-linking-by-removing-classes-from-static-libraries