可执行文件中的共享库名称与文件名不同
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.2
和 libfoo.so.2
的 SONAME
,以及符号 link libfoo.so
现在指向 libfoo.so.2
.
瞧:两个要求都已实现:现有二进制文件继续使用 libfoo.so.1
,新 linked 二进制文件使用 libfoo.so.2
,不需要 Makefile
更改。
我的编译命令的清理版本看起来像 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.2
和 libfoo.so.2
的 SONAME
,以及符号 link libfoo.so
现在指向 libfoo.so.2
.
瞧:两个要求都已实现:现有二进制文件继续使用 libfoo.so.1
,新 linked 二进制文件使用 libfoo.so.2
,不需要 Makefile
更改。