If you’re using a static library in your project and specifying the
-all_load flag to ensure files containing Objective-C categories are loaded correctly, you’ll likely experience “duplicate symbol” errors at link time if the static library includes the same classes used in your project or another library.
e.g. A third party has provided you with a static library (
libProprietary.a) which uses KissXML internally for parsing & generating XML. You also have an internal static library (
libBitsAndBobs.a) which also uses
KissXML. If you use both libraries, you’ll get duplicate symbol errors for all the
KissXML classes (
A brutish yet simple workaround is to remove the offending classes from one of the libraries, so I’ll show you how it’s done.
Firstly, we need to see if the static library is a “fat file”, which means it contains code for multiple architectures. You’ll find most iOS static libraries are fat files, since they need to work both on the device (
armv7) and in the Simulator (
$ lipo -info libProprietary.a Architectures in the fat file: libProprietary.a are: armv6 i386
As you can see, we have a fat file on our hands.
The tools we’ll be using require us to split the static library into seperate files for each architecture if it’s a fat file. To do that, we’ll use
$ lipo -thin armv6 libProprietary.a -output libProprietary-armv6.a
We can now use
ar to peek inside one of these thin archive files, listing the included object files.
$ ar -t libProprietary-armv6.a __.SYMDEF SORTED FOOBar.o DDXMLDocument.o DDXMLElement.o DDXMLElementAdditions.o DDXMLNode.o
As expected, in addition to the
FOOBar.o file containing code specific to
libProprietary.a, we also have object files for each of the classes defined in the
KissXML project. To delete those, we’ll need to unpack the object files from the archive, delete the object files we don’t want, and repack the archive.
First, the extraction:
$ mkdir libProprietary-armv6 $ cd libProprietary-armv6 $ ar -x ../libProprietary-armv6.a
We now have a directory containing the contents of the archive:
$ ls -1 DDXMLDocument.o DDXMLElement.o DDXMLElementAdditions.o DDXMLNode.o FOOBar.o __.SYMDEF SORTED
Simply remove the
KissXML related object files and repack the archive like so:
$ rm DDXML*.o $ libtool -static *.o -output ../libProprietary-armv6.a
And to confirm we’ve successfully removed the correct object files from our archive, we can list the contents again:
$ ar -t ../libProprietary-armv6.a __.SYMDEF SORTED FOOBar.o
So far we’ve only stripped the
armv6 archive, so we need to repeat the process for the
$ 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
Now for the final step, we recombine the thin files into a fat file again:
lipo -create libProprietary-armv6.a libProprietary-i386.a -output libProprietary-noKissXML.a
If you’ve done everything correctly you can now replace
libProprietary-noKissXML.a and you won’t have any more duplicate symbol errors.