Thursday, December 10, 2015

Avoiding Duplicate File / Symbol Issues Linking 3rd Party Library on iOS

1. File Name Conflicts or Same Duplicated Symbols

$ lipo -info libTest.a
Architectures in the fat file: libTest.a are: armv7 i386
Then to extract just armv7, for example:
$ lipo -extract_family armv7 -output libTest-armv7.a libTest.a
$ mkdir armv7
$ cd armv7
$ ar -x ../libTest-armv7.a
You can then extract the same architecture from the other library into the same directory, change file names, and then recombine them like so:
$ libtool -static -o ../libTest-armv7.a *.o
And then finally, after you've done this with each architecture, you can combine them again with lipo:
$ cd ..
$ lipo -create -output lib.a libTest-armv7.a libTest-i386.a
This should get rid of any duplicate symbols if we can assume the 3rd party libraries are the same between two libraries, when combining the two libraries into one. If you want to keep them separate, or just delete the duplicate from one library, you can modify the process accordingly.

2. Not Many Symbols Conflicts

Michael Tyson mentioned to use the preprocessor to rename the symbols automatically during the build phase.

This is done by adding a series of -DOldSymbol=NewSymbol flags to the ‘Other C Flags’ build setting – like -DTPCircularBuffer=ABCircularBuffer, for instance in XCode.

3. Many Symbols Conflicts

We may need prefix other static libraries to use a two-pass compilation process:

  • The first pass builds the dependent project and runs nm to dump all symbols into a header file.
  • The second pass builds the dependent project again, but this time with the generated prefix header file imported in the precompiled header. This prefix header must be used anywhere you reference symbols from the dependency in your framework in order to properly refer to the renamed symbols.
 Kamil Burczyk gave a very good tutorial, "Avoiding dependency collisions in iOS static library managed by CocoaPods". For example, to get a TEST symbols in lib.a :

$ nm lib.a | grep TEST
You will get a list of all symbols of TEST. Then use a script to add a prefix to all of the symbols in final .a file so that e.g. TEST becomes NEW_TEST under a #ifdef. Your version of dependency is not connected to version used by developer and no collisions occurs.

No comments:

Followers

About Me

My photo
HD Multimedia Technology player