如何动态查找和包含库

时间:2019-04-30 00:19:51

标签: c++ linker autotools autoconf automake

我有一个库,我正在使用Autotools套件开发配置和makefile。该库在要对其进行编译的系统上需要一个外部库(特别是fftw3),我希望Autoconf / Automake在编译之前/编译时(在configure.ac或Makefile.am中)自动查找并链接/包括该外部库。

我目前仅使用autoconf“ --with-”标志为用户提供库文件和系统上外部库的include文件夹的位置,但这对用户来说似乎很麻烦。我正在为其构建配置文件和生成文件的库将部署在各种共享系统上,因此很难假设必要的外部库始终位于同一位置。

解决此问题的最佳方法是什么?

2 个答案:

答案 0 :(得分:1)

您可能想得太多。将库安装在不同系统上的不同位置本身并不是问题。开发工具链了解使用它们的系统的布局。基本情况相当稳健。只是(例如)...

AC_CHECK_LIB([fftw3], [fftw_plan_dft])

这将认识到libfftw3在搜索路径中确实可用,并且在这种情况下,会将适当的链接选项放在LIBS变量的前面,并定义HAVE_LIBFFTW3。 / p>

仅当您要提供未在链接器默认搜索路径中的库的使用,或者在该路径的较早位置找到该库的其他版本时,才会出现问题。 那是提供--with-foo选项的一种情况,构建者可以通过这些选项来指定位置。但是请注意,这是一个特殊情况下的问题,至少在与动态库链接时,因为开发库通常与运行时库一起安装,并且如果静态链接器在构建时未找到开发库,则通常需要一些动态链接器在运行时可以找到运行库的一种特殊规定。

尽管如此,如果要检查编码为configure的可能库位置的列表,则可以相对容易地完成。生成的configure是一个shell脚本,您可以为它编写文字代码到configure.ac中,而不会太麻烦。例如,

# Preserve the original value of LIBS
LIBS_save=$LIBS

# This is how we will report out the result
FFTW3_LIBS=

# Check the default locations first
AC_CHECK_LIB([fftw3], [fftw_plan_dft], [
  # libfftw3 found in the library search path
  FFTW3_LIBS=-lfftw3
], [
  # libfftw3 not found in the library search path; try some other paths
  # make the linker search the chosen path by adding an `-L` option to the LDFLAGS
  LDFLAGS_save=$LDFLAGS
  for fftw_libdir in
      /usr/lib/fftw
      /usr/lib/fftw3
      /usr/local/lib/fftw3
  do
    LDFLAGS="${LDFLAGS_save} -L${fftw_libdir}"
    AC_CHECK_LIB([fftw3], [fftw_plan_dft], [
      # library found
      FFTW3_LIBS="-L${fftw_libdir} -lfftw3"
      break
    ])
  done

  # restore the original LDFLAGS
  LDFLAGS=$LDFLAGS_save
])

# restore the original LIBS
LIBS=$LIBS_save

AS_IF([test x = "x${FFTW3_LIBS}"], [
  # configure fails if it does not find libfftw3
  AC_MSG_ERROR([libfftw3 not found])
])

# Make FFTW3_LIBS an output variable
AC_OUTPUT([FFTW3_LIBS])

该代码的显着特征包括

  • 保存和恢复配置在运行测试(LDFLAGS)和报告结果(LIBS)中使用的变量
  • 使用shell循环测试各种选项
  • 使用AC_CHECK_LIB的成功/错误操作
    • 了解AC_CHECK_LIB是一个,而不是一个函数,因此,例如,您可以将break放入其参数,这将退出{使用了{1}}
  • 使用输出变量将结果报告为一组链接选项。通过将AC_CHECK_LIB添加到适当的Makefile.am$(FFTW3_LIBS)变量中,可以在*LIBADD中使用它。 (或者,如果您不使用Automake,则可以通过适当的方式将其添加到链接命令中。)

当然,您可以将其与*LDADD选项结合使用,以支持意外情况(作为练习)。

答案 1 :(得分:0)

由于fftw3似乎要安装*.pc文件,因此我将在configure.ac中使用基于pkg-config的宏,类似于

PKG_CHECK_MODULES([FFTW3], [fftw3])

或者,如果您想对编译库的人有所帮助,类似

PKG_CHECK_MODULES([FFTW3], [fftw3], [],
                  [AC_MSG_ERROR([fftw3 devel package not found])])

当然,这需要在pkg-configautoreconf的时间安装configure

如果有人恰好在不寻常的地方安装了fftw3,他们可以将*.pc文件的安装目录添加到PKG_CONFIG_PATH环境变量中。

在定义Makefile.am库的libfoo文件中,然后可以添加类似

的行
libfoo_CFLAGS += $(FFTW3_CFLAGS)
libfoo_LIBADD += $(FFTW3_LIBS)

如果您想尽早发现试图在源代码上运行autoreconf而未安装pkg-config的用户,则可以在configure.ac上添加一行以确保{{1 }}定义了autoconf m4宏:

PKG_CHECK_MODULES

这是在野外看到的。

与内置m4_pattern_forbid([PKG_CHECK_MODULES])dnl 和Co宏相比,优点是AC_CHECK_LIB文件可以定义更多信息。例如

*.pc

但没有惊喜

[user@host ~]$ pkg-config --libs fftw3
-lfftw3 

可能包含令人惊讶的其他标志。分发软件包可能还在那里添加了系统特定的信息。

恕我直言,当依赖项附带了[user@host ~]$ pkg-config --libs fftw3q -lfftw3q -lquadmath 个文件时,使用*.pc优于使用PKG_CHECK_MDOULE