【问题标题】:Weakly link static library via -weak_library通过 -weak_library 弱链接静态库
【发布时间】:2023-04-03 14:00:01
【问题描述】:

问题:

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

简短的细节

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

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

I am using -weak_library。我的测试应用程序抱怨静态链接器无法在 MyFrameworkABCTracker.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 二进制文件,结果是一个静态 lib 文件 libMyLibrary.a,其标题为 MyLib.h
  • libMyLibrary.a 已从 MyFramework.framework 目标的 Build Phases > Link Binary With Libraries 中移除 (as suggested here) .只有 MyLib.h 可用于使用框架类中的库 API
  • 框架和库中均未使用任何位码
  • MyFramework.frameworklibMyLibrary.a 和自定义应用程序都是用 Objective-C 编写的
  • MyLib.h 只定义了一个 Objective-C 类 MyClass
  • MyFramework.framework 使用自己的类 ABCTracker 中的 MyClass 在运行时有条件地检查符号可用性,例如NSClassFromString(@"MyClass") == NULL
  • MyFramework 目标的 Build Settings 我已将 Other Librarian FlagsOther Linker Flags 设置为相同的值 -weak_library MyLibrary

    OTHER_LDFLAGS = (
        "-weak_library",
        MyLibrary,
    );
    OTHER_LIBTOOLFLAGS = "-weak_library MyLibrary";
    

结果

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

    $ 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 FlagsOther 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 实际上弱链接静态库那么干净
  • 我解决了最初的问题(为了简单起见,我没有在这里发布)。问题是符号重复,当 MyFramework.frameworkmy application staticky 与 libMyLibrary.a 链接时。我认为弱链接库可以解决符号重复问题。不过,我采取了另一种方式,在静态库编译期间重新定义符号:将OTHER_CFLAGS 设置为-DMyClass =MyPrefixMyClassMyFramework.frameworkmy application 需要单独的构建目标。
  • 听起来您从未完全解决过-weak-lMyLibrary 导致与-lMyLibrary 相同(错误)包含符号的问题?
  • @Danny 正确。

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


【解决方案1】:

我也没有成功让 XCode 正确弱链接静态库,尽管我遇到了与你相反的问题 - 对我来说,nm 显示了静态库中的所有符号,而不是“U”( undefined) 符号类型,就像你弱链接框架时看到的那样。

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

  1. 创建一个名为 MyWrapper.framework 的新 Cocoa Touch 框架项目并将 libMyLibrary.a 添加到其中
  2. -ObjC 添加到链接器标志以确保所有符号都得到 已加载(如果您需要非 Obj-C 符号,还有 -all_load
  3. 构建阶段中将库的标头添加到框架的Public Headers部分
  4. 构建此框架(您需要设置一个聚合目标来构建所有架构,但这是一个完全独立的主题)
  5. 打开您的 MyFramework.framework 项目并将 MyWrapper.framework 添加到它,弱链接(即使用切换将其设置为 可选或者,如果您希望将其从 Link Binary with Libraries 阶段中删除,并通过 -weak_framework 将其添加到 Other Linker Flags
  6. 现在构建 MyFramework.framework
  7. 在您的测试应用中,删除对 libMyLibrary.a 的所有引用
  8. 您应该能够在没有崩溃的情况下运行您的测试应用,并且您的代码应该检测到来自 libMyLibrary.a 的符号的存在
  9. MyWrapper.framework 添加到您的测试应用程序中,然后您应该会看到相反的结果 - libMyLibrary.a 中的符号将被发现并可用。

【讨论】:

  • MyWrapper.frameworkstatic 框架吗?您的解决方案听起来很有希望。我会试一试的。
  • 不,它是一个动态框架 - 这就是允许在 MyFramework.framework 中适当地弱链接
猜你喜欢
  • 2021-11-06
  • 2018-12-06
  • 1970-01-01
  • 1970-01-01
  • 2013-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多