本文介绍了通过-weak_library弱链接静态库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is it possible to weakly link a static library (Obj-C)?

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

I do want my custom static framework (MyFramework.framework) to weakly link my other custom static library (libMyLibrary.a).

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

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.

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

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)

如何正确设置弱链接?

  • 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 class ABCTracker conditionally checking for symbol availability during runtime, e.g. NSClassFromString(@"MyClass") == NULL
  • From MyFramework target's Build Settings I have set Other Librarian Flags and Other Linker Flags to same value -weak_library MyLibrary:

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

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

  • 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

  • 尽管如此,我的未与 MyLibrary 链接的测试应用程序都生成了ld错误:

  • 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)
    

  • 我在这里做什么错了?

    MyFramework 目标中,将Other Librarian FlagsOther Linker Flags设置为相同的值:

    In MyFramework target I set Other Librarian Flags and Other Linker Flags of to same value:

    • -lMyLibrary.结果:otool显示库的符号已内置到框架中(预期).
    • -weak-lMyLibrary.结果与lMyLibrary相同(是预期的吗?)
    • -lMyLibrary. Result: otool shows the library's symbols are built into the framework (expected).
    • -weak-lMyLibrary. Result is the same as for lMyLibrary (is it expected?)

    我的应用目标中,将Other Linker Flags设置为-force_load MyLibrary.结果:链接器错误略有变化:

    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)
    

    推荐答案

    我也没有成功让XCode适当地弱链接静态库,尽管我遇到了与您相反的问题-对我来说nm显示了所有静态库中的符号,而不是弱链接框架时看到的"U"(未定义)符号类型.

    I have also not been successful at getting XCode to properly weak link a static library, although I have the opposite problem from yours - for me nm showed all the symbols from the static library, and not with "U" (undefined) symbol type as you see when you weak link a framework.

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

    But a workaround you can use is the following:

    1. 创建一个名为 MyWrapper.framework 的新Cocoa Touch Framework项目,并向其中添加 libMyLibrary.a
    2. -ObjC添加到链接器标志以确保所有符号都被获取已加载(如果需要非Obj-C符号,则为-all_load)
    3. 将库的标头添加到构建阶段
    4. 中框架的公共标头部分
    5. 构建此框架(您将希望为所有体系结构建立一个聚合目标,但这是一个单独的主题)
    6. 打开您的 MyFramework.framework 项目,并将其添加到链接较弱的 MyWrapper.framework (即,使用切换开关将其设置为可选或者如果您希望将其从与库链接二进制文件阶段删除,然后通过-weak_framework将其添加到 Other Linker Flags (其他链接器标记))
    7. 现在构建 MyFramework.framework
    8. 在您的测试应用中,删除对 libMyLibrary.a
    9. 的所有引用
    10. 您应该能够在没有崩溃的情况下运行测试应用,并且您的代码应该检测到 libMyLibrary.a
    11. 中是否存在符号.
    12. MyWrapper.framework 添加到测试应用程序中,然后您将看到相反的结果-将找到并使用 libMyLibrary.a 中的符号.
    1. Create a new Cocoa Touch Framework project called MyWrapper.framework and add libMyLibrary.a to it
    2. Add -ObjC to the linker flags to make sure all the symbols getloaded (and -all_load if you need non Obj-C symbols)
    3. Add your library's headers to the framework's Public Headers section in Build Phases
    4. Build this framework (you'll want to set up an aggregate target to build for all architectures but that is a whole separate topic)
    5. Open your MyFramework.framework project and add MyWrapper.framework to it, weakly linked (i.e. use the toggle to set it to Optional or if you prefer remove it from the Link Binary with Libraries phase and add it via -weak_framework to Other Linker Flags)
    6. Now build MyFramework.framework
    7. In your testing app, remove any reference to libMyLibrary.a
    8. You should be able to run your testing app with no crash and your code should not detect the presence of symbols from libMyLibrary.a
    9. Add MyWrapper.framework to your testing app and then you should see the opposite result - symbols from libMyLibrary.a will be found and usable.

    这篇关于通过-weak_library弱链接静态库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    08-13 19:16