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

时间:2011-03-03 05:13:17

标签: autoconf automake

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

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

AC_CHECK_LIB([png], [png_create_write_struct_2])

我的Makefile.am有:

if USE_LIBPNG
libdev_la_SOURCES += png.c
endif

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

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

AM_CONDITIONAL([USE_LIBPNG], [test SOMETHINGOROTHER])

问题是,什么可以测试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])

之后我可以测试它:

AM_CONDITIONAL([USE_LIBPNG], [test "x$HAS_LIBPNG" = "x1"])

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

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

任何?

3 个答案:

答案 0 :(得分:25)

如果您要检查的库提供.pc文件以供pkg-config使用,那么您最好使用PKG_CHECK_MODULES来获取正确的标记。 libpng确实:

(在configure.ac

PKG_CHECK_MODULES([libpng], [libpng12])

这使您可以访问要添加到$(libpng_CFLAGS)的变量$(libpng_LIBS)Makefile.am(可能在AM_CFLAGS / AM_CXXFLAGS和{{ 1}},或其特定目标版本。)

如果找不到LDADD,它还会导致configure失败并显示错误。如果您希望libpng12.pc继续,则需要提供configure的{​​{1}}和PKG_CHECK_MODULES的第三个和第四个参数:

(在ACTION-IF-FOUND

ACTION-IF-NOT-FOUND

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

(在PKG_CHECK_MODULES([libpng], [libpng12], [HAVE_LIBPNG=1], [HAVE_LIBPNG=0])

automake

如果您还需要预处理器定义,可以使用configure.ac,如下所示:

(在AM_CONDITIONAL([USE_LIBPNG], [test "$HAVE_LIBPNG" -eq 1])

AC_DEFINE

可能更好的是在configure.ac中设置定义:

(在AS_IF([test "$USE_LIBPNG" -eq 1], [AC_DEFINE([USE_LIBPNG], [1], [Define if using libpng.])])

Makefile.am

这会使您的命令行变得混乱,而如果您使用Makefile.amAM_CPPFLAGS = if USE_LIBPNG AM_CPPFLAGS += -DUSE_LIBPNG endif 可以将定义放在标题中。我想如果你使用AC_DEFINE或者不关心你的命令行是否整洁(或者说实话,AC_CONFIG_HEADERS生成一些非常粗糙的命令行,这并不重要。)

关于良好AM_SILENT_RULES([yes])样式

的说明

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

(在automake

autoconf

(在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])

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

为了完整起见,这是我如何检查没有if USE_LIBPNG AM_CPPFLAGS += -DUSE_LIBPNG AM_CFLAGS += $(libpng_CFLAGS) LDADD += $(libpng_LIBS) libdev_la_SOURCES += png.c endif 文件的库。我将跳过以下良好.pc风格的细节。 .pc设置了一个缓存变量,因此您可以对其进行测试,而不是替换autoconf的{​​{1}}:

(在AC_CHECK_LIB

ACTION-IF-FOUND

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

答案 1 :(得分:1)

我会对杰克建议使用PKG_CHECK_MODULES轻微地反对意见。最好避免使用它。但我同意杰克关于避免在AC_CHECK_LIB的第3个参数中分配LIBS。如果让AC_CHECK_LIB使用默认设置,生活会更容易。

虽然AC_CHECK_LIB没有定义指示是否找到库的shell变量,但您可以在configure.ac中执行此操作:

AM_CONDITIONAL([USE_LIBPNG],[grep HAVE_LIBPNG confdefs.h > /dev/null])

可以说,这依赖于内部autoconf细节,但实际上可靠地工作。

答案 2 :(得分:1)

感谢您的回复。

杰克:我正在尝试最大程度的可移植性,所以不能假设这些库是作为软件包的一部分安装的(它们不在我自己的盒子里!),这意味着你建议的其他选项解决方案是我已经尝试过的 - 手动设置shell变量 - 但也手动执行AC_CHECK_LIB已经完成的额外步骤:将库预先添加到LIBS并定义HAVE_LIBxxx。

虽然有一个问题:autoheader抱怨裸AC_DEFINE:

autoheader: warning: missing template: HAVE_LIBPNG
autoheader: Use AC_DEFINE([HAVE_LIBPNG], [], [Description])

如果autoheader将来工作我会很好,所以我不得不将AC_DEFINE更改为完整的monty:

AC_CHECK_LIB([png], [png_create_write_struct_2],
    [HAS_LIBPNG=1
     LIBS="-lpng $LIBS"
     AC_DEFINE([HAVE_LIBPNG], 1, [Define to 1 if you have the `png' library (-lpng)])])

这样可行,但我不太喜欢复制AC_CHECK_LIB的默认行为。

William:是的,我可以在confdefs.h中找到符号定义,这也有效。

两种解决方案都有其优点和缺点(什么不是?)。不知道我会选择哪种方式,但有选择权很好。

再次感谢。