通过-weak_library

时间:2017-11-17 08:01:14

标签: ios objective-c xcode linker static-libraries

问题:

是否可以弱链接静态库(Obj-C)?

简短细节

我确实希望我的自定义静态框架( MyFramework.framework )弱链接我的其他自定义静态库( libMyLibrary.a )。

libMyLibrary.a 背后的功能是可选的,如果 NO libMyLibrary.a 被任何第三方应用程序链接,则可以省略使用 MyFramework.framework

I am using -weak_library。我的测试应用程序抱怨静态链接器无法在 MyFramework MyClass符号中找到 MyLibrary 的符号ABCTracker.o

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二进制文件,结果是一个静态lib文件 libMyLibrary.a ,标题为 MyLib.h
  • libMyLibrary.a 已从 MyFramework.framework 目标&#39> 构建阶段>中删除链接二进制文件库as suggested here)。只有 MyLib.h 可以使用框架类中的库API
  • NO Bitcode既不在框架中使用,也不在库中使用
  • MyFramework.framework libMyLibrary.a 和自定义应用程序都是用Objective-C编写的
  • MyLib.h 只定义一个Objective-C类MyClass
  • MyFramework.framework 使用其自己的类MyClass中的ABCTracker来有条件地检查运行时期间的符号可用性,例如NSClassFromString(@"MyClass") == NULL
  • MyFramework 目标&#39> 构建设置我已将Other Librarian FlagsOther Linker Flags设置为相同的值{{1} }:

    -weak_library MyLibrary

结果

  • MyFramework.framework 构建正常
  • 构建之后,我检查了生成的二进制文件中的符号,输出是emty(静态库中没有符号构建到静态框架二进制文件中):

    OTHER_LDFLAGS = (
        "-weak_library",
        MyLibrary,
    );
    OTHER_LIBTOOLFLAGS = "-weak_library MyLibrary";
    
  • 尽管如此,我的测试应用程序与 MyLibrary 无关,构建时出现$ otool -L MyFramework.framework/MyFramework | grep MyClass 错误:

    ld

我在这里做错了什么?

其他观察

MyFramework 目标中,我将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) Other Librarian Flags设置为相同的值:

  • Other Linker Flags。结果:-lMyLibrary显示库的符号已构建到框架中(预期)。
  • otool。结果与-weak-lMyLibrary(预期?)
  • 相同

我的应用目标中,我将lMyLibrary设置为Other Linker Flags。结果:链接器错误稍有变化:

-force_load MyLibrary

1 个答案:

答案 0 :(得分:1)

我也没有成功地让XCode正确地弱连接静态库,虽然我遇到了与你相反的问题 - 对我来说nm显示了静态库中的所有符号,而不是“U” “(未定义)符号类型,如您在链接框架时所看到的那样。

但您可以使用的解决方法如下:

  1. 创建一个名为 MyWrapper.framework 的新Cocoa Touch Framework项目,并将 libMyLibrary.a 添加到其中
  2. -ObjC添加到链接器标志以确保获得所有符号 已加载(如果您需要非Obj-C符号,则为-all_load
  3. 将您的图书馆标题添加到构建阶段
  4. 中框架的公共标题部分
  5. 构建此框架(您需要为所有体系结构设置聚合目标,但这是一个完全独立的主题)
  6. 打开 MyFramework.framework 项目并向其添加 MyWrapper.framework ,弱链接(即使用切换将其设置为可选或者如果您希望将其从链接二进制文件库阶段删除,并通过-weak_framework添加到其他链接标记
  7. 现在构建 MyFramework.framework
  8. 在您的测试应用中,删除对 libMyLibrary.a
  9. 的任何引用
  10. 您应该能够在没有崩溃的情况下运行您的测试应用,并且您的代码检测 libMyLibrary.a
  11. 中是否存在符号
  12. MyWrapper.framework 添加到您的测试应用中,然后您会看到相反的结果 - libMyLibrary.a 中的符号将被找到并可用。