问题:
是否可以弱链接静态库(Obj-C)?
详细信息
我确实希望我的自定义静态框架 (MyFramework.framework) 弱链接我的其他自定义静态库 (libMyLibrary.a)。
libMyLibrary.a 背后的功能是可选的,如果没有 NO libMyLibrary.a 被任何第 3 方应用程序链接,则可以省略使用 MyFramework.framework。
I am using -weak_library
。我的测试应用程序提示静态链接器无法在 MyFramework 的 ABCTracker.o
中找到 MyLibrary 的符号 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)
如何正确设置弱链接?
详细信息
设置
- Xcode 项目构建了一个静态 Mach-O 二进制文件并将其捆绑到一个静态框架中。结果是 MyFramework.framework 包。
- 其他项目构建静态 Mach-O 二进制文件,结果是静态库文件 libMyLibrary.a, header 为 MyLib.h
- libMyLibrary.a 已从 MyFramework.framework 目标的Build Phases> Link Binary With Libraries ( as suggested here ).只有 MyLib.h 可用于从框架的类中使用库的 API
- NO Bitcode既不在框架中也不在库中使用
- MyFramework.framework、libMyLibrary.a 和自定义应用程序都是用 Objective-C 编写的
- MyLib.h 只定义了一个 Objective-C 类
MyClass
- MyFramework.framework 使用它自己的类
ABCTracker
中的MyClass
在运行时有条件地检查符号可用性,例如NSClassFromString(@"MyClass") == NULL
从 MyFramework 目标的 Build Settings 我已将
Other Librarian Flags
和Other Linker Flags
设置为相同的值-weak_library MyLibrary
:OTHER_LDFLAGS = ( "-weak_library", MyLibrary, ); OTHER_LIBTOOLFLAGS = "-weak_library MyLibrary";
结果
- MyFramework.framework 构建正常
在构建之后,我检查了生成的二进制文件中的符号,输出为空(静态库中的符号没有内置到静态框架二进制文件中):
$ otool -L MyFramework.framework/MyFramework | grep MyClass
尽管如此,我的测试应用程序未与任何 MyLibrary 链接,构建时出现
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
显示库的符号已内置到框架中(预期)。-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)
最佳答案
我也没有成功地让 XCode 正确地弱链接静态库,尽管我遇到了与您相反的问题 - 对我来说 nm
显示了静态库中的所有符号,而不是使用弱链接框架时看到的“U”(未定义)符号类型。
但您可以使用以下解决方法:
- 创建一个名为 MyWrapper.framework 的新 Cocoa Touch Framework 项目,并向其中添加 libMyLibrary.a
- 将
-ObjC
添加到链接器标志以确保所有符号都得到 加载(和-all_load
如果你需要非 Obj-C 符号) - 将您的库的 header 添加到构建阶段中框架的公共(public) header 部分
- 构建此框架(您需要设置一个聚合目标以构建所有架构,但这是一个完全独立的主题)
- 打开您的 MyFramework.framework 项目并将 MyWrapper.framework 添加到其中,弱链接(即使用切换将其设置为可选或者,如果您希望将其从Link Binary with Libraries 阶段移除并通过
-weak_framework
添加到Other Linker Flags) - 现在构建MyFramework.framework
- 在您的测试应用中,删除对 libMyLibrary.a 的所有引用
- 您应该能够在没有崩溃的情况下运行您的测试应用程序,并且您的代码应该不检测到来自 libMyLibrary.a 的符号的存在
- 将 MyWrapper.framework 添加到您的测试应用程序,然后您应该会看到相反的结果 - 来自 libMyLibrary.a 的符号将被发现并可用。
关于ios - 通过-weak_library 弱链接静态库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47345870/