首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >autoconf/automake:基于库存在的条件编译?

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

Stack Overflow用户
提问于 2011-03-03 05:13:16
回答 2查看 10.2K关注 0票数 17

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

例如,如果有一个PNG库,我希望包含使用它的代码。我的configure.ac有:

代码语言:javascript
运行
复制
AC_CHECK_LIB([png], [png_create_write_struct_2])

我的Makefile.am有:

代码语言:javascript
运行
复制
if USE_LIBPNG
libdev_la_SOURCES += png.c
endif

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

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

代码语言:javascript
运行
复制
AM_CONDITIONAL([USE_LIBPNG], [test SOMETHINGOROTHER])

问题是,什么东西可以测试或其他东西是什么?AC_CHECK_LIB定义了我可以测试的内容吗?

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

我试图重写默认的AC_CHECK_LIB行为如下:

代码语言:javascript
运行
复制
AC_CHECK_LIB([png], [png_create_write_struct_2], [HAS_LIBPNG=1])

在那之后我可以测试它:

代码语言:javascript
运行
复制
AM_CONDITIONAL([USE_LIBPNG], [test "x$HAS_LIBPNG" = "x1"])

这太丑了,但在Makefile工作.但是造成了一个新的问题:因为它丢弃了原始的AC_CHECK_LIB行为,所以我不再需要添加到config.h的符号。

我一定是错过了一些基本的东西,或者可能做错了什么。已经挖了好几个小时了却没找到答案。

有没有人?

EN

回答 2

Stack Overflow用户

发布于 2011-03-03 06:28:10

如果您正在检查的库提供了一个.pc文件,以便与pkg-config一起使用,那么最好使用PKG_CHECK_MODULES来获得正确的标志。libpng确实:

( configure.ac)

代码语言:javascript
运行
复制
PKG_CHECK_MODULES([libpng], [libpng12])

这使您可以访问要添加到$(libpng_CFLAGS)中的变量$(libpng_LIBS) (可能在AM_CFLAGS/AM_CXXFLAGSLDADD中,或者在特定于目标的版本中)。

如果找不到configure,也会导致libpng12.pc失败。如果希望configure继续,则需要向PKG_CHECK_MODULES提供第三个和第四个参数,即ACTION-IF-FOUNDACTION-IF-NOT-FOUND

( configure.ac)

代码语言:javascript
运行
复制
PKG_CHECK_MODULES([libpng], [libpng12], [HAVE_LIBPNG=1], [HAVE_LIBPNG=0])

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

( configure.ac)

代码语言:javascript
运行
复制
AM_CONDITIONAL([USE_LIBPNG], [test "$HAVE_LIBPNG" -eq 1])

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

( configure.ac)

代码语言:javascript
运行
复制
AS_IF([test "$USE_LIBPNG" -eq 1], [AC_DEFINE([USE_LIBPNG], [1], [Define if using libpng.])])

可能更好的做法是在Makefile.am中设置定义

( Makefile.am)

代码语言:javascript
运行
复制
AM_CPPFLAGS =
if USE_LIBPNG
AM_CPPFLAGS += -DUSE_LIBPNG
endif

然而,这将使命令行混乱,而如果使用AC_DEFINE,则AC_CONFIG_HEADERS可以将定义放入标头中。我想如果您使用AM_SILENT_RULES([yes])或者不关心您的命令行是否整洁(老实说,automake生成了一些非常粗糙的命令行),这并不重要。

关于良好autoconf风格的一点注记

基于检查是否成功,构建可选支持被认为是糟糕的形式(详见这个绅士医生 )。下面是我如何为libpng编写可选的支持:

( configure.ac)

代码语言:javascript
运行
复制
# 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)

代码语言:javascript
运行
复制
if USE_LIBPNG
AM_CPPFLAGS += -DUSE_LIBPNG
AM_CFLAGS += $(libpng_CFLAGS)
LDADD += $(libpng_LIBS)
libdev_la_SOURCES += png.c
endif

如果您的库没有.pc文件

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

( configure.ac)

代码语言:javascript
运行
复制
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])

IMHO,只有在没有其他选择的情况下,你才应该这样做。

票数 31
EN

Stack Overflow用户

发布于 2011-03-03 18:02:46

谢谢你的回复。

杰克:我正在努力实现最大的可移植性,所以不能假设库是作为包的一部分安装的(它们不是在我自己的盒子上!),这意味着您建议的没有其他选项的解决方案就是我已经尝试过的--手动设置一个shell变量--但也手动执行了AC_CHECK_LIB应该完成的额外步骤:将库放在LIBS前面,并定义HAVE_LIBxxx。

但是有一个问题:自动报头抱怨裸露的AC_DEFINE:

代码语言:javascript
运行
复制
autoheader: warning: missing template: HAVE_LIBPNG
autoheader: Use AC_DEFINE([HAVE_LIBPNG], [], [Description])

如果autoheader在将来起作用的话,我会很高兴的,所以我不得不将AC_DEFINE改为完整的monty:

代码语言:javascript
运行
复制
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的默认行为。

威廉:是的,我可以用grep来定义concondes.h中的符号,这也很管用。

这两种解决方案各有优缺点(什么不是呢?)不知道我会走哪条路,但有选择是很好的。

再次感谢。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5176929

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档