Search code examples
linuxgccshared-librariesld

Shared library name in executable is different than the filename


A cleaned up version of my compile command looks like gcc -o semantic_seg -Wl,-rpath,... -l:libnvrtc-5e8a26c9.so.10.1 ... and I have a dynamic library file named exactly libnvrtc-5e8a26c9.so.10.1 in the directory specified by the -rpath flag. The command succeeds.

When I go to run my program, it says semantic_seg: error while loading shared libraries: libnvrtc.so.10.1: cannot open shared object file: No such file or directory and when I do ldd it shows libnvrtc.so.10.1 => not found.

So the problem looks like the name of the shared library in the executable is not the same as the filename. Could that be true? Did the 5e8a26c9 part of the name somehow get stripped off?

Update: Creating a symbolic link libnvrtc-5e8a26c9.so.10.1 -> libnvrtc.so.10.1 allows the executable to run. But I'm still not sure the mechanism that causes this name modification to happen. It seems a bit magic.


Solution

  • Could that be true?

    This is often true.

    On ELF systems, the linker uses SONAME of the library (if it has one) and not its filename to record a runtime dependency.

    Running readelf -d libnvrtc-5e8a26c9.so.10.1 | grep SONAME will likely show that in fact that library does have SONAME, and the value of SONAME is libnvrtc.so.10.1.

    This used to be very convenient for external library versioning.

    Update:

    it allows you to link against a library which will be different than the one which will used at run time, but why would I ever want that?

    Like I said, it's useful for external library versioning and ABI evolution.

    Suppose you ship version 1.0 of libfoo.so. You provide libfoo.so as a symlink to libfoo.so.1, and you use libfoo.so.1 as SONAME.

    Any program that links with gcc main.c -lfoo (note: no funny -l:libfoo.so.1 syntax required) will record libfoo.so.1 as its external dependency, and will use that name at runtime.

    Time passes, and you are ready to ship version 2, which is not ABI-compatible.

    You don't want to cause all your end-users to change their link line, and you don't want to break any existing binaries.

    With the SONAME, this is trivial: new package will include libfoo.so.2 with SONAME of libfoo.so.2, and a symlink libfoo.so now pointing to libfoo.so.2.

    Voila: both requirements are achieved: existing binaries continue to use libfoo.so.1, newly-linked binaries use libfoo.so.2, no Makefile changes required.