简体   繁体   English

通过-weak_library弱链接静态库

[英]Weakly link static library via -weak_library

Question: 题:

Is it possible to weakly link a static library (Obj-C)? 是否可以弱链接静态库(Obj-C)?

Short Details 简短的细节

I do want my custom static framework ( MyFramework.framework ) to weakly link my other custom static library ( libMyLibrary.a ). 我确实希望我的自定义静态框架( MyFramework.framework )弱链接我的其他自定义静态库( libMyLibrary.a )。

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 . 背后libMyLibrary.a的功能是可选的,如果没有 libMyLibrary.a被使用MyFramework.framework任何第三方应用程序链接可以省略。

I am using -weak_library . 我正在使用-weak_library My test application complains that static linker is unable to find MyLibrary 's symbol MyClass within MyFramework 's ABCTracker.o symbol: 我的测试应用程序抱怨静态链接器无法在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)

How to correctly setup weak linking? 如何正确设置弱链接?

Full Details 详细资料

Setup 设定

  • The Xcode project builds a static Mach-O binary and bundles it into a static framework. Xcode项目构建一个静态的Mach-O二进制文件并将其捆绑到一个静态框架中。 The result is MyFramework.framework bundle. 结果是MyFramework.framework捆绑包。
  • Other project builds a static Mach-O binary and the result is a static lib file libMyLibrary.a with a header MyLib.h 其他项目建立一个静态的Mach-O二进制文件,结果是一个头MyLib.h静态库文件libMyLibrary.a
  • libMyLibrary.a is removed from MyFramework.framework target's Build Phases > Link Binary With Libraries ( as suggested here ). libMyLibrary.a已从MyFramework.framework目标的Build Phases > Link Binary With Libraries如此处建议 )中删除。 Only MyLib.h is available to use library's API from the framework's classes 只有MyLib.h可以使用框架类中的库API
  • 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 MyFramework.frameworklibMyLibrary.a和自定义应用程序均用Objective-C编写
  • The MyLib.h defines just one Objective-C class MyClass MyLib.h仅定义一个Objective-C类MyClass
  • MyFramework.framework uses MyClass from its own class ABCTracker conditionally checking for symbol availability during runtime, eg NSClassFromString(@"MyClass") == NULL MyFramework.framework使用其自身类ABCTracker MyClass有条件地在运行时检查符号的可用性,例如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 : MyFramework目标的Build Settings中,我将Other Librarian FlagsOther Linker Flags为相同的值-weak_library MyLibrary

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

Result 结果

  • MyFramework.framework builds OK MyFramework.framework建立成功
  • 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): 构建之后,我检查了生成的二进制文件中的符号,输出为emty(静态库中没有任何符号内置到静态框架二进制文件中):

     $ otool -L MyFramework.framework/MyFramework | grep MyClass 
  • Despite that, my test application which is not linked with MyLibrary whatsoever, builds with ld error: 尽管如此,我的未与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) 

What am I doing wrong here? 我在这里做错了什么?

Other Observations 其他观察

In MyFramework target I set Other Librarian Flags and Other Linker Flags of to same value: MyFramework目标中,我将Other Librarian FlagsOther Linker Flags设置为相同的值:

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

In my application target I set Other Linker Flags to -force_load MyLibrary . 我的应用程序目标中,我将Other Linker Flags设置为-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)

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. 我也没有成功地使XCode正确弱链接静态库,尽管我遇到了与您相反的问题-对我来说, nm显示了静态库中的所有符号,而不是“ U”(未定义)符号类型当您弱连接框架时,您会看到。

But a workaround you can use is the following: 但是,可以使用以下解决方法:

  1. Create a new Cocoa Touch Framework project called MyWrapper.framework and add libMyLibrary.a to it 创建一个名为MyWrapper.framework的新Cocoa Touch Framework项目,并将libMyLibrary.a添加到其中
  2. Add -ObjC to the linker flags to make sure all the symbols get loaded (and -all_load if you need non Obj-C symbols) -ObjC到链接器标志中,以确保所有符号-all_load加载(如果需要非Obj-C符号,则添加-all_load
  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 (ie 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 ) 打开MyFramework.framework项目,并向其中添加MyWrapper.framework ,使其链接较弱(即,使用切换将其设置为Optional,或者如果您更喜欢从“ 与库链接二进制文件”阶段将其删除,并通过-weak_framework将其添加到Other Linker Flags )。
  6. Now build MyFramework.framework 现在构建MyFramework.framework
  7. In your testing app, remove any reference to libMyLibrary.a 在您的测试应用中,删除对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 你应该能够无碰撞运行测试应用程序,你的代码应该检测的符号从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. MyWrapper.framework添加到您的测试应用程序中,然后您将看到相反的结果-libMyLibrary.a中的符号将被找到并可用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM