Search code examples
c++linuxld

Why linux ld somtime use the symbolic link of libs


I use the jsoncpp lib in my linux cli tool.

The CMakeLists.txt contains

find_library(LIB_JSON jsoncpp)
target_link_libraries(${PROJECT_NAME} ${LIB_JSON})

The result is

/usr/bin/c++ -rdynamic CMakeFiles/cktwagent.dir/agent_main.cpp.o -o cktwagent -ljsoncpp

When i check the binary I found:

 $> ldd cktwagent 
    linux-vdso.so.1 (0x00007ffe4cfd1000)
    libjsoncpp.so.24 => /usr/lib/libjsoncpp.so.24 (0x00007f87505bd000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f87503e0000)
    libm.so.6 => /usr/lib/libm.so.6 (0x00007f875029a000)
    libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f8750280000)
    libc.so.6 => /usr/lib/libc.so.6 (0x00007f87500b7000)
    /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f87506ce000)

Why ld use /usr/lib/libjsoncpp.so.24 and not the symbolic link /usr/lib/libjsoncpp.so?

Why the ld sometime resolv the linbrary link to the real library file?

$> ls -l /usr/lib/libjsoncpp.so
lrwxrwxrwx 1 root root 16 26. Sep 17:02 /usr/lib/libjsoncpp.so -> libjsoncpp.so.24

In case of /usr/lib/libstdc++.so.6 the ld use the symbolic link. When i check the path from ldd output, libstdc++.so.6 point to a symbolic link.

$> ls -l /usr/lib/libstdc++.so.6
lrwxrwxrwx 1 root root 19  9. Nov 12:43 /usr/lib/libstdc++.so.6 -> libstdc++.so.6.0.28

I like to understand this behavior. Because when i copy the binary to a different system, the link to libjsoncpp.so available. But it points to some different version.

Many thanks

Thomas


Solution

  • That's a version compatibility feature. By convention, API compatibility is determined by the major version number. So 6.0.28 would be is compatible with 6.1.1, but not with 5.0.1 or 7.0.1.

    To allow for compatible upgrades, libstdc++.so.6.0.28 is symlinked as libstdc++.so.6. Then it can be binary-upgraded to e.g. libstdc++.so.6.0.29 without touching applications that rely on API version 6 of libstdc++.

    In addition, it allows libraries with different major version numbers to coexist on the same system. Installing libstdc++.so.7.0.0 will not break apps that link against libstdc++.so.6.

    Why ld use /usr/lib/libjsoncpp.so.24 and not the symbolic link /usr/lib/libjsoncpp.so?

    That's because libjsoncpp has a soname of libjsoncpp.so.24. Apparently it is following the same convention of having the major version number determine compatibility.

    You can achieve the same behavior with your shared lib libfoo if you link it like this:

    gcc -shared -Wl,-soname,libfoo.so.<major> -o libfoo.so.<major>.<minor>
    

    For more details refer to GCC Howto - Version numbering, sonames and symlinks.