Question:
Is it possible to weakly link a static library (Obj-C)?
Short Details
I do want my custom static framework (MyFramework.framework) to weakly link my other custom static library (libMyLibrary.a).
The functionality behind libMyLibrary.a is optional and can be omitted if there is NO libMyLibrary.a being linked by any 3rd party application that uses MyFramework.framework.
I am using -weak_library
. My test application complains that static linker is unable to find MyLibrary's symbol MyClass
within MyFramework's ABCTracker.o
symbol:
Undefined symbols for architecture arm64:
"_OBJC_CLASS_$_MyClass", referenced from:
objc-class-ref in MyFramework(ABCTracker.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
How to correctly setup weak linking?
Full Details
Setup
- The Xcode project builds a static Mach-O binary and bundles it into a static framework. The result is MyFramework.framework bundle.
- Other project builds a static Mach-O binary and the result is a static lib file libMyLibrary.a with a header MyLib.h
- libMyLibrary.a is removed from MyFramework.framework target's Build Phases > Link Binary With Libraries (as suggested here). Only MyLib.h is available to use library's API from the framework's classes
- NO Bitcode is used neither in the framework, nor in the library
- MyFramework.framework, libMyLibrary.a and custom application are all written in Objective-C
- The MyLib.h defines just one Objective-C class
MyClass
- MyFramework.framework uses
MyClass
from its own classABCTracker
conditionally checking for symbol availability during runtime, e.g.NSClassFromString(@"MyClass") == NULL
From MyFramework target's Build Settings I have set
Other Librarian Flags
andOther Linker Flags
to same value-weak_library MyLibrary
:OTHER_LDFLAGS = ( "-weak_library", MyLibrary, ); OTHER_LIBTOOLFLAGS = "-weak_library MyLibrary";
Result
- MyFramework.framework builds OK
After the build I have checked the symbols in the resulting binary and the output was emty (no symbols from the static library were built into static framework binary):
$ otool -L MyFramework.framework/MyFramework | grep MyClass
Despite that, my test application which is not linked with MyLibrary whatsoever, builds with
ld
error:Undefined symbols for architecture arm64: "_OBJC_CLASS_$_MyClass", referenced from: objc-class-ref in MyFramework(ABCTracker.o) ld: symbol(s) not found for architecture arm64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
What am I doing wrong here?
Other Observations
In MyFramework target I set Other Librarian Flags
and Other Linker Flags
of to same value:
-lMyLibrary
. Result:otool
shows the library's symbols are built into the framework (expected).-weak-lMyLibrary
. Result is the same as forlMyLibrary
(is it expected?)
In my application target I set Other Linker Flags
to -force_load MyLibrary
. Result: the linker error slightly changes:
ld: file not found: MyClass
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I have also not been successful at getting XCode to properly weak link a static library, although I have the opposite problem from yours - for me
nm
showed all the symbols from the static library, and not with "U" (undefined) symbol type as you see when you weak link a framework.But a workaround you can use is the following:
-ObjC
to the linker flags to make sure all the symbols get loaded (and-all_load
if you need non Obj-C symbols)-weak_framework
to Other Linker Flags)