autoconf/automake:基于库的存在的条件编译?

Ian*_*cky 13 automake autoconf

我需要根据库的存在有条件地编译一些代码.使用autoconf/automake似乎应该很容易,但我无法弄明白.

例如,如果存在PNG库,我想包含使用它的代码.我的configure.ac有:

AC_CHECK_LIB([png], [png_create_write_struct_2])
Run Code Online (Sandbox Code Playgroud)

我的Makefile.am有:

if USE_LIBPNG
libdev_la_SOURCES += png.c
endif
Run Code Online (Sandbox Code Playgroud)

(它将png.c添加到libdev的源列表中,以便进行编译).

像USE_LIBPNG这样的automake条件要求在configure.ac中定义条件,所以我需要:

AM_CONDITIONAL([USE_LIBPNG], [test SOMETHINGOROTHER])
Run Code Online (Sandbox Code Playgroud)

问题是,什么可以测试SOMETHINGOROTHER?AC_CHECK_LIB定义了什么,我可以测试?

AC_CHECK_LIB的默认行为是定义一个可以在源代码中使用的符号(在config.h中),但这对Makefile没有帮助,因为AM_CONDITIONAL需要shell测试

我尝试覆盖默认的AC_CHECK_LIB行为,如下所示:

AC_CHECK_LIB([png], [png_create_write_struct_2], [HAS_LIBPNG=1])
Run Code Online (Sandbox Code Playgroud)

之后我可以测试它:

AM_CONDITIONAL([USE_LIBPNG], [test "x$HAS_LIBPNG" = "x1"])
Run Code Online (Sandbox Code Playgroud)

这很丑陋,但适用于Makefile ...但是会产生一个新问题:因为它丢弃了原来的AC_CHECK_LIB行为,而且我不再在config.h中添加一个符号,这是我需要的.

我必须遗漏一些基本的东西,或者可能做错了.已经挖了几个小时,没有找到答案.

任何人?

Jac*_*lly 25

如果您要检查的库提供了一个.pc文件供使用pkg-config,那么您最好使用它PKG_CHECK_MODULES来获取正确的标志.libpng做:

(中configure.ac)

PKG_CHECK_MODULES([libpng], [libpng12])
Run Code Online (Sandbox Code Playgroud)

这使您可以访问变量$(libpng_CFLAGS)以及$(libpng_LIBS)要添加到的变量Makefile.am(可能在AM_CFLAGS/ AM_CXXFLAGSLDADD其特定于目标的版本中).

configure如果libpng12.pc找不到,它也会导致失败并出现错误.如果你想configure继续,你需要提供第三个和第四个参数PKG_CHECK_MODULES,它们是ACTION-IF-FOUNDACTION-IF-NOT-FOUND:

(中configure.ac)

PKG_CHECK_MODULES([libpng], [libpng12], [HAVE_LIBPNG=1], [HAVE_LIBPNG=0])
Run Code Online (Sandbox Code Playgroud)

现在,如果您需要automake条件,您可以执行以下操作:

(中configure.ac)

AM_CONDITIONAL([USE_LIBPNG], [test "$HAVE_LIBPNG" -eq 1])
Run Code Online (Sandbox Code Playgroud)

如果您还需要预处理器定义,则可以这样使用AC_DEFINE:

(中configure.ac)

AS_IF([test "$USE_LIBPNG" -eq 1], [AC_DEFINE([USE_LIBPNG], [1], [Define if using libpng.])])
Run Code Online (Sandbox Code Playgroud)

可能更好的是将定义设置为Makefile.am:

(中Makefile.am)

AM_CPPFLAGS =
if USE_LIBPNG
AM_CPPFLAGS += -DUSE_LIBPNG
endif
Run Code Online (Sandbox Code Playgroud)

但是,这会使命令行变得混乱,但AC_DEFINE如果使用,可以将定义放在标题中AC_CONFIG_HEADERS.我想这并不重要,如果你使用AM_SILENT_RULES([yes])或不关心你的命令行整洁(并且说实话,automake无论如何生成一些非常粗糙的命令行).

关于好autoconf风格的说明

根据检查是否成功构建可选支持被视为不良形式(有关详细信息,请参阅此gentoo文档).以下是我为libpng编写可选支持的代码:

(中configure.ac)

# This is because the first PKG_CHECK_MODULES call is inside a conditional.
PKG_PROG_PKG_CONFIG

AC_ARG_WITH([libpng],
  [AS_HELP_STRING([--with-libpng],
    [support handling png files @<:@default=check@:>@])],
  [],
  [with_libpng=check])
AS_CASE(["$with_libpng"],
  [yes], [PKG_CHECK_MODULES([libpng], [libpng12], [HAVE_LIBPNG=1])],
  [no], [],
  [PKG_CHECK_MODULES([libpng], [libpng12], [HAVE_LIBPNG=1], [HAVE_LIBPNG=0])])
AM_CONDITIONAL([USE_LIBPNG], [test "$with_libpng" != no -a "$HAVE_LIBPNG" -eq 1])
Run Code Online (Sandbox Code Playgroud)

(中Makefile.am)

if USE_LIBPNG
AM_CPPFLAGS += -DUSE_LIBPNG
AM_CFLAGS += $(libpng_CFLAGS)
LDADD += $(libpng_LIBS)
libdev_la_SOURCES += png.c
endif
Run Code Online (Sandbox Code Playgroud)

如果您的图书馆没有.pc文件

为了完整起见,这是我如何检查没有.pc文件的库.我将跳过以下好autoconf风格的细节.AC_CHECK_LIB设置一个缓存变量,所以你可以测试,而不是替换的ACTION-IF-FOUNDAC_CHECK_LIB:

(中configure.ac)

AC_CHECK_LIB([png], [png_create_write_struct_2])

# Then test:
AS_IF([test "$ac_cv_lib_png_png_create_write_struct_2" = yes], [HAVE_LIBPNG=1], [HAVE_LIBPNG=0])

# Or set conditional:
AM_CONDITIONAL([USE_LIBPNG], [test "$ac_cv_lib_png_png_create_write_struct_2" = yes])
Run Code Online (Sandbox Code Playgroud)

恕我直言,你应该这样做,如果没有其他选择.