多个版本的库,如何使用GCC / g ++ whit out版本号进行编译

时间:2014-07-18 08:55:35

标签: gcc g++ rpm deb

我正在使用C中的库,我们称之为忍者。 Ninja取决于一些铺设不足的库(我们也提供)(例如jutsu,goku,bla)。 这些都放在共享库文件夹中,让我们说/ usr / lib / secret /。 正在使用这个项目的客户希望能够并排放置忍者版本1和2,这并不难。当忍者1依赖于例如jutsu 1并且忍者2依赖于jutsu 3时,问题就出现了。如何...我们/我这样做以便从我们的软件包存储库安装ninja时。它知道jutsu的正确版本。当然rpm / deb包应该取决于jutsu包的正确版本。

所以我们想要的是什么时候,我们在忍者中执行zypper。它在系统上安装和编译,它知道哪个jutsu库带有一个版本号。

所以我们在make文件中不必这样做:

gcc ninja.c -o ninja -L /usr/local/lib/secret/ -l jutsu_2

但只是

gcc ninja.c -o ninja -L /usr/local/lib/secret/ -l jutsu

注意:我知道使用忍者等是随机的,但我不允许发布真正的库名称

1 个答案:

答案 0 :(得分:1)

您想要使用SONAME。描述所有必要的步骤可能是一个很好的StackOverflow答案的范围,但我可以给出一个概述并指出一些文档。

SONAME是共享库中的特殊数据字段。它通常用于表示与同一库的其他版本的兼容性;如果共享库的两个不同版本具有相同的SONAME,则链接器将知道任一个可以填充该库的依赖关系。如果他们有不同的SONAME,他们就不能。

示例:我在Debian wheezy系统上安装了libdns88libbind-dev版本1:9.8.4.dfsg.P1-6+nmu2+deb7u1。我用samurai构建了一个名为-ldns的二进制文件。 GNU链接器在我的库搜索路径中找到“libdns.so”并动态链接samurai。它从libdns.so(这是libdns.so.88.1.1的符号链接)读取SONAME字段。 SONAME有“libdns.so.88”。

$ objdump -p /usr/lib/libdns.so | grep SONAME
  SONAME               libdns.so.88

libdns开发人员(或者可能是打包者)选择SONAME来指示任何版本的88. * libdns都应该与任何其他版本88二进制兼容。*。对于具有兼容ABI的所有版本,它们使用相同的SONAME。当ABI发生变化时,他们将SONAME更改为libdns.so.89,依此类推。 (大多数管理良好的库通常不会改变它们的ABI。)

因此,写入samurai二进制文件的库依赖关系只是libdns.so.88。当我稍后运行samurai时,动态链接器/加载器会查找名为“libdns.so.88”的文件,而不仅仅是“libdns.so”。

同样按照惯例,当包含库的SONAME发生更改时,rpm或deb包的名称应该更改。这就是为什么有libdns88包与libdns100包分开的原因,它们可以并排安装而不会相互干扰。我的samurai包将依赖于“libdns88”,我可以预期任何名为libdns88的包都将与我构建的包具有兼容的ABI。像dpkg-shlibdeps这样的工具可以在使用SONAME和版本化符号时轻松创建正确的共享库包依赖项。

http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html