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 标志的输出?

4

1 回答 1

8

-all_load用于当您想要链接(到链接器)不必要的编译单元时。例如,也许您将在运行时动态访问静态库中您知道地址但实际上并未进行任何显式函数调用的函数。你会怎么做?好吧,编译器可以通过将一堆函数指针存储在可执行文件中以在运行时读取来帮助您,然后您将构建一个查找系统以使用字符串查找这些函数,然后您将整个事情称为 Objective -C,这可能是最常见的用户-all_load(至少如果谷歌是任何指南的话)。

ObjC 中最常见的情况是当您在自己的编译单元中有一个类别时。编译器可能无法告诉您引用它,因此不会链接它。所以 ObjC 程序员比其他类似 C 的程序员更频繁地使用-all_load(或)。-force_load实际上,-all_load是 gcc 中的一个达尔文特有的扩展。

但在某些情况下,人们可能希望-all_load在 ObjC 之外使用。例如,libA 和 libB 中可能存在一些相互依赖关系。考虑这种情况:

  • source.cpp 需要A()B()

  • libA 定义A()ina.oAprime()inaprime.o

  • libB 定义B()b.o要求Aprime()

这通常不会链接 (*)。编译器将从以下各项开始source.o并列出要求:A()B(). 然后它会查看 libA 并看到它定义了A(),所以它会链接a.o(但不是 aprime.o)。然后它将查看 libB 并查看它定义B()和需要Aprime(). 它现在没有库了,而且还没有解决Aprime()。它失败。

(*)实际上,它会与 clang 一起使用,因为 clang 对此非常聪明。但至少在 4.6 之前不会使用 g++。

最好的解决方案是重新排序,以便 libB 排在第一位 (**)。但如果依赖关系是循环的,你可能会完全陷入困境。-all_load-force_load让您通过关闭链接器的优化来解决这些情况。

(**)真正最好的解决方案通常是重新设计你的库以避免这种相互依赖,但这可能希望太多。

如果你想解决这个问题,请参阅https://gist.github.com/rnapier/5710509

strip只是从可执行文件中删除符号。这与静态链接并没有特别相关-all_load(尽管它确实会影响动态链接)。strip(1)对此有很多讨论。

于 2013-06-04T23:41:13.683 回答