共享对象文件中的版本号

时间:2011-04-22 21:12:20

标签: c++ linux gcc compiler-construction shared-libraries

我正在使用GCC从一组C ++源文件构建共享对象文件。有关构建.so文件的所有示例教程都显示使用.so后缀之后的版本号创建的文件。例如:

gcc -shared -Wl,-soname,libmean.so.1 -o libmean.so.1.0.1  calc_mean.o

这将生成.so文件libmean.so.1.0.1

此外,如果我浏览本地计算机上的/usr/lib目录,我会看到许多.so文件最后都有版本号。

但是,当我编译共享对象文件并将其放在/usr/lib中时,如果我在最后添加版本号,链接器将无法找到它。如果我删除版本号,它可以正常工作。我真的不关心是否设置版本号,我只是不明白为什么这似乎是一个常见的约定,但这会导致共享库无法使用链接器。那么,这里发生了什么?为什么有一个约定将版本号放在.so文件名的末尾?

1 个答案:

答案 0 :(得分:17)

附加版本号,以便您可以在系统中共存多个不兼容的库版本。每当您以不兼容的方式更改API时,您应该增加主版本号(soname中的数字)(当然,假设先前的版本已在系统中安装和使用)。

文件名中的第2和第3个数字允许对系统中的库进行多次次要修订,可通过简单的符号链接更新在系统范围内进行切换。

在链接时,您可以将.so文件名作为链接器参数,而不是-l选项。 ldd非常聪明,可以从中提取soname,这种链接的二进制文件使用它来查找库。

例如,让我们编译库并使用它测试二进制文件:

czajnik@czajnik:~/z$ gcc -shared -Wl,-soname,libtest.so.2 -o libtest.so.2.3.4  a.c 
czajnik@czajnik:~/z$ gcc -o test b.c -L. ./libtest.so.2.3.4

您可以使用ldd验证二进制文件现在查找libtest.so.2

czajnik@czajnik:~/z$ LD_LIBRARY_PATH=. ldd ./test
    linux-gate.so.1 =>  (0x002c1000)
    libtest.so.2 => not found
    libc.so.6 => /lib/libc.so.6 (0x00446000)
    /lib/ld-linux.so.2 (0x00a28000)

显然无法找到它,但这就是符号链接的用途:

czajnik@czajnik:~/z$ ln -s libtest.so.2.3.4 libtest.so.2
czajnik@czajnik:~/z$ LD_LIBRARY_PATH=. ldd ./test
    linux-gate.so.1 =>  (0x00d75000)
    libtest.so.2 => ./libtest.so.2 (0x00e31000)
    libc.so.6 => /lib/libc.so.6 (0x00a5e000)
    /lib/ld-linux.so.2 (0x00378000)

更新:以上所有情况都属实,但我不知道版本号第3个组成部分的含义。直到最近,我相信它只是一个补丁号码(或类似的东西)。错误!对于libtool,它具有特殊含义。

第三个组件结果是 age 字段,其中与当前版本向后兼容的主要版本

推荐阅读: