设置自动工具以静态链接单个系统库



我有一个项目,我想静态链接其中一个系统库。该项目使用GNU构建系统。

configure.ac 我有:

AC_CHECK_LIB(foobar, foobar_init)

在开发机器上,这个库安装在/usr/lib/x86_64-linux-gnu 中。它被检测到,但它是动态链接的,这会导致问题,因为它在某些计算机上不存在。静态链接它(-wl,-bstatic 等)工作正常,但我不知道如何在自动工具中设置它。我尝试将其强制到项目的 Makefile.am 链接标志中,但它仍然优先选择动态库。 我也尝试将 --enable-static 与 ./configure 一起使用,但它似乎对系统库没有影响。

如果要静态链接整个程序,则应将--disable-shared选项传递给configure。 您可能还需要也可能不需要传递--enable-static,具体取决于该选项的默认值(您可以通过configure.ac文件对其进行影响)。 你真的应该考虑这样做。

您还应该考虑将此作为安装程序的问题,而不是构建系统的问题。 让安装程序负责确保程序所需的所有共享库都由安装它的系统提供。 这是常见的;事实上,它是包装管理系统的灵感之一,例如yum/dnfapt,及其底层打包格式。

如果您坚持静态地只链接一个库,而动态链接其他所有库,那么您将需要跳过更多的箍。 目标是发出链接选项,使该库仅静态链接,而不更改其他库的链接。 使用GNU工具链,假设程序是动态链接的,那就是选项的组合:

-Wl,-Bstatic -lfoobar -Wl,-Bdynamic

现在考虑AC_CHECK_LIB()宏的文档:

宏:AC_CHECK_LIB(libraryfunction, [action-if-found], [action-if-not-found], [other-libraries])

[...]action-if-found是与库的链接成功时要运行的 shell 命令列表;action-if-not-found是外壳列表 链接失败时要运行的命令。如果action-if-found不是 指定,默认操作在-llibrary前面预置LIBS并定义 'HAVE_LIBlibrary'(所有首都)。[...]

特别要注意在未提供可选参数的情况下的默认行为(您现在的情况)——这不是您想要的,至少不是本身。 我建议至少为action-if-found情况提供另一种行为,您也可以考虑在action-if-not-found情况下configure失败。 后者留作练习;仅实现前者可能如下所示:

AC_CHECK_LIB([foobar], [foobar_init], [
LIBS="-Wl,-Bstatic -lfoobar -Wl,-Bdynamic $LIBS"
AC_DEFINE([HAVE_LIBFOOBAR], [1], [Define to 1 if you have libfoobar.])
])

您还应该注意AC_CHECK_LIB()调用的顺序。 正如其文档继续说的那样:

此宏旨在支持从右到左构建LIBS(从最小依赖到最依赖)方式,使得库 依赖性作为连续的自然副作用得到满足 测试。链接器对库排序很敏感,因此 生成的LIBS对于可靠地检测库非常重要。

如果您发现仍然没有得到想要的东西,请查看make实际执行的链接命令。 您需要先了解它们的问题所在,然后才能确定如何解决问题。

综上所述,我观察到上述处理基本上是一种黑客攻击,它使您的构建系统的弹性大大降低。 它引入了对GNU工具链选项的依赖(尽管如此,其他一些工具链可能会接受),并且它假设动态链接总体上正在执行。 也许可以通过额外的 Autoconf 代码解决这些问题,但我敦促您改用我描述的前两种选择之一。

最新更新