有人可以解释有关Linux库命名?

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

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

版本控制是这样的,如果你改变了面向公众的方法,你可以build立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 

要么:

 g++ ... -Wl,-soname,libhelloworld.1.0.0 

Solutions Collecting From Web of "有人可以解释有关Linux库命名?"

从我发给同事的一封旧邮件中提出这个问题:

以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 

如果我是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 

请注意,这里没有libxml2.so。 看起来开发人员厌倦了不负责任的应用程序开发人员。

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

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

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

库命名约定

根据惠勒 ,我们有real namesonamelinker name

  Real name libfoo.so.1.2.3 Soname libfoo.so.1 Linker name libfoo.so 

real name是包含实际库代码的文件的名称。 soname通常是real name的象征性链接,当界面以不兼容的方式变化时,它的编号会增加。 最后, linker name是链接器在请求库时使用的,这是没有任何版本号的soname。

因此,要首先回答您的最后一个问题,您应该在创建共享库时使用sonamelibhelloworld.so.1作为链接器选项:

 g++ ... -Wl,-soname,libhelloworld.so.1 ... 

在本文中 ,Kerrisk提供了一个非常简单的例子,介绍如何使用标准命名约定创建共享库。 我认为Kerrisk和Wheeler都非常值得一读,如果你想知道更多关于Linux库。

图书馆编号公约

关于图书馆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版本)。

当然,还有一些因素会使这个问题更加复杂。 您可能已经开发了库,以便同一个文件可以同时保存多个版本 ,也可以使用libtoolcurrent:revision:age 。 但这是另一次的讨论。 🙂

这种方法的主要优点是很容易让用户知道他们拥有哪个版本的库。 例如,如果我知道我得到的错误是在1.0.4中修复的,那么我可以很容易地检查我链接的库的版本,并知道这是修复错误的正确方法。

这个数字被称为“共享对象版本”或“soversion”,是ELF二进制标准的一部分。 IBM在http://www.ibm.com/developerworks/power/library/pa-spec12/上对ELF进行了很好的概述。

有几种方法来命名库:

  1. Solaris风格:.so – > .so.1
  2. GNU风格:.so – > .so.1 – > .so.1.2.3
  3. 随机:.so – > .so.1.2

看到:

https://blogs.oracle.com/ali/entry/how_to_name_a_solaris http://www.gnu.org/software/libtool/manual/libtool.html#Versioning