弱链接静态库通过-weak_library
题:
弱链接静态库(Obj-C)有可能吗?
短细节
我希望我的自定义静态框架( MyFramework.framework )弱链接我的其他自定义静态库( libMyLibrary.a )。
libMyLibrary.a背后的function是可选的,如果没有 libMyLibrary.a被任何使用MyFramework.framework的第三方应用程序链接,可以省略。
我正在使用-weak_library
。 我的testing应用程序抱怨静态连接器无法在MyFramework的ABCTracker.o
符号中findMyLibrary的符号MyClass
:
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)
如何正确设置弱链接?
全部细节
build立
- Xcode项目构build一个静态的Mach-O二进制文件并将其捆绑到一个静态框架中。 结果是MyFramework.framework包。
- 其他项目生成一个静态Mach-O二进制文件,结果是一个静态lib文件libMyLibrary.a,带有一个头文件MyLib.h
- libMyLibrary.a从MyFramework.framework目标的“ 构build阶段” >“ 链接二进制库”中移除( 如此处所示 )。 只有MyLib.h可以从框架的类中使用库的API
- NO Bitcode既不用在框架中,也不用在库中
- MyFramework.framework , libMyLibrary.a和自定义应用程序都是用Objective-C编写的
- MyLib.h只定义了一个Objective-C类
MyClass
- MyFramework.framework使用
MyClass
从它自己的类ABCTracker
有条件地检查运行时的符号可用性,例如NSClassFromString(@"MyClass") == NULL
-
从MyFramework目标的构build设置我已经设置
Other Librarian Flags
和Other Linker Flags
为相同的值-weak_library MyLibrary
:OTHER_LDFLAGS = ( "-weak_library", MyLibrary, ); OTHER_LIBTOOLFLAGS = "-weak_library MyLibrary";
结果
- MyFramework.framework生成OK
-
编译后,我已经检查了生成的二进制文件中的符号,输出是emty(静态库中没有符号被构build到静态框架二进制文件中):
$ otool -L MyFramework.framework/MyFramework | grep MyClass
-
尽pipe如此,我的testing应用程序不与MyLibrary链接,build立与
ld
错误: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)
我在这里做错了什么?
其他观察
在MyFramework目标中,我将Other Librarian Flags
和Other Linker Flags
设置为相同的值:
-
-lMyLibrary
。 结果:otool
显示库的符号被构build到框架中(预期)。 -
-weak-lMyLibrary
。 结果与lMyLibrary
相同(是否预期?)
在我的应用程序目标中,我将Other Linker Flags
设置为-force_load MyLibrary
。 结果:链接器错误稍微改变:
ld: file not found: MyClass clang: error: linker command failed with exit code 1 (use -v to see invocation)