我需要根据库的存在有条件地编译一些代码。使用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中添加一个符号,这是我需要的。
我必须遗漏一些基本的东西,或者可能做错了。一直在挖掘几个小时,没有找到答案。
任何?
答案 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.am
,AM_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中找到符号定义,这也有效。
两种解决方案都有其优点和缺点(什么不是?)。不知道我会选择哪种方式,但有选择权很好。
再次感谢。