可执行文件中的共享库名称与文件名不同

Shared library name in executable is different than the filename

我的编译命令的清理版本看起来像 gcc -o semantic_seg -Wl,-rpath,... -l:libnvrtc-5e8a26c9.so.10.1 ...,并且我在 -rpath 标志指定的目录中有一个名为 libnvrtc-5e8a26c9.so.10.1 的动态库文件。命令成功。

当我进入 运行 我的程序时,它显示 semantic_seg: error while loading shared libraries: libnvrtc.so.10.1: cannot open shared object file: No such file or directory 而当我进入 ldd 时它显示 libnvrtc.so.10.1 => not found.

所以问题看起来是可执行文件中共享库的名称与文件名不同。那是真的吗?名称的 5e8a26c9 部分是否以某种方式被剥离?

更新:创建符号 link libnvrtc-5e8a26c9.so.10.1 -> libnvrtc.so.10.1 允许可执行文件 运行。但我仍然不确定导致此名称修改发生的机制。好像有点神奇。

Could that be true?

这通常是正确的。

在 ELF 系统上,linker 使用库的 SONAME(如果它有的话)并且 而不是 其文件名来记录运行时依赖性.

运行 readelf -d libnvrtc-5e8a26c9.so.10.1 | grep SONAME 可能会显示实际上该库确实有 SONAME,而 SONAME 的值是 libnvrtc.so.10.1.

这对external library versioning来说曾经很方便。

更新:

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?

就像我说的,它对外部库版本控制和 ABI 演变很有用。

假设您发布 libfoo.so 的 1.0 版。您将 libfoo.so 作为 libfoo.so.1 的符号 link 提供,并使用 libfoo.so.1 作为 SONAME.

任何 link 带有 gcc main.c -lfoo 的程序(注意:不需要有趣的 -l:libfoo.so.1 语法)将记录 libfoo.so.1 作为其外部依赖项,并将使用该名称在运行时。

时间流逝,您已准备好发布与 ABI 不兼容的版本 2。

您不想让所有最终用户更改他们的 link 行,并且您不想破坏任何现有的二进制文件。

对于 SONAME,这是微不足道的:新包将包括 libfoo.so.2libfoo.so.2SONAME,以及符号 link libfoo.so 现在指向 libfoo.so.2.

瞧:两个要求都已实现:现有二进制文件继续使用 libfoo.so.1,新 linked 二进制文件使用 libfoo.so.2,不需要 Makefile 更改。