Mar*_*cus 69 dll dependencies gcc g++
请考虑以下情形:
我想编译一个与libB链接的二进制文件.我应该仅将二进制文件与libB或libA链接?
有没有办法只链接直接依赖关系,让运算符的依赖关系解析未解析的符号?
我担心库libB实现将来可能会发生变化,引入其他依赖项(例如libC,libD,libE).我会遇到问题吗?
换一种说法:
当然,b.cpp包含ah而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
Run Code Online (Sandbox Code Playgroud)
我应该使用哪种波纹管选项?
g++ main.cpp -o main -I. -L. -lB
Run Code Online (Sandbox Code Playgroud)
要么
g++ main.cpp -o main -I. -L. -lB -lA
Run Code Online (Sandbox Code Playgroud)
我无法使用第一个选项.链接器抱怨库libA中未解析的符号.但这听起来有点奇怪.
非常感谢.
- 更新评论:
当我链接二进制文件时,链接器将尝试解析main和libB中的所有符号.但是,libB具有来自libA的未定义符号.这就是链接器抱怨的原因.
这就是我需要与libA联系的原因.但是我发现了一种忽略共享库中未解析符号的方法.看起来我应该使用以下命令行来做到这一点:
g++ main.cpp -o main -I. -L. -lB -Wl,-unresolved-symbols=ignore-in-shared-libs
Run Code Online (Sandbox Code Playgroud)
看起来仍然可以使用该-rpath
选项.但是我需要更好地理解它.
有没有人知道使用该-Wl,-unresolved-symbols=ignore-in-shared-libs
选项时可能存在的任何陷阱?
- 更新评论2:
-rpath
不应该用于此目的.强制在给定目录中找到库是很有用的.这种-unresolved-symbol
方法看起来好多了.
再次感谢.
kit*_*ril 39
看起来你已经完成了大部分工作.你的调查做得好.让我们看看我是否可以帮助清理它背后的"原因".
这是链接器正在做的事情.当你链接你的可执行文件(上面的'main')时,它有一些未解决的符号(函数和其他东西).它将查看后面的库列表,尝试解析未解析的符号.在此过程中,它发现某些符号是由libB.so提供的,因此它注意到它们现在已由此库解析.
但是,它还发现其中一些符号使用了可执行文件中尚未解析的其他符号,因此现在也需要解析这些符号.如果没有链接libA.so,您的应用程序将是不完整的.一旦链接到libA.so,就会解析所有符号并完成链接.
如你所见,使用-unresolved-symbols-in-shared-libs
,并没有解决问题.它只是推迟它,以便在运行时解析这些符号.这-rpath
就是:指定在运行时搜索的库.如果无法解析这些符号,那么您的应用将无法启动.
找出库依赖关系并不容易,因为符号可以由多个库提供,并且可以通过链接任何一个库来满足.
这里有另一个这个过程的描述:为什么库链接的顺序有时会导致GCC错误?
小智 16
对于动态链接只可以使用直接依赖-Wl,--as-needed
与添加库后 -Wl,--as-needed
:
gcc main.c -o main -I. -L. -Wl,--as-needed -lB -lA
Run Code Online (Sandbox Code Playgroud)
要检查直接依赖关系,您应该使用readelf而不是ldd,因为ldd还显示了间接依赖关系.
$ readelf -d main | grep library
0x0000000000000001 (NEEDED) Shared library: [libB.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
如果使用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}")
Run Code Online (Sandbox Code Playgroud)