g++动态库链接问题

G++ Dynamic Library Linking Issues

本文关键字:问题 链接 动态 g++      更新时间:2023-10-16

我试图将多个动态库链接到一个应用程序中,但在使用g++时遇到了问题。

考虑:

  • libA.so
  • libB。so依赖于libA.so
  • libC。so依赖于libB.so
  • 应用程序D直接依赖于lib .so

如果我尝试将应用程序D链接到libC。所以,对于A和b中的符号,我得到了未解析的符号,我觉得编译器应该能够找出它,当我使用英特尔编译器时,它确实可以。然而,g++无法找出这种链接。我希望我的库和可执行文件只需要链接到他们直接需要的东西,而不是试图预测他们正在使用的库需要什么。

我也有问题,当libA。so链接到一个静态库,当我试图编译可执行文件时,我从静态库中得到无法解析的符号。所以应该用。

我看到很多人问过这个问题和类似的问题,并得到了各种各样的答案(链接带有依赖关系的动态库),但答案都相当模糊,经常相互冲突,并且非常倾向于"继续运输和RTFM"。

给我的印象是链接顺序很重要。为什么呢?我怎么知道链接的顺序呢?

我相信正在发生的事情是沿着libA的路线。因此包含两个函数(AA和AB)。libB。AA和libC也需要。AB也需要。所以得到链接,g++得到libA。因此,看到只使用了AA,并省略了AB。然后libC。所以被链接在,g++看到libA。所以已经链接,不重新访问它,导致AB是未定义的。我已经看到文档表明静态库以这种方式工作,但是编译器会以同样的方式对待动态库吗?如果是这样,有没有办法解决这个问题?

(您没有显示实际的链接器错误,也没有提供有关问题的足够信息,因此下面的内容部分是猜测…)

如果我尝试将应用程序D链接到libC。因此,我得到了A和b中未解析的符号

当链接一个可执行文件时,GNU链接器检查所有的符号是否可用。您可以使用--allow-shlib-undefined关闭它(使用-Wl,--allow-shlib-undefined告诉GCC将其传递给链接器)

最好不要使用该选项,但在这种情况下,链接器需要知道在哪里可以找到libA.solibB.so,以便它可以检查libC.so所需的符号是否会被找到。你可以使用-rpath-link链接器选项

当使用ELF或SunOS时,一个共享库可能需要另一个。这种情况发生在"旧共享"时。链接包含一个共享库作为输入文件之一。

当链接器在做一个非共享的、不可重定位的链接时遇到这样的依赖时,它将自动尝试找到所需的共享库并将其包含在链接中,如果它没有被显式包含。

因此,您应该能够通过使用-Wl,-rpath-link,.来告诉链接器在当前目录(.)中查找libC.so所依赖的库来解决这个问题。

给我的印象是链接顺序很重要。为什么呢?我怎么知道链接的顺序呢?

是的,链接顺序很重要。如果一个文件foo.cc依赖于一个库,那么把这个库放在链接器行后面,所以它会在处理foo.cc之后被发现,如果这个库依赖于另一个库,把它放在后面,所以它会在需要它的较早的库之后被处理。如果你把一个库放在链接行的开头,那么链接器就没有任何未解析的符号需要查找,所以不需要链接到那个库。

您需要显式指定您直接使用的所有库。

在静态链接期间,加载的。so的依赖项不会被使用;当链接主程序时,所有符号必须在主程序本身、在命令行指定的静态库中或在命令行指定的共享库中找到。

这是你得到错误的地方。

程序执行时,加载动态库的依赖关系,以便解析来自其他共享库的引用。到程序运行时,它实际上可能(动态地)链接到共享库的不同版本。这个不同的版本可能有不同的依赖项,所以主程序绝对不能依赖于作为依赖项加载的附加库集。