SomeRandomiOSDev
SomeRandomiOSDev

Reputation: 184

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.

Upvotes: 2

Views: 1238

Answers (1)

fullofsquirrels
fullofsquirrels

Reputation: 1858

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.

Upvotes: 1

Related Questions