在linux

时间:2017-07-20 09:50:48

标签: c gcc clang shared-libraries

我开发了一个需要一些动态库的C程序,最着名的是libmysqlclient.so,我打算在一些远程主机上运行。好像我有以下分发选项:

  1. 编译程序静态。
  2. 在远程主机上安装所需的依赖项
  3. 使用该程序分发依赖项。
  4. 第一个选项是有问题的,因为我在运行时需要glibc-version(因为我现在使用glibc和libnss)。

    我不确定第二个选项:是否有一种机制可以检查已安装的库版本是否足以运行程序(在libxyz.so.VERSION旁边)。我可以在启动时以某种方式检查ABI兼容性吗?

    关于最后一个选项:我将使用二进制文件分发所有共享库,还是仅使用可能未安装的共享库(例如libmysqlclient,而不是libm)。

    除此之外,如果我为二进制文件使用不同的编译器,那么我可能会遇到ABI兼容性问题,那么依赖项是用它构建的(例如binary clang,libraries gcc)?

1 个答案:

答案 0 :(得分:3)

版本检查是特定于分发的。通常,您可以使用目标发行版的打包工具将应用程序打包到.deb.rpm文件中,然后将其发送给用户。这意味着您必须为每个受支持的发行版构建一次应用程序,但无论如何都无法解决这个问题,因为不同的发行版具有稍微不同的libmysqlclient版本。这些分发构建工具会自动生成一些依赖版本信息,而在其他情况下,需要一些手动帮助。

作为一个起点,查看依赖于MySQL / MariaDB客户端库并复制它的内容的分发包装是一个好主意。也许Debian中的inspircd就是一个很好的例子。

您可以通过构建要支持的最旧的分发版本来减少创建和测试所需的构建量。但有些警告适用;分布在它们提供的向后兼容性程度上有所不同。

分发与程序的依赖关系是非常有问题的,因为基本操作系统也提供了诸如libmysqlclient之类的流行库,并且如果使用LD_LIBRARY_PATH注入自己的版本,这可能会无意中扩展到其他程序(例如,您从自己的程序启动的程序)。即使您使用DT_RUNPATH(通过-rpath链接器选项),后一种风险仍然存在,尽管它有所减少。

另一种选择是静态链接特定于应用程序的支持库,并动态链接基本操作系统库。 (这是一些软件集合所做的。)尽管如此,这似乎不是libmysqlclient的一个很好的选择,因为可能期望它的功能集与分发相同(关于TLS库和可用的配置选项),并且使用静态链接,这很难实现。