为什么 linux ld 有时使用库的符号 link

Why linux ld somtime use the symbolic link of libs

我在我的 linux cli 工具中使用 jsoncpp 库。

CMakeLists.txt包含

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

结果是

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

当我检查我发现的二进制文件时:

 $> 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)

为什么 ld 使用 /usr/lib/libjsoncpp.so.24 而不是符号 link /usr/lib/libjsoncpp.so?

为什么 ld 有时会将 linbrary link 解析为真正的库文件?

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

在 /usr/lib/libstdc++.so.6 的情况下,ld 使用符号 link。当我检查 ldd 输出的路径时,libstdc++.so.6 指向一个符号 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

我喜欢理解这种行为。因为当我将二进制文件复制到不同的系统时,link 到 libjsoncpp.so 可用。但它指向一些不同的版本。

非常感谢

托马斯

这是一个版本兼容性功能。按照惯例,API 兼容性由主版本号决定。所以 6.0.286.1.1 兼容,但与 5.0.17.0.1.

不兼容

为了兼容升级,libstdc++.so.6.0.28 被符号link编辑为 libstdc++.so.6。然后它可以二进制升级到例如libstdc++.so.6.0.29 不接触依赖 libstdc++ 的 API 版本 6 的应用程序。

此外,它允许具有不同主版本号的库在同一系统中共存。安装 libstdc++.so.7.0.0 不会破坏 link 针对 libstdc++.so.6 的应用程序。

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

那是因为 libjsoncppsonamelibjsoncpp.so.24。显然它遵循让主版本号确定兼容性的相同约定。

如果您 link 像这样

,您可以使用共享库 libfoo 实现相同的行为:

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

有关详细信息,请参阅 GCC Howto - Version numbering, sonames and symlinks