动态链接的ELF 二进制文件(无论是另一个库还是可执行文件)使用shared-object name or soname 来标识可执行文件在执行时应链接到的库。
当一个库被创建为一个 ELF 共享库时,编译时链接编辑器在可执行文件中插入一个 DT_SONAME 字段,该库的 SONAME 到库本身。 DT_SONAME 在ELF standard 中定义为:
此元素保存以空字符结尾的字符串表偏移量
字符串,给出共享对象的名称。偏移量是一个索引
到DT_STRTAB 条目中记录的表中。请参阅“共享对象”
更多关于这些名称的信息。
所以现在当一个可执行文件被创建时,SONAME 被嵌入其中。当可执行文件运行时,链接器使用它在动态库的预定义位置的文件中查找库。 Windows 中的预定义位置是 DLL 所在的位置。在 Linux 和 Mac OS X 以及其他 System V 兼容系统中,它们将是 /lib 和 /usr/lib 以及可能的其他位置,这取决于使用的链接器,并且可以在链接器自己的配置中定义。
在所有情况下,链接器都会查看在 soname 条目中命名的库是否存在于任何这些位置,如果存在,它将使用它。
请注意,该标准说 soname 是一个字符串,并且版本控制约定在事后成为事实上的标准,并且是这样的:
将 soname 设为 libmyname.so.A 并将库文件名设为 libmyname.so.A.B 或 libmyname.so.A.B.C(在 MacOSX 下为 libmyname.A.B.dylib)。创建从libmyname.so.A.B[.C]? 到libmyname.so.A 的软链接。
A 保持不变,而库的 ABI 保持不变。
B(或B.C)成为次要版本。
在 Linux 下,库版本与包版本号相同是很常见的。这有利有弊。
libtool 形式化
GNU libtool 被大量用于构建动态库,并且具有更正式的版本控制系统和强大的逻辑。 sonames 的 libtool 版本控制系统运行良好,并被复杂的库采用以保持正常。
在libtool下,版本如下:
libmylib-当前。发布。年龄 em>
在 libtool 下的想法是,随着库的发展,它们将添加和删除功能。
假设您正在开发一个库。首先使用0.0.0 的版本。
现在假设你修复了一些错误,你只会增加 release 数量。
所以新名称将是 libmylib.0.1.0 或 libmylib.0.2.0 等。对于每个仅修复错误但不更改任何 ABI 的版本。
按照你说的。啊!我本可以更好地完成这个子功能,所以你添加了一组新的函数来做更好的事情,但是因为其他人仍在使用你的库,所以你仍然保留旧的(已弃用的)功能。
规则如下:
-
从每个 libtool 库的版本信息“0:0:0”开始。
-
仅在公开之前更新版本信息
发布您的软件。不需要更频繁的更新,并且
只保证当前接口号越大越快。
-
如果库源代码自上次更新后发生了变化,
然后增加修订('c:r:a' 变为'c:r+1:a')。
-
如果自上次以来添加、删除或更改了任何接口
更新,增加当前,并将修订设置为 0。
-
如果自上次公开发布以来添加了任何接口,则增加年龄。
-
如果自上次公开以来已删除或更改任何接口
释放,然后将年龄设置为 0。
您可以在libtool documentation了解更多信息
更新...
以下是我的解释有错误的评论。它不需要,这需要比可以放入答案评论更多的细节,所以见下文。
原反对意见
这里有一个错误:在linux上,版本的形式是
libmylib.(current-age).release.age,其中括号表示
要评估的表达式。例如 GLPK 4.54 与
current:revision:age = 37:1:1 on linux 安装库文件
libglpk.so.36.1.1。有关更多信息,请参阅,例如,
.
反驳
TLDR:autotools.io 不是权威来源。
解释
虽然 Flameeyes 是一位了不起的开发人员,并且他是 Gentoo 的维护者之一,但正是 他 犯了错误,并创建了对 libtool 规范的“经验法则”松散解释。虽然这不会在 99% 的情况下破坏系统,但如果我们遵循更新 current 的临时方式:
处理这些值时的经验法则是:
始终增加修订值。
每当添加接口时增加当前值,
删除或更改。
仅当对 ABI 所做的更改是
向后兼容。
然后他接着说维护多个版本的 Gtk 最好只是将库版本附加到库 NAME 中并简单地转储版本号。 (就像他们在 GTK+ 中所做的那样):
在这种情况下,最好的选择是附加库的一部分
版本信息到库的名称,例如
Glib 的 libglib-2.0.so.0 soname。为此,声明中的
Makefile.am 必须是这样的:
lib_LTLIBRARIES = libtest-1.0.la
libtest_1_0_la_LDFLAGS = -version-info 0:0:0
嗯,这只是破坏动态链接和符号解析版本控制功能的克罗克波特方法,完全没有实际意义!。他说关掉就好了。马鼻屎!难怪即使是经验丰富的开发人员也很难构建和维护开源项目,而且每次安装新版本的库时,我们都会不断遇到二进制文件死机(因为它们会相互破坏)。
libtool 版本控制方法是经过深思熟虑的。它是一个算法,它的步骤是有序指令1到6每次有一个更新动态链接库的代码。
对于新的和现有的开发人员,请仔细阅读它们,并想象在您出色的软件的整个生命周期中库版本号会发生什么变化。如果您这样做,您会注意到以前链接的每个软件将始终正确使用您惊人库的最新和准确版本,并且没有一个永远不会破坏或互相跺脚,并且你永远不必在你的图书馆的名字中添加一个盛开的数字(除非它是为了娱乐或美学)。