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)