有人可以解释一下Linux库命名吗?

Nic*_*ton 21 c++ linux shared-libraries

当我在Linux上创建一个库时,我使用这个方法:

  1. 构建:libhelloworld.so.1.0.0
  2. 链接:libhelloworld.so.1.0.0 libhelloworld.so
  3. 链接:libhelloworld.so.1.0.0 libhelloworld.so.1

版本控制是这样的,如果您更改面向公众的方法,您可以构建到libhelloworld.so.2.0.0(并将1.0.0保留在原处),以便使用旧库的应用程序不会中断.

然而,命名为1.0.0的重点是什么 - 为什么不坚持使用libhelloworld.so和libhelloworld.so.1?

另外,最佳做法是使用1.0.0来命名您的库,还是仅仅1?

g++ ... -Wl,-soname,libhelloworld.1
Run Code Online (Sandbox Code Playgroud)

要么:

g++ ... -Wl,-soname,libhelloworld.1.0.0
Run Code Online (Sandbox Code Playgroud)

Tyl*_*nry 23

你应该形成xyz版本的方式是这样的:

  1. 第一个数字(x)是库的接口版本.每当您更改公共界面时,此数字都会增加.
  2. 第二个数字(y)是当前接口的修订号.无论何时在不更改公共接口的情况下进行内部更改,此数字都会增加.
  3. 第三个数字(z)不是内部版本号,它是向后兼容性计数.这告诉您支持多少先前的接口.因此,例如,如果接口版本4严格地是接口3和2的超集,但是与1完全不兼容,则z = 2(4-2 = 2,支持的最低接口编号)

因此,对于系统来说,x和z数字对于确定给定应用程序是否可以使用给定库非常重要,因为应用程序是针对编译的.y号主要用于跟踪错误修复.

  • 我认为您的解释定义了libtool映射方案,而不是Linux(或Solaris)soname方案. (4认同)

imo*_*lit 15

库命名约定

根据Wheeler的说法,我们拥有real name,soname以及linker name:

  Real name  libfoo.so.1.2.3
     Soname  libfoo.so.1
Linker name  libfoo.so
Run Code Online (Sandbox Code Playgroud)

real name是包含实际库代码的文件的名称.的soname通常是符号链接real name,并且其数目被递增时在不兼容的方式的界面的变化.最后,这linker name是链接器在请求库时使用的内容,该库是没有任何版本号的soname.

所以,先回答你的最后一个问题,你应该使用soname,libhelloworld.so.1用于链接器选项创建共享库时:

g++ ... -Wl,-soname,libhelloworld.so.1 ...
Run Code Online (Sandbox Code Playgroud)

在本文档中,Kerrisk提供了一个非常简单的示例,说明如何使用标准命名约定创建共享库.如果你想了解更多有关Linux库的信息,我认为KerriskWheeler都非常值得一读.

图书馆编号惯例

关于real name图书馆中每个数字的意图和目的存在一些混淆.我个人认为Apache Portable Runtime Project很好地解释了每个数字应该递增的规则.

简而言之,版本号可以被认为是libfoo.MAJOR.MINOR.PATCH.

  • PATCH 对于与其他版本兼容的向前和向后兼容的更改,会递增.
  • MINOR如果新版本的库是源代码并且二进制版本与旧版本兼容,则应增加.不同的次要版本是向后兼容的,但不一定是向前兼容的.
  • MAJOR 如果引入了一个破坏API的更改,或者与先前版本不兼容,则会增加.

这意味着PATCH版本可能仅在内部有所不同,例如在实现函数的方式.不允许更改API,公共函数的签名或函数参数的解释.

MINOR版本可能会引入新函数或常量,并且不推荐使用现有函数,但可能不会删除任何外部公开的函数.这确保了向后兼容性.换句话说,次要版本1.12.3可用于替换任何其他1.12.x 或更早版本,例如1.11.21.5.0.1.16.1然而,它并不是替代品,因为不同的次要版本不一定是向前兼容的.

随着新MAJOR版本的发布,可以进行任何类型的更改; 常量可能被删除或更改,(已弃用)函数可能被删除,当然,任何通常会增加MINORPATCH数字的更改(尽管将这些更改反向移植到以前的MAJOR版本可能也是值得的).

当然,有些因素会使这种情况进一​​步复杂化; 您可能已经开发了您的库,以便同一个文件可以同时包含多个版本,或者您可能使用libtool的约定current:revision:age.但这是另一次讨论.:)


bmd*_*cks 3

从我发给同事的一封关于这个问题的旧电子邮件中:

让我们以 libxml 为例。首先,共享对象存储在 /usr/lib 中,并带有一系列符号链接来表示可用库的版本:

lrwxrwxrwx 1 root root     16 Apr  4  2002 libxml.so -> libxml.so.1.8.14
lrwxrwxrwx 1 root root     16 Apr  4  2002 libxml.so.1 -> libxml.so.1.8.14
-rwxr-xr-x 1 root root 498438 Aug 13  2001 libxml.so.1.8.14
Run Code Online (Sandbox Code Playgroud)

如果我是 libxml 的作者,并且推出了新版本 libxml 2.0.0,它破坏了与以前版本的接口兼容性,我可以将其安装为 libxml.so.2 和 libxml.so.2.0.0。请注意,应用程序程序员要对其链接的内容负责。如果我真的很肛门,我可以直接链接到 libxml.so.1.8.14 ,任何其他版本都会导致我的程序无法运行。或者我可以链接到 libxml.so.1 并希望 libxml 开发人员不会破坏 1.X 版本中我的符号兼容性。或者,如果您不在乎并且鲁莽,只需链接到 libxml.so 并获取任何版本即可。有时,当有足够多的人这样做时,库作者必须在后续版本中发挥创意。因此,libxml2:

lrwxrwxrwx 1 root root     17 Apr  4  2002 libxml2.so.2 -> libxml2.so.2.4.10
-rwxr-xr-x 1 root root 692727 Nov 13  2001 libxml2.so.2.4.10
Run Code Online (Sandbox Code Playgroud)

请注意,此文件中没有 libxml2.so。看起来开发人员已经厌倦了不负责任的应用程序开发人员。

  • 嗯,假的。当您将“-lxml”提供给动态链接器时,它将使用“libxml.so”中的*库soname*,即“libxml.so.1”,因此这就是生成的可执行文件链接的内容。...(继续) (5认同)
  • (续)...当库版本正确时,*不会*发生直接链接到 `libxml.so` 或 `libxml.so.1.8.14` 的情况。运行可执行文件不需要“lib*.so”符号链接,仅需要开发它们,因此您可能会发现它们通常放置在单独的二进制包中。 (3认同)
  • 要查看库 soname,请使用“readelf -d /usr/lib/libxml.so”(假设您使用的是安装了 binutils 的开发系统)。 (3认同)