Bil*_*rin 7 linker gcc ld shared-objects
假设我有:
/usr/lib/libsomething.so.1 在机器A上;/usr/lib/libsomething.so.2 在机器B.两台机器都有/usr/lib/libsomething.so符号链接到各自的库.
如果我使用链接gcc用-lsomething(甚至/usr/lib/libsomething.so),它会跟随符号链接,和ldd机器上的产生是这样的:
libsomething.so.1 => /usr/lib/libsomething.so.1
Run Code Online (Sandbox Code Playgroud)
这意味着它将无法在机器B上找到库.
现在我知道这些是主要的版本号更改,我知道它们可能不兼容,但我愿意冒这个风险.我想告诉链接器要查找libsomething.so,不要按照符号链接ldd显示
libsomething.so => /usr/lib/libsomething.so.1
Run Code Online (Sandbox Code Playgroud)
在A但是
libsomething.so => /usr/lib/libsomething.so.2
Run Code Online (Sandbox Code Playgroud)
在B.然后加载器将遵循符号链接到任何版本.
此外,我不希望延迟加载dlopen或任何东西.我希望它在编译时链接到共享对象.
这甚至可能吗?
当然,制作使用任何可用版本的共享库的可执行文件是可能的.
问题是您将可执行文件链接到特定于版本的soname(libsomething.so.1和libsomething.so.2).你应该用无版本的soname libsomething.so代替它.
为了实现这一点,在构建机器上,您应该编译和安装soname(ELF SONAME)等于libsomething.so(没有版本)的库,以便链接器可以在构建可执行文件时选择此soname.
根据共享库HOWTO,您可以在构建库时传递所需的无版本声纳:
gcc -shared -Wl,-soname,libsomething.so -o libsomething.so.X objectsomething.o
Run Code Online (Sandbox Code Playgroud)
然后,只要您安装库并运行ldconfig,您就拥有:
/lib/libsomething.so指向/lib/libsomething.so.1机器A;/lib/libsomething.so指向/lib/libsomething.so.2机器B.加载器(运行ldd)将选择无版本的符号链接,无论它指向何处:
libsomething.so => /lib/libsomething.so (0xNNNNNNNN) 在机器A上;libsomething.so => /lib/libsomething.so (0xNNNNNNNN) 在机器B.Linux dynamic loader(ld.so)根据在可执行文件(ELF NEEDED)中编写的soname值来解析库.SONAME在构建可执行文件时,将从库文件(ELF )复制该值.只要目标系统上存在符合可执行文件中记录的soname的符号链接,就会加载此符号链接指向的库.
让我们运行您的设置并显示命令以验证假设.
为了清晰起见,我使用Fedora 18 X86_64进行测试并调整输出i686.
编译两者libsomething.so.1和libsomething.so.2.确保SONAME设置为无版本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]
Run Code Online (Sandbox Code Playgroud)将库安装到/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)
Run Code Online (Sandbox Code Playgroud)编译可执行文件并确保它引用了没有版本的同一个soname NEEDED.
readelf -a executable | grep NEEDED
0xNNNNNNNN (NEEDED) Shared library: [libsomething.so]
Run Code Online (Sandbox Code Playgroud)你的可执行文件libsomething.so现在依赖于unversioned .将可执行文件复制到两台计算机ldd并对两个副本运行
ldd executable
libsomething.so => /lib/libsomething.so (0xNNNNNNNN)
Run Code Online (Sandbox Code Playgroud)
两台机器上的最后一个输出是相同的,因为可执行文件是使用没有版本的soname构建的.这使得加载器在目标机器上采用无版本的符号链接.根据机器的不同,符号链接可以指向库的不同实现libsomething.so.1或libsomething.so.2.
| 归档时间: |
|
| 查看次数: |
4196 次 |
| 最近记录: |