与依赖动态链接库与依赖动态链接库(Linking with dynamic library with

2019-05-12 22:42发布

考虑以下情形:

  • 共享库libA.so,无依赖性。
  • 共享库libB.so,与libA.so作为其依赖。

我想编译与libB链接的二进制文件。 我应该libB链接二进制单独或与力霸要么?

有没有什么办法只能与直接依赖关系链接,让悬而未决的符号从依赖运行系统的分辨率?

我担心的是,该库libB实现可能在将来改变,引入其他依赖(libC中,LIBD,libE例如)。 我是不是要和的问题?

换一种说法:

  • 力霸文件:a.cpp啊
  • libB文件:b.cpp BH
  • 主程序文件:main.cpp中

当然,b.cpp包括啊和main.cpp中包括BH

编译命令:

g++ -fPIC a.cpp -c
g++ -shared -o libA.so a.o

g++ -fPIC b.cpp -c -I.
g++ -shared -o libB.so b.o -L. -lA

我应该使用哪波纹管的选择?

g++ main.cpp -o main -I. -L. -lB

要么

g++ main.cpp -o main -I. -L. -lB -lA

我不能使用第一个选项。 链接器抱怨从库力霸未解决的符号。 但它听起来有点怪我。

非常感谢。

-更新评论:

当我链接的二进制文件,链接器将尝试解决从主和libB所有符号。 然而,libB是未定义从利巴符号。 这就是为什么链接器抱怨说。

这就是为什么我需要太多与力霸链接。 但是我发现了一个办法忽略从共享库解析的符号。 看起来我应该使用以下命令行来做到这一点:

g++ main.cpp -o main -I. -L. -lB -Wl,-unresolved-symbols=ignore-in-shared-libs

看起来它仍然可以使用-rpath选项。 不过,我需要一点点更好地理解它。

是否使用时,任何人都知道任何可能存在的缺陷-Wl,-unresolved-symbols=ignore-in-shared-libs的选择吗?

-更新注释2:

-rpath不应该被用于此目的。 它是有用的,迫使库在给定的目录中找到。 该-unresolved-symbol的方法看起来好多了。

再次感谢。

Answer 1:

它看起来像你最的方式存在了。 与你的调查做得很好。 让我们来看看,如果我能帮助清理“为什么”背后。

下面是该接头用做。 当您将可执行文件(“主”以上)它有一个尚未解决的一些符号(函数和其他东西)。 它会看不起遵循库的列表,试图解决悬而未决的符号。 一路上,它发现一些符号是由libB.so提供,因此它指出,他们现在通过此库解决。

然而,它也发现一些这些符号的使用尚未解决您的可执行其他符号,所以现在需要解决那些为好。 如果没有对libA.so链接,你的应用程序将是不完整的。 一旦链接对libA.so,所有符号都解决了并且完成了链接。

正如你所看到的,使用-unresolved-symbols-in-shared-libs ,不解决问题。 它只是推迟它,以便这些符号在运行时解决。 这就是-rpath是:到指定的库文件在运行时进行搜索。 如果这些符号不能再解决,您的应用程序将无法启动。

这不是找出库的依赖,因为符号可以由多个库来提供,并通过对他们中的任何一个连接来满足一件容易的事情。

这里有这个过程的另一种描述: 在GCC为什么的顺序库有时与造成的错误?



Answer 2:

对于动态链接只能用直接的依赖,你可以使用-Wl,--as-needed使用加入库-Wl,--as-needed

gcc main.c -o main -I. -L. -Wl,--as-needed -lB -lA

为了检查有直接的依赖,你应该使用readelf LDD因为LDD也显示了间接的依赖关系。

$ readelf -d main | grep library
0x0000000000000001 (NEEDED)             Shared library: [libB.so]
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

LDD也显示了间接的依赖关系:

$ LD_LIBRARY_PATH=. ldd ./main
linux-vdso.so.1 (0x00007fff13717000)
libB.so => ./libB.so (0x00007fb6738ed000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb6734ea000)
libA.so => ./libA.so (0x00007fb6732e8000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb673af0000)

如果你使用的cmake,您可以添加以下行只包括直接依赖关系:

set(CMAKE_EXE_LINKER_FLAGS    "-Wl,--as-needed ${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed ${CMAKE_SHARED_LINKER_FLAGS}")


Answer 3:

另一种选择是使用libtool

如果更改g++调用libtool --mode=compile g++编译源代码,然后libtool --mode=link g++来创建应用程序关闭的libB ,然后libA将被自动链接。



Answer 4:

这是一个有趣的帖子 - 我敲我的头,这为好,但我觉得你错过这里的一个点..

这个想法是如下,对不对?

main.cpp =(depends)=> libB.so =(depends)=> libA.so

让我们进一步考虑..

  • 在a.cpp(只有那里)你定义一个类/变量,我们称之为“司马”
  • 在b.cpp(只有那里)你定义一个类/变量,我们称之为“SYMB”。
  • SYMB使用西马
  • main.cpp中使用SYMB

现在,如果上述libB.so和libA.so已经编译。 在这之后,你的第一选择应该工作,即:

g++ main.cpp -o main -I. -L. -lB

我猜你的问题的事实,起源

在main.cpp中还指司马

我对么?

如果您在代码中使用符号,那么该符号必须在.so文件发现

回参考间共享库(即创建的API)的整体思想是,在更深的层被隐藏符号(认为剥洋葱的),而不是使用。 ..即不是指司马在main.cpp中,但只SYMB来代替(让SYMB仅指司马)。



文章来源: Linking with dynamic library with dependencies