在什么情况下你需要-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标志影响输出?
答案 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.o
和Aprime()
中的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)对此进行了大量讨论。