使用-all_load标志包含静态库

7

在什么情况下需要使用-all_load标志?

假设我有以下内容:

g++ source.cpp -o test libA.a libB.a libC.a

据我记得,如果在source.cpp中有对某个符号的引用,并且该符号存在于libB.a文件中,那么libB.a将被链接(只链接该符号还是整个库?),而libA.a和libC.a将被忽略(它们的代码将不会出现在最终的可执行文件中)。

  • 使用以下-all_load标志时,其他库会发生什么情况:

    g++ source.cpp -o test -Wl,-all_load libA.a libB.a libC.a

  • 'strip'命令如何影响带有all_load标志的输出?

1个回答

9
-all_load是用于链接编译单元,这些单元(对于链接器来说)是不必要的。例如,也许你会在运行时动态访问静态库中的函数,你知道地址,但实际上并没有进行任何显式的函数调用。你该怎么做呢?好吧,编译器可以通过在可执行文件中存储一堆函数指针来帮助你,在运行时读取,然后你将构建一个查找系统来使用字符串查找那些函数,最后你会将整个东西称为Objective-C,这可能是-all_load最常见的用户(至少如果谷歌是任何指南的话)。
在ObjC中最常见的情况是当你有一个独立的编译单元时。编译器可能无法确定你是否引用它,因此不会链接它。因此,ObjC程序员比其他类C程序员更经常使用-all_load(或-force_load)。事实上,-all_load是gcc中的一个特定于Darwin的扩展。
但是,人们可能希望在ObjC之外使用-all_load的情况也存在。例如,libA和libB之间可能存在一些相互依赖关系。考虑以下情况:
- source.cpp需要A()B() - libA在中定义了A(),在中定义了Aprime() - libB在中定义了B()并需要Aprime() 这通常无法链接(*)。编译器将从source.o开始,并列出要求:A()B()。然后它将查看libA并看到它定义了A(),因此它将链接(但不是aprime.o)。然后它将查看libB并看到它定义了B()并需要Aprime()。现在它已经没有库可以使用,而且它还没有解决Aprime()。它失败了。
(*) 实际上,clang会成功,因为clang对此非常聪明。但至少在g++ 4.6之前,它不会成功。
最好的解决方案是重新排序,使libB首先出现(**)。但如果依赖关系是循环的,你可能会完全卡住。-all_load-force_load让您通过关闭链接器的优化来解决这些情况。
(**) 最好的解决方案通常是重新设计您的库以避免这种相互依赖关系,但这可能希望过高。
如果你想处理这个问题,可以参考https://gist.github.com/rnapier/5710509
`strip`仅仅是从可执行文件中移除符号。这与静态链接和`-all_load`没有特别的关系(尽管它会影响动态链接)。strip(1)中有很多相关讨论。

据我所知,在较新版本的clang中,-force_load无效。 - Alex Gray

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接