共享对象文件中的版本号

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

 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 ,如果我在末尾添加版本号,连接器将无法find它。 如果我删除版本号,它工作正常。 我真的不在乎放置一个版本号,我只是不明白为什么这似乎是一个共同的惯例,但这会导致共享库不工作的链接器。 那么,这是怎么回事? 为什么有一个约定将版本号放在.so文件名的末尾?

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

文件名中的第二个和第三个数字允许在系统中对库进行多次小修改,可以通过简单的符号链接更新进行系统范围的切换。

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

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

 czajnik@czajnik:~/z$ gcc -shared -Wl,-soname,libtest.so.2 -o libtest.so.2.3.4 ac czajnik@czajnik:~/z$ gcc -o test bc -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) 

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

第三部分原来是年龄段, 说明有多少个主要版本向后兼容当前版本

推荐阅读:

  • 白痴指南ABI版本
  • Libtool的版本控制系统