在 linux 下分发具有库依赖项的 c 程序的选项
Options for distributing a c program with library-dependencies under linux
我开发了一个需要一些动态库的 C 程序,最值得注意的是 libmysqlclient.so,我打算在某些远程主机上 运行。似乎我有以下分发选项:
- 静态编译程序。
- 在远程主机上安装所需的依赖项
- 随程序分发依赖项。
第一个选项有问题,因为无论如何我都需要 glibc-version
在 运行 时间(因为我现在使用 glibc 和 libnss)。
我不确定第二个选项:是否有一种机制可以检查安装的库版本是否足以让程序达到 运行(除了 libxyz.so.VERSION)。我可以在启动时以某种方式检查 ABI 兼容性吗?
关于最后一个选项:我会用二进制文件分发所有共享库,还是只分发可能未安装的共享库(例如 libmysqlclient,但不是 libm)。
除此之外,如果我对二进制文件使用不同的编译器,然后使用构建依赖项的编译器(例如二进制 clang、库 gcc),我是否可能会遇到 ABI 兼容性问题?
版本检查是特定于发行版的。通常,您会使用目标发行版的打包工具将您的应用程序打包到 .deb
或 .rpm
文件中,然后将其发送给用户。这意味着您必须为每个受支持的发行版构建您的应用程序一次,但实际上没有办法解决这个问题,因为不同的发行版具有略微不同的 libmysqlclient
版本。这些分发构建工具会自动生成一些依赖版本信息,在其他情况下,需要一些手动帮助。
作为起点,最好查看依赖于 MySQL/MariaDB 客户端库的分发包并复制它。也许 Debian 中的 inspircd
就是一个很好的例子。
您可以通过构建您想要支持的最旧的分发版本来减少您需要创建和测试的构建数量。但有一些警告适用;发行版提供的向后兼容性程度各不相同。
使用程序分发依赖项是非常有问题的,因为基本操作系统也提供了 libmysqlclient
等流行的库,如果您使用 LD_LIBRARY_PATH
注入您自己的版本,这可能会无意中也扩展到其他程序(例如,您从自己的程序启动的程序)。即使您使用 DT_RUNPATH
(通过 -rpath
linker 选项),后一种风险仍然存在,尽管它有所降低。
一个不同的选择是 link 仅静态支持特定于应用程序的库,而 link 动态支持基本操作系统库。 (这是一些软件集合所做的。)不过,对于 libmysqlclient
来说,这似乎不是一个很好的选择,因为可能期望它的功能集与发行版相同(关于 TLS 库和可用的配置选项),并且使用静态 linking,这很难实现。
我开发了一个需要一些动态库的 C 程序,最值得注意的是 libmysqlclient.so,我打算在某些远程主机上 运行。似乎我有以下分发选项:
- 静态编译程序。
- 在远程主机上安装所需的依赖项
- 随程序分发依赖项。
第一个选项有问题,因为无论如何我都需要 glibc-version
在 运行 时间(因为我现在使用 glibc 和 libnss)。
我不确定第二个选项:是否有一种机制可以检查安装的库版本是否足以让程序达到 运行(除了 libxyz.so.VERSION)。我可以在启动时以某种方式检查 ABI 兼容性吗?
关于最后一个选项:我会用二进制文件分发所有共享库,还是只分发可能未安装的共享库(例如 libmysqlclient,但不是 libm)。
除此之外,如果我对二进制文件使用不同的编译器,然后使用构建依赖项的编译器(例如二进制 clang、库 gcc),我是否可能会遇到 ABI 兼容性问题?
版本检查是特定于发行版的。通常,您会使用目标发行版的打包工具将您的应用程序打包到 .deb
或 .rpm
文件中,然后将其发送给用户。这意味着您必须为每个受支持的发行版构建您的应用程序一次,但实际上没有办法解决这个问题,因为不同的发行版具有略微不同的 libmysqlclient
版本。这些分发构建工具会自动生成一些依赖版本信息,在其他情况下,需要一些手动帮助。
作为起点,最好查看依赖于 MySQL/MariaDB 客户端库的分发包并复制它。也许 Debian 中的 inspircd
就是一个很好的例子。
您可以通过构建您想要支持的最旧的分发版本来减少您需要创建和测试的构建数量。但有一些警告适用;发行版提供的向后兼容性程度各不相同。
使用程序分发依赖项是非常有问题的,因为基本操作系统也提供了 libmysqlclient
等流行的库,如果您使用 LD_LIBRARY_PATH
注入您自己的版本,这可能会无意中也扩展到其他程序(例如,您从自己的程序启动的程序)。即使您使用 DT_RUNPATH
(通过 -rpath
linker 选项),后一种风险仍然存在,尽管它有所降低。
一个不同的选择是 link 仅静态支持特定于应用程序的库,而 link 动态支持基本操作系统库。 (这是一些软件集合所做的。)不过,对于 libmysqlclient
来说,这似乎不是一个很好的选择,因为可能期望它的功能集与发行版相同(关于 TLS 库和可用的配置选项),并且使用静态 linking,这很难实现。