Preventing "duplicate symbol" errors with iOS frameworks - ios

Apple uses the following code in the header of all its framework classes.
#if !defined(__COREFOUNDATION_CFARRAY__)
#define __COREFOUNDATION_CFARRAY__ 1
...
#endif
Is this a recommended approach for eliminating "duplicate symbol" linker errors, when designing classes or categories for framework use, or are these left over protection from the use of #include instead of #import in c?
Research into this has lead me to this article on include guard
NOTE: this question is not asking how to fix a duplicate symbol error, but instead asking if there is any way of preventing your own code from causing the problem if its included more than once in a project.

You're right about the include guard - there's probably some compatibility reason it's not been removed from the source.
However, this won't really protect you against duplicate symbols much.
For example,
What if you have two third party library, each of which uses the SBJSON library (I had this happen to a colleague a few weeks ago).
Each of the libraries was compiled seperately so, from their point of view, SBJSON was only included once. However, when I came to link my app I couldn't because I had duplicate symbols.
I had to solve this by manually removing the symbols from one of the .a library files (This link shows it's quite a common problem!)
EDIT : This link is a much clearer step by step solution to the problem

Apple uses the following code in the header of all its framework classes.
Not necessarily for the ObjC APIs. But CoreFoundation, yes they use include guards. It's still idiomatic in many camps to use traditional #includes in C sources, and to use #import for objc sources (#import is a compiler extension, not traditional C).
Is this a recommended approach for eliminating "duplicate symbol" linker errors
No, it does not prevent linker errors; it can result in duplicate declaration errors during compile phases.
If you're getting duplicate symbol linker errors, the problem is something else, such as visibility of definition. For that, you should provide an example of your troubling program.

Related

Linker Error in iOS (duplicate symbols for architecture x86_64) when running on Xcode simulator

duplicate symbol _llvm.cmdline in:
/Users/inntot/Documents/navigationdrawer 2 2 2 2 2/Pods/GoogleInterchangeUtilities/Frameworks/GoogleInterchangeUtilities.framework/GoogleInterchangeUtilities(Descriptor.pb.o)
/Users/inntot/Documents/navigationdrawer 2 2 2 2 2/Pods/GoogleSymbolUtilities/Frameworks/GoogleSymbolUtilities.framework/GoogleSymbolUtilities(overload.o)
duplicate symbol _llvm.embedded.module in:
/Users/inntot/Documents/navigationdrawer 2 2 2 2 2/Pods/GoogleInterchangeUtilities/Frameworks/GoogleInterchangeUtilities.framework/GoogleInterchangeUtilities(Descriptor.pb.o)
/Users/inntot/Documents/navigationdrawer 2 2 2 2 2/Pods/GoogleSymbolUtilities/Frameworks/GoogleSymbolUtilities.framework/GoogleSymbolUtilities(overload.o)
A duplicate symbol error means that somewhere in your project being compiled, something that can only be defined once (like a function, const or class) is being defined twice, and hence the name, duplicated, so the compiler is unsure which definition to use.
However, it is highly likely that this is not a problem with you. These particular symbols, namely _llvm.cmdline and _llvm.embedded.moduleare not generally user-defined symbols and are generally created instead by a framework that you are using, people have encountered this error using frameworks by Twitter and Facebook as well. Looking at the paths to the two files where there are conflicting symbols confirms my suspicion. The errors are being generated in a file in the Google Utils framework.
Firstly, if you made any changes to these google framework files themselves, undo them, as your added or changed code may be the problem.
There are a few fixes that may work for you. The first is that this could be a cocoapods issue. Ensure that you have the default "Debug" and "Release" build configurations in your project, otherwise cocoapods will not handle this well. The next fix that I would suggest is to not include the GoogleInterchangeUtilities framework in the project. GoogleSymbolUtilities was in fact introduced to fix this error cropping up in other google frameworks, so try ONLY including googleSymbolUtilities in your project rather than both symbolutilities and interchangeutilities. Failing that, If there are other versions of these two google frameworks you can download, download a different version, as a fix might have been released or you can find a version before this bug occurred.
If none of these work for you then I would advise getting in touch with google to notify them of this issue, and then sitting tight for a fix.
You can try
Project-> Build Settings-> Enabled bit code (change it From Yes to No) i hope it works for you, if it doesn't please check your pods updated or not or if still your facing problem give some details about issue.

iOS Static Library | Linking only USED symbols

I am using some third party iOS Static Libraries and am having some trouble keeping the binary size small. The libraries that I am using have an Objective-C interface that is backed by native C/C++ code. The issue is that ALL of the symbols from the library (checked with nm) are being included in my App when linked (even if I don't reference any of the code in the library). This is contrary to my understanding of static libraries where only the code that your application (or other linked libraries) reference is pulled into your application.
I've done a bunch of reading and have found that due to the dynamic nature of Objective-C, there are particular issues that can arise from linking object files or static libraries containing only Objective-C category methods. Because of this, you can pass the -ObjC flag to the linker to have the linker pull in ALL object files containing Objective-C classes or categories. This ensures that all classes and categories are defined at runtime, but bloats your App's binary with unused Objective-C classes/categories/method definitions.
Strangely enough, I am seeing the effects of adding the -ObjC linker flag while not using it anywhere in my build. ALL of the Objective-C symbols are being included, and as a consequence, ALL of the native C/C++ symbols that the Objective-C code references, whether or not my App references any of the code in the library. Has anyone else experienced this problem or found a solution to it?
OS X 10.11.4 and Xcode 7.3.
First, a disclaimer: I haven't personally tried the solution I describe here (all the projects I've worked on just use the -ObjC flag indiscriminately), so YMMV.
That said, this might be of use: https://github.com/CocoaPods/CocoaPods/issues/712
Basically, the idea is, rather than using the -Objc carpet bomb, you can do a slightly more targeted load on a per-library basis: -force_load $(TARGET_BUILD_DIR)/lib<yourLibName>.a.
The author of the referenced link specifically mentions CocoaPods as the culprit for a specific problem he encountered, but I would think (hope) that this solution would apply to the more general question you're asking.
As to the question of why you even have to bother, the only thing I can find that even comes close to an actual explanation can be found here: https://developer.apple.com/library/mac/qa/qa1490/_index.html. This post describes an "impedance mismatch" between Unix (BSD) static libraries and the more dynamic Objective-C based libraries (even static ones) containing e.g. categories. Current linkers can't make the required connections at compile/link time for methods that are essentially bound at runtime, so these linker flags are a workaround to that problem.

BitCode and unexported_symbols_list cannot be used together?

For an iOS Framework, I'd like to be able to hide the symbols inside of it, in order to prevent collisions when the framework, and the application that uses the framework, include different versions of the same 3rd party library.
Until now this has been possible by specifying -unexported_symbols_list in the options.
However, in Xcode 7 Beta 5, the following error message...
-unexported_symbols_list and -bitcode_bundle (Xcode
setting ENABLE_BITCODE=YES) cannot be used together
...occurs when trying to compile the BitCode version of the framework.
So, I have three (3) questions:
1) Is there a straightforward way to hide your symbols when compiling BitCode?
2) If not, is there anything else that can be done to keep the Framework's 3rd-party libraries from colliding with the Application's 3rd-party libraries when they are the same lib, but different versions?
3) Why can't -unexported_symbols_list and -bitcode_bundle be used together?
Partial answer (since I am also looking for the complete answer)
When using -exported_symbols_list or -unexported_symbols_list in the options, the various functions symbols are turned into local symbols.
For some reason, the linker is unable use bitcode option with local symbols.
Hence the two cannot be used together.
Also note, strip keyword which is used for symbol hiding can hide global symbols but the library has to be dynamic.
This is an option I haven't explored completely yet. If a dynamic library works for you, then you should explore it.
If this helps someone get a different perspective as to how to resolve this issue, that would be awesome.

So many errors occurred when I using the ARC convertion tool

I have a project previously built in iOS 4.3. When I tried to invoke the “ARC” conversion tool with
Edit > Refactor > Convert to Objective-C ARC
from XCode 4.5.2, the tool reports many errors. Some are supposed to be modified automatically by itself, for example the keywords autorelease/release/retain should not be used.
The errors seem too many (1,987 occurrences) to resolve by hand. Are there any configuration options that i am missing or should something else be done?
If you are using existing libraries you can simply not use ARC for those libraries and begin using it throughout your app by using a flag.
Add this to your library or files in question to ignore ARC
-fno-objc-arc
i think you have used any third party libraries, if you have used any third party libraries then it won't helps you.that means in this situation it wont automatically converts it to ARC.
Unfortunately ARC manages memory only for objective-c objects, if you have used any C or C++ files then in this case you have to handle memory management yourself

SKPSMTPMessage library

I am getting the error you see in the photo when I import the SKPSMTPMessage library:
The point is that I have no idea what it means. I have done a clean, I have added the files under the Compile Sources, and I have added the CFNetwork framework. Any idea what it means??
You're getting all sorts of "duplicate symbol errors" getting spewed because the same symbols are defined in both a file you're including ("Base64Transcoder.m") and a SDK you are including (the DropBox SDK). So the compiler doesn't know which symbol you really want to use at run time.
I recommend removing "Base64Transcoder.m" from your project, at least temporarily, to see if all those duplicate symbol errors go away.

Resources