当然,可以使用任何可用版本的共享库来制作可执行文件。
问题是您将可执行文件链接到特定于版本的soname (libsomething.so.1
和libsomething.so.2
)。您应该使用未版本化的 sonamelibsomething.so
来代替。
为了实现这一点,在构建机器上,您应该编译和安装 soname (ELF SONAME
) 等于libsomething.so
(无版本)的库,以便链接器可以在构建可执行文件时选择此 soname。
根据Shared Libraries HOWTO ,您可以在构建库时传递所需的未版本化soname :
gcc -shared -Wl,-soname,libsomething.so -o libsomething.so.X objectsomething.o
然后,一旦您安装了库并运行ldconfig
,您将拥有:
/lib/libsomething.so
指向/lib/libsomething.so.1
机器 A 的符号链接;
/lib/libsomething.so
指向/lib/libsomething.so.2
机器 B 上的符号链接。
加载器 (run ldd
) 将选择未版本化的符号链接,无论它指向何处:
libsomething.so => /lib/libsomething.so (0xNNNNNNNN)
在机器 A 上;
libsomething.so => /lib/libsomething.so (0xNNNNNNNN)
在机器 B 上。
Linux 动态加载程序 ( ) 根据写入可执行文件 (ELF )ld.so
中的 soname 值解析库。NEEDED
该值是SONAME
在构建可执行文件时从库文件 (ELF) 中复制的。只要目标系统上存在与可执行文件中记录的 soname 匹配的符号链接,就会加载该符号链接指向的库。
让我们运行您的设置并显示命令以验证假设。
我使用 Fedora 18X86_64
进行测试,并将输出调整i686
为清晰。
编译libsomething.so.1
和libsomething.so.2
。确保SONAME
设置为 unversioned libsomething.so
:
readelf -a libsomething.so.1 | grep SONAME
0xNNNNNNNN (SONAME) Library soname: [libsomething.so]
readelf -a libsomething.so.2 | grep SONAME
0xNNNNNNNN (SONAME) Library soname: [libsomething.so]
将库安装到各自机器的/lib/
目录下。在两台机器上运行ldconfig -v
并验证输出。
ldconfig -v 2>&1 | grep something
libsomething.so -> libsomething.so.1 (changed)
ldconfig -v 2>&1 | grep something
libsomething.so -> libsomething.so.2 (changed)
编译可执行文件并确保它引用相同的 soname,但没有NEEDED
.
readelf -a executable | grep NEEDED
0xNNNNNNNN (NEEDED) Shared library: [libsomething.so]
您的可执行文件现在取决于未版本化libsomething.so
。将可执行文件复制到两台机器并ldd
针对这两个副本运行。
ldd executable
libsomething.so => /lib/libsomething.so (0xNNNNNNNN)
两台机器上的最后一个输出是相同的,因为可执行文件是用 soname 构建的,没有版本。这使得加载程序在目标机器上采用未版本化的符号链接。根据机器的不同,符号链接可以指向库的不同实现libsomething.so.1
或libsomething.so.2
.