给出一个可执行文件:
>objdump -x someprog | grep c++
NEEDED libstdc++.so.6
我想将要求更改为完整版(包括次要版本和补丁级别):
>objdump -x someprog | grep c++
NEEDED libstdc++.so.6.0.22
我知道有两种方法可以做到这一点:
>patchelf --add-needed libstdc++.so.6.0.22 someprog >objdump -x someprog | grep c++ NEEDED libstdc++.so.6 NEEDED libstdc++.so.6.0.22
(我还没找到--replace-needed的工作命令行)
这些对我来说都像黑客。 有没有办法在编译或链接时使用适当的-Wl标志来实现gcc?
理想情况下,我想避免使用-nostdlib,因为这需要我特定的不仅仅是libstd ++而是libc以及我想要标准版本的所有其他内容。
对于常规库,仅链接到特定版本对于libstdc ++来说已经足够了(或者我怀疑-stdlib会覆盖我提供的后续完全限定名称)。
背景:我的可执行文件需要的libstdc++
版本比系统上安装的更高版本。不幸的是,安装的版本可能是相同的主要版本,如果是这样,ld
将很乐意使用系统版本,因为它匹配 soname libstdc++.so.6
我不想静态链接,因为我实际上想要安装许多共享相同C ++运行时的小程序,这会大大增加安装量。
有关我的(图书馆)搜索路径的一些信息可在此处获取:
ld --verbose | grep SEARCH_DIR SEARCH_DIR("在/ usr / x86_64的-红帽-LINUX / lib64下&#34); SEARCH_DIR("在/ usr / lib64下&#34); SEARCH_DIR("在/ usr /本地/ lib64下&#34); SEARCH_DIR(" / lib64下&#34); SEARCH_DIR("在/ usr / x86_64的-红帽-LINUX / LIB&#34); SEARCH_DIR("在/ usr / local / lib目录&#34); SEARCH_DIR(" / lib中&#34); SEARCH_DIR(" / usr / lib中&#34);
在我的情况下很明显,在可执行文件的RPATH之前搜索/ usr / lib64:
>objdump -x /opt/foo/bin/bar | grep PATH
RPATH $ORIGIN/../lib64/private:$ORIGIN/../lib64:$ORIGIN/
man ld.so
建议搜索顺序为:
如果库依赖项不包含斜杠,则搜索它 按以下顺序:
o (ELF only) Using the directories specified in the DT_RPATH dynamic section attribute of the binary if present and DT_RUNPATH attribute does not exist. Use of DT_RPATH is deprecated.
o Using the environment variable LD_LIBRARY_PATH. Except if the executable is a set-user-ID/set-group-ID binary, in which case it is ignored.
o (ELF only) Using the directories specified in the DT_RUNPATH dynamic section attribute of the binary if present.
o From the cache file /etc/ld.so.cache, which contains a compiled list of candidate libraries previously found in the augmented library path. If, however, the binary was linked with the -z node‐
flib linker option, libraries in the default library paths are skipped. Libraries installed in hardware capability directories (see below) are preferred to other libraries.
o In the default path /lib, and then /usr/lib. If the binary was linked with the -z nodeflib linker option, this step is skipped.
同样https://software.intel.com/sites/default/files/m/a/1/e/dsohowto.pdf
两者似乎都被实际使用所压倒,但实际情况并非如此。 需要的是寻找符号链接:
>LD_LIBRARY_PATH= LD_DEBUG=libs ldd /opt/foo/bin/bar
21720: find library=libstdc++.so.6 [0]; searching
21720: search path=/opt/foo/bin/../lib64/private:/opt/foo/bin/../lib64:/opt/foo/bin (RPATH from file /opt/foo/bin/bar)
21720: trying file=/opt/foo/bin/../lib64/private/libstdc++.so.6
这是与我install shared imported library with necessary links的另一个问题的互动,其中的建议是不需要链接。 如果您没有指定完整的语义版本,那么它们显然是 。
答案 0 :(得分:1)
这不起作用,因为libstdc++.so.6.0.22
将导出与系统libstdc ++相同的符号,并且最终会在两个库之间混合使用(假设您确实更改了较新的libstdc ++版本的soname)。
您应该静态链接整个libstdc ++(这可能需要库的静态PIC变体)而不导出任何符号(可能带有链接器版本脚本),或静态链接新符号。
第二种方法似乎是目前最好的选择:它允许您使用大多数新语言功能,但您仍然与系统的其余部分保持很大程度的互操作性(特别是如果您使用{{1配置GCC)并且您不必安装任何其他共享对象进行部署。这就是Developer Toolset software collection提供更新版GCC的方式(我也相信SUSE Linux Toolchain Module)。如果C ++对象通过共享对象边界(包括异常处理)传递,则完全静态链接会导致问题,并且这种选择性静态链接可以避免许多这些问题。
答案 1 :(得分:1)
我想我已回答了我的问题,但不是我实际问过的问题。
在RPATH
之前搜索 LD_LIBRARY_PATH
。
/usr/lib64/libstdc++.so.6
被提取而不是libstdc++.so.6.0.22
的原因是没有从/where/i/installed/libstdc++.so.6
到/where/i/installed/libstdc++.so.6.0.22
因此规则遵循您的平台的标准(他们是明智的)。在这种情况下: 每当您安装共享库时,也要安装预期的链接。
我认为我提出的实际问题在技术上仍然很有趣,所以如果有人有一个(甚至几年后),我仍会接受更好的答案。