包括带有-all_load标志的静态库

时间:2013-06-04 20:10:59

标签: macos gcc compiler-construction g++ clang

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

让我说我有类似

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

我记得如果有一些对source.cpp中使用的符号的引用 在说libB.a文件中,libB.a将被链接(只是该库中的符号或整个代码?),libA.alibC.a将被忽略(他们的代码不会出现在最终的可执行文件中。)

  • 当我使用-all_load标志时,其他库会发生什么?

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

  • 'strip'命令如何使用all_load标志影响输出?

1 个答案:

答案 0 :(得分:7)

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

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

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

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

  • libA定义A()中的a.oAprime()中的aprime.o

  • libB在B()中定义b.o并需要Aprime()

这通常不会链接(*)。编译器将从source.o开始,并列出要求列表:A()B()。然后它将查看libA并查看它定义A(),因此它将链接a.o(但不是 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)对此进行了大量讨论。