libssl.a inside Custom iOS SDK Library causing duplicate symbols/definitions - ios

My SDK uses a libssl.a library, but when I give it to a customer to use my SDK, they also uses a version of libssl.a and is causing duplicate symbol. Is there anyway to allow both to coexist?
Thanks

One option would be to rebuild libssl with a custom prefix on each symbol. I wrote a script for this purpose, which you can find here.
A simpler option might be to not link to libssl.a and require the customer to link to it instead. To do this, simply #import libssl's headers as usual, but leave libssl.a out from the link binary with libraries phase. The linker does not attempt to resolve symbols unless the target is an executable, so you will be able to compile a static library on this way without issues.

Related

Duplicate symbol in .framework and .a

I am developing a library .a file in Which i am using AFNetworking classes ... This library does also include one .framework which also using the AFNetworking classes (Adding this framework is optional)
Due to this I am getting following errors
duplicate symbol _OBJC_IVAR_$_AFHTTPRequestOperation._responseSerializer in:
.../KonySDK.framework/KonySDK(AFHTTPRequestOperation.o)
.../Core.a(AFHTTPRequestOperation.o)
Options i have already considered is removing AF***.o from one of the file lipo -thin and ar -d -sv commands
Using this Link
But this library is configurable from server and adding that particular .framework is optional.
My question is ... Is there any otherway by which i can resolve this issue ? ALso i can would rather not prefer to remove .m files of AFNetworking from my library source as the entire process of generating library is fully automatic and configurable in many ways
I have also tried to resolve this by removing -all_load from other linker flags but this resulted in crash as categories of some classes are not loaded due to this.
You will get the duplicate symbol linker error whenever you have included a binary version of a class. The way to get rid of it is to remove the superfluous object.
For building your library you only need the .h files of AFNetworking because those tell the compiler which classes and methods are available. You do not need to compile the AFNetworking source code because a .a file is essentially a collection of .o files which each contain the compiled versions of .m files.
Libraries are not linked
Only apps get linked and therefore need to have the symbols/objects present. i.e. if you provide your library without AFNetworking compiled in, then the developer using it needs to add AFNetworking via library, framework or cocoapod.

Export an `OBJC_CLASS` from one static lib as part of another

I want to create a static library (actually, a framework, but I know how to do that part) that bundles up code from, among other things, another static library. However, the OBJC_CLASS exports from the original library end up as undefined symbols.
For example, in Xcode 5.1.1 (using default settings/choices at every step, unless otherwise specified):
Create a new "iOS Framework & Library Cocoa Touch Static Library" project named LibA.
Build (for either simulator or a real device, doesn't matter).
Create another new "iOS Framework & Library Cocoa Touch Static Library" project named LibB.
Drag libLibA.a from the LibA products to the Frameworks folder in the LibB project tree.
Drag LibA from the include directory next to the static lib to the top level of the LibB project tree.
Edit LibB.h as shown below.
Build (same target as before).
Create a new "iOS Application" (any type) project named AppC.
Drag libLibB.a from the LibB products to the Frameworks folder in the AppC project tree.
Drag LibB from the include directory to the top level.
Drag LibA from the first project's include directory to the top level.
Verify that LibA appears in the Link Binary With Libraries phase.
In any method of any class the wizard generated (e.g., -[MasterViewController awakeFromNib]), add (void)[[LibB alloc] init].
At the top of the .m file you just edited, add #import "LibB.h".
Build.
Here's the LibB.h promised above:
#import <Foundation/Foundation.h>
#import "LibA.h"
#interface LibB: LibA
#end
I get the following error:
Undefined symbols for architecture i386:
"_OBJC_CLASS_$_LibA", referenced from:
_OBJC_CLASS_$_LibB in libLibB.a(LibB.o)
"_OBJC_METACLASS_$_LibA", referenced from:
_OBJC_METACLASS_$_LibB in libLibB.a(LibB.o)
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Looking at the files, the problem is obvious:
$ nm -g libLibB.a
U _OBJC_CLASS_$_LibA
0000031c S _OBJC_CLASS_$_LibB
U _OBJC_METACLASS_$_LibA
00000308 S _OBJC_METACLASS_$_LibB
U _OBJC_METACLASS_$_NSObject
U __objc_empty_cache
The symbols for _OBJC_CLASS_$_LibA and _OBJC_METACLASS_$_LibA are exported as undefined.
I can reference methods, C functions and structs, globals, etc. from LibA. Even categories on Foundation objects (as long as I do the category-dummy trick). It's only the class and metaclass objects that I can't figure out how to export.
Here's what I've tried to fix it:
Turn off Dead Code Stripping (in all three projects).
Add -ObjC as an extra linker flag (in all projects). (This makes no sense for static libs, and all it does is give you a warning error telling you exactly that, but everyone suggests it to me.)
Create an "Exported Symbols File" (for LibB). (This also only makes sense for dynamic libs.)
Pass ${PROJECT_DIR}/libLibA.a as an "Other Linker Flags" (for LibB) instead of adding libLibA as a framework (in case -lLibA is processed differently from libLibA.a).
What I've tried that I still think may be on the right path, but I'm not sure:
Try to figure out appropriate libtool options that have no corresponding settings in Xcode. (I can wrap it in a Makefile, or and Xcode custom build step, if necessary.)
Enable "Perform Single-Object Prelink", then add ${PROJECT_DIR}/libLibA.a to "Prelink libraries". I get warnings about duplicate symbols and then success but with an empty libLibB.a, so obviously there's something else I need to do. I've done this with .dylibs and dynamic Frameworks on OS X, and there wasn't anything else I needed to do there… but never with static libs.
Workarounds that I know about (and I'll use one of these if there's no real solution):
Require that anyone who wants to use LibB also has to add LibA to their project. And, in particular, the pre-built copy of LibA that we provide.
Distribute LibB as source to be included in your project, instead of a static lib and headers.
Manually ar libLibA.a and LibB.o, then ranlib like it's 1999 (although the docs say this doesn't work, it seems to).
(None of these are too terrible for my simple test project, but in real life, this is not an open source project, that LibA is actually 80 different libs from 3 different projects, and some of the LibA code builds fat armv7/armv7s (which means ar doesn't work on it…), and we're planning to do the usual hack of lipo'ing together the simulator and native builds and making a framework out of them, all of which makes things more of a problem.
I think I may have solved it with single-object prelink (basically this means it does an ld -r to build a giant object file, then passes that to libtool), although I'm still not sure, and I don't love the solution. So, I will post what I've got as an answer, but hope someone else comes along with a better answer.
To get single-object prelink to work, you need to (in LibB):
Add libLibA.a as a Framework.
Make sure it does not appear in the Link Binary With Libraries build phase.
Set "Dead Code Stripping" to No.
Set "Don't Dead-Strip Inits and Terms" to Yes.
Set `Perform Single-Object Prelink" to Yes.
Set "Prelink libraries" to ${PROJECT_DIR}/libLibA.a
Set "Preserve Private External Symbols" to Yes.
(The second step is what I was doing wrong earlier…)
Unfortunately, this seems to break the dependency rules completely, so that every build recompiles every .m (and .pch) that's part of the target, even if nothing has changed.
Other than that annoyance, this seems to work for both AppC and my real project just fine.
AppC does not need "Preserve Private External Symbols"; my real project does. I believe this is because one of the third-party libraries does an ld -r with an empty -exported_symbols_list explicitly to "transform all symbols to private_extern. Otherwise, class objects don't end up that way. However, I'm not 100% sure I understand this one.
Adding this to Other Linker Flags appears to work
-force_load $(CONFIGURATION_BUILD_DIR)/libLibA.a

Duplicate symbols in monotouch library and some 3rd party library I use

I'm working on an iPhone app with Monotouch. In my app, I have to use a static library provided by 3rd party. This library is for Xcode and written in Objective-C. I bound it with Monotouch using Binding Project Template. When I add the resulting dll to my project it compiles fine, but when I use a class from the library it fails to compile with the following error:
Duplicate symbol _DeleteCriticalSection
So what can I do? Is there any way to remove the conflict?
Thank you in advance.
I've seen similar things inside FAT libraries where some files were duplicated, leading to duplicate objects. You can try to see if this is the same issue, e.g. if your library is named mystaticlibrary.a
$ nm mystaticlibrary.a | grep DeleteCriticalSection
Now it can be normal to have the symbol multiple times if you have a FAT library (more than one architecture). To see if that's the case do:
$ file mystaticlibrary.a
You should have the symbol for each architecture. If you see more symbols (e.g. 3x DeleteCriticalSection but only 2 arch) then you have a similar issue.
The fix (if it's the same issue) was to split the FAT library (lipo tool), then each architecture specific library, then re-merge everything (arch then FAT).
Your best bet might be to contact your library vendor and ask him for a fixed library (something was likely wrong in the build process). Give them the above command output and they'll likely find out what went wrong.

Ho can I use adMob library for iOS without using -all_load linker flag

I'm adding adMob provide by google to my iOS app and I'm stuck on this part of the installation:
Add -all_load under Other Linker Flags in the project build info
If I add that flag, then another third party library breaks giving me the error message:
ld: duplicate symbol _vw_chartype_table_p in /Users/josh/ Projects/app/libs/libvt_universal.a(vw_ctype-3279EF26D0C25F3A.o) and / Users/josh/Projects/app/libs/ libvt_universal.a(vw_ctype-34AB9EC0B46D954C.o) for architecture i386
Is there any way to use the adMob library without using -all_load? For example, I've tried -force_load $(SOURCE_ROOT)/adMob/libGoogleAdMobAds.a
but
ld: file not found: /Users/USERNAME/Desktop/latest/bbbb/APPNAME/adMob/libGoogleAdMobAds.a
The reason Google suggests using -all_load is that they are using categories in their code, and Objective-C libraries with categories are not properly loaded by the llvm linker (well that was the case in 4.3 xcode, not sure about 4.4 with the newer clang).
So, I guess if you are brave you can try to just remove the all_load flag. It should build fine. If the bug is NOT fixed, what will happen is when you run your code, it will crash, since none of the categories the library uses will have been loaded. This might be a good thing to do in any case, as your project should build, and if it does not you can fix those problems first.
What I do suggest you do is use -force_load, which has llvm load the categories in the adMob library (among other things). To use it you MUST have a fully qualified path (ie starts at '/') to the library. Obviously if you use Terminal and run:
ls -l /Users/USERNAME/Desktop/latest/bbbb/APPNAME/adMob/libGoogleAdMobAds.a
its going to fail. So enter the proper path - hard coded - for now to just see if you can get the project to first build, then run. If it does you can later figure out what is the appropriate $(VAR) to use to find it inside your project.

Conflict between static libraries used in Xcode project

I am using RestKit, GData and Facebook API.
All of them has a JSON files, many of them share the same name, enums etc.
When i compile I get an error on duplicates.
How can i prevent the conflicts?
Thanks
Shani
This is my best guess. It would be helpful to post the errors you get on compile.
If you are using the -all_load linker flag, turn it off. If your libraries require that you use this option, try using -force_load option on the specific libraries that require it. As an absolute last resort, build the libraries that you can from source, renaming colliding symbols.
The question below might provide some more insight on the all_load issues:
Objective-C categories in static library
I ran into this issue because the new Facebook SDK 3.0 is now a static framework which also includes SBJSON, I also have another static framework which also includes the same class. Originally I would just go in and edit the source files of the Facebook SDK and apply a custom prefix to the SBJSON classes. This no longer works.
Here is an outside the box solution.
Navigate to FacebookSDK.framework->Versions->Current
Open the compiled FacebookSDK library file with the best IDE, textedit will do!
Search case sensitive and replace all occurrences of "SBJson" with "FBJson"
Search case sensitive and replace all occurrences of "SBJSON" with "FBJSON"
Save, clean, compile.
Note: Some would say, why replace with FBJson and not FBSBJson? I determined it would be best to keep it the same character length to be safe.
Note: If you are attempting this with other frameworks, be sure to search the header files for any references to the conflicting class that you are renaming. In this case the class being renamed was not referenced in any of the header files. If it had been, I would have made sure to rename it in the header files.

Resources