Given a executable such that:
>objdump -x someprog | grep c++
NEEDED libstdc++.so.6
I want to change the requirement to the full version (including the minor version and patch level):
>objdump -x someprog | grep c++
NEEDED libstdc++.so.6.0.22
I know of two ways to do this:
- create a dummy library as per this question (Forcing or preventing use of a particular minor version of libstdc++)
- use patchelf
>patchelf --add-needed libstdc++.so.6.0.22 someprog >objdump -x someprog | grep c++ NEEDED libstdc++.so.6 NEEDED libstdc++.so.6.0.22
(I haven't figured out a working command line for --replace-needed)
Both of these feel like hacks to me. Is there a way to achieve the same at compile or link time using appropriate -Wl flags to gcc?
Ideally I want to avoid using -nostdlib as that requires I specify not just libstd++ but libc and everything else for which I do want standard versions.
For a regular library just linking to the specific version is enough for libstdc++ it is not (or rather I suspect -stdlib overrides subsequent fully qualified names I provide).
Background: I have executables which require a later version of libstdc++
than is installed on the system. Unfortunately the installed version could be the same major version and if so ld
will happily use the system version as it matches the soname libstdc++.so.6
I prefer not to statically link as I actually want to install many small programs sharing the same C++ runtime and this would bloat the installation considerably.
Some information about my (the) library search path is available here:
ld --verbose | grep SEARCH_DIR SEARCH_DIR("/usr/x86_64-redhat-linux/lib64"); SEARCH_DIR("/usr/lib64"); SEARCH_DIR("/usr/local/lib64"); SEARCH_DIR("/lib64"); SEARCH_DIR("/usr/x86_64-redhat-linux/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");
It is clear in my case that /usr/lib64 is being searched before the RPATH of the executable which is:
>objdump -x /opt/foo/bin/bar | grep PATH
RPATH $ORIGIN/../lib64/private:$ORIGIN/../lib64:$ORIGIN/
man ld.so
suggests the search order should be:
If a library dependency does not contain a slash, then it is searched for in the following order:
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.
Similarly https://software.intel.com/sites/default/files/m/a/1/e/dsohowto.pdf
Both seem to be trumped by actual usage but in fact this is not the case. the needed is looking for symbolic links:
>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
This is an interaction with another question I had install shared imported library with necessary links where the suggestion was that the links are not required. They clearly are required if you do not specify the full semantic version.