Linker flags for iOS with Xcode - ios

Where can I find documentation on the compiler flags and linker flags that we can specify for our iOS projects in Xcode?
The present reason I want to read more on the possible flags in the first place is that the Google Admob SDK says we MUST set the linker -Objc flag, whereas Facebook SDK suggests NOT setting it for smaller binaries. So, I was wondering, can we set Objc for a particular library (google admob in this case) and have it unset for another library (facebook)? I expected to be able to find a man page or some other doc about what the compiler and linker options are in the first place, and then zoom in on Objc. There's tons of documentation and stackoverflow posts etc. on how to set linker flags in Xcode. What's lacking is a listing of possible linker flags we can set, and what they each mean.
Surprisingly, googling around made me quite confused, as there's stuff on clang, llvm, llvm-gcc, etc., and LLVM site lists a number of llvm commands but I don't see -Objc listed in any of the corresponding pages. Apart from the question of whether the compiler and linker are clang or llvm, or whatever they're called, is there a place we could go to in order to read documentation on whatever Xcode is currently using by default for compiling and linking iOS projects? (say, both Xcode 4.6 and Xcode 5.0.2, in case there are different doc sets?) Thanks!

You can try man 1 ld.
For the -ObjC flag in particular the description is:
-ObjC Loads all members of static archive libraries that
implement an Objective-C class or category.
EDIT
For your other question about the AdMob SDK and the Facebook SDK, I would suggest to add the -ObjC to the linker flags and take a look at this article which explains why. Basically Facebook suggests not to use it, because your executable will end up being larger due to additional object code loaded into your binary.

I had this problem when I put a function into my .hpp file.
void logError(char const* szError)
{
...
}
I had to add in the inline to make it work.
inline void logError(char const* szError)
{
...
}
Even better don't define your functions inside your headers.

Related

Can the -ObjC flag be applied selectively to static libraries?

TL;DR
How can I make the -ObjC linker flag target a specific static library and not all the static libraries I am linking against in order to avoid unused object files being linked in with my app?
Too Long; Did Read
So you are developing a new iOS app and you add in your homegrown "objcutil" static library which contains a variety of useful Objective-C classes (not implemented as categories) to do various things that have been useful in the past. So far, so good, and only those object files that are being referenced in the utility library are being linked with the app.
Then you decide to integrate the Google Maps SDK which wants you to use the -ObjC Other Linker Flags and all of a sudden dependencies in the utility library fail to be resolved, because you haven't configured Xcode to link to those libraries.
OK I can resolve the missing dependencies easily enough, however you now have unused object files and library dependencies that you don't need and you'd like to be a bit tidier than that.
So how do you avoid OCD overload?
Some reference from the ld manpage:
-ObjC Loads all members of static archive libraries that define an Objective C class or a category. This option does not apply to dynamic
shared libraries.
Xcode Version: 5.1.1
OSX Version: 10.9.4
OK so the answer is to use -force_load instead of -ObjC as -force_load is more focused.
So WRT to the Google Maps SDK, if you followed the instructions and copied the static framework into the app project directory, then the framework will be in the project root directory and you can remove -ObjC from the Other Linker Flags and replace it with
-force_load GoogleMaps.framework/Versions/Current/GoogleMaps:
Nothing else needs changing.
For other libraries you will need to use the full static library path as the argument to -force_load.

Reason to include "-ObjC" in Xcode

We include "-ObjC"in other linker flags of project settings in Xcode if we include any external libraries or frameworks can any one tell me what is the reason for it and what it does if we include it.
Thanks in Advance..
It's explained pretty well in Apple's QA1490.
Key excerpts:
Objective-C does not define linker symbols for each function (or
method, in Objective-C) - instead, linker symbols are only generated
for each class.
...
To resolve this issue, the target linking against the static library
must pass the -ObjC option to the linker. This flag causes the linker
to load every object file in the library that defines an Objective-C
class or category
Categories are most known use case for this flag (as Apple's QA1490 explains), but they are not the only reason why this flag is needed.
Since Objective-C is a dynamic language which makes things like NSClassFromString() possible, the standard behaviour of C linker of including only actually used symbols (and throwing away all others) does not work, because there is no way to find out whether some symbols are actually used in some indirect ways like concatenating strings then calling NSSelectorFromString or NSClassFromString.
Consider xib/nib files for example: they don't participate in linking stage, yet they may instantiate library classes which are not referred by anything but this nib file. If linker threw away those classes as unused, the nib couldn't load and work properly.
The only way to ensure nothing is lost is to include every Obj-C class from a library at link time, and this flag does that.
-ObjC linker flag causes the linker to load ever object file in the library that defines an Objective-C class or category.
Why to use -ObjC linker flag - Apple Documentation?

Google Analytics and ShareKit

I've been trying to integrate Sharekit to a project that already has google analytics.
I followed the installation guide on the sharekit git wiki which told me to include the 'other linker flags' "-ObjC" and "-all_load"
However when I try compiling I am getting duplicate symbol errors in google analytics, such as:
duplicate symbol _OBJC_IVAR_$_OAServiceTicket.data in:
/Users/x3ro/Library/Developer/Xcode/DerivedData/APPNAME-bgfudbwainndvsdmvtafsrwfryvz/Build/Intermediates/APPNAME.build/Debug-iphonesimulator/APPNAME.build/Objects-normal/i386/OAServiceTicket.o
/Users/x3ro/APPNAME/Developer/Xcode/DerivedData/APPNAME-bgfudbwainndvsdmvtafsrwfryvz/Build/Products/Debug-iphonesimulator/libShareKit.a(OAServiceTicket.o)
Removing the flags solves these errors, however I know this isn't a good idea and I'll very likely run into issues down the line. Any help in getting the flags and both libraries to work together would be really appreciated.
Use the linker flag "-force_load" with the path to Sharekit.
It look like something like this:
-force_load $(BUILT_PRODUCTS_DIR)/libRestKit.a
From Apple Documentation:
-all_load forces the linker to load all object files from every archive it sees, even those without Objective-C code. -force_load is available in Xcode 3.2 and later. It allows finer grain control of archive loading. Each -force_load option must be followed by a path to an archive, and every object file in that archive will be loaded.
You can find others answers with this related post:
Using the force_load linker flag with RestKit (iOS)

Significance of -ObjC value in Other Linker Flags: GMaps SDK

I was trying out google maps sdk integration with iOS 6.1. I am successfully able to populate gmap on iOS simulator by using instructions given on
GMaps for iOS starting guide
Then what the issue with it:
It works great when I use it as a separate project. But when I club the above project code with my existing application, then it behaves weird, and all the errors generates due to inclusion of -ObjC value in Other Linker Flags in Build Settings.
Error
duplicate symbols for architecture i386
When I skip step 7 (GMaps iOS), it doesn't give errors. Due to exclusion of -ObjC value, it doesn't able to identify a specific GMaps library class and its method:
[GMSCameraPosition cameraWithLatitude:longitude:zoom:]: unrecognized selector sent
My iOS application background:
Using a third party library SUP (Sybase Unwired Platform). Connecting SAP to iOS application. I guess there is something ambiguous with SUP environment enablement (Build settings) when I am trying to add GMaps library.
Seeking for your advices.
Thanks!
There many posts on SO about the duplicate symbols for architecture i386 error. Usually it means that you defined the same symbol twice in the one namespace. The last time I got this error was because I accidentally included a .m file instead of .h header file.
Have you checked the Build Architecture?
Try setting Build Active Architecture Only to Yes.
I was facing the same issue Today! -ObjC linker flag - When trying to add it to "Other Linker Flags" I get an error
I solved my problem, Here is what I'd suggest. Take your original project (without Gmaps and with SUP) and add the -ObjC flag to it. Are you still getting an error? If so, take Gmaps out of the equation. If you are still getting an error check in the warnings about which files it is warning you about. My problem was that I had two files libGoogleAnalytics.a and libGoogleAnalytics_debug.a and for some reason they could not coexist with the -ObjC.
Long story short, you need to find what libraries Gmaps is using that you already have in your project and remove one of them.
Please try this…
step 1: Add '-ObjC' to other linker flags in 'Build Settings' of your 'target' only not to the 'project'

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.

Resources