如何对使用 GCC for Linux 创建的共享对象文件进行版本控制
请用几个例子解释一下
LD_LIBRARY_PATH 中可以存在多个版本的共享库。
例如:
/usr/lib/libform.so -> libform.so.5
/usr/lib/libform.so.5 -> libform.so.5.9
/usr/lib/libform.so.5.9
/usr/lib/libform.so.6 -> libform.so.6.0
/usr/lib/libform.so.6.0
上例中存在符号链接,因为在链接时,如果您只提及-lform
,它会自动根据符号链接为您选择正确的库。
当二进制文件链接到一组共享库时,它将请求特定版本的库。二进制文件依赖的库列表可以使用ldd
$ ldd /usr/bin/python
linux-vdso.so.1 (0x00007ffffa5fe000)
libpython2.7.so.1.0 => /usr/lib64/libpython2.7.so.1.0 (0x00007ff6e9b6c000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007ff6e9950000)
libc.so.6 => /lib64/libc.so.6 (0x00007ff6e95ab000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007ff6e93a7000)
libutil.so.1 => /lib64/libutil.so.1 (0x00007ff6e91a4000)
libm.so.6 => /lib64/libm.so.6 (0x00007ff6e8ead000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff6e9f0a000)
在上面的例子中,python
是依赖于libm.so.6
而不是仅仅libm.so
。
库文件名中的版本控制通常采用以下形式:
libSOMETHING.so.VERSION
libSOMETHING.so.MAJOR_VERSION.MINOR_VERSION
有些库有时也有次要编号或补丁编号。
每个库都嵌入了一个soname
在库中调用的字符串,编译时和运行时链接器都会检查版本兼容性。
例如,由于主版本号的变化,编译的二进制文件libform.so.5
可以使用libform.so.5.9
,libform.so.5.9.1
但不能使用。libform.so.6
要将soname
信息构建到库中,您需要执行以下操作:
gcc -fPIC -shared -Wl,-soname,libfoo.so.1 -o libfoo.so.1.0.0 foo.c bar.c baz.c
从手册页ld
:
-soname=name
When creating an ELF shared object, set the internal DT_SONAME
field to the specified name. When an executable is linked with
a shared object which has a DT_SONAME field, then when the
executable is run the dynamic linker will attempt to load the
shared object specified by the DT_SONAME field rather than the
using the file name given to the linker.