我正在使用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它有一个特殊的含义。
第三部分原来是年龄段, 说明有多少个主要版本向后兼容当前版本 。
推荐阅读: