在什么情况下,您到底需要-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标志影响输出?

最佳答案

-all_load用于当您想要链接不需要的编译单元(至链接器)时。例如,也许您将在运行时动态访问静态库中的函数,这些函数您知道其地址,但实际上并未对其进行任何显式的函数调用。你会怎么做?好的,编译器可以通过在运行时存储一堆函数指针以在运行时读取这些函数指针来为您提供帮助,然后您将构建一个查找系统以使用字符串查找那些函数,然后将整个过程称为目标-C,它可能是-all_load的最普通用户(至少在Google指导下)。

在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非常聪明。但是至少在4.6版之前,g ++才不会。

最好的解决方案是对其重新排序,以使libB首先出现(**)。但是,如果依赖性是循环的,那么您可能会完全陷入困境。 -all_load-force_load使您可以通过关闭链接器的优化来解决这些情况。

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

如果您想解决该问题,请参见https://gist.github.com/rnapier/5710509

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

关于macos - 包括带有-all_load标志的静态库,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16926608/

10-10 13:55