【转】GNU autotools(四)编写configure.ac

1. 常用的autoconf宏

1.1 AC_PREREQ()

AC_PREREQ宏指定autoconf的最低版本。例子如下:

AC_PREREQ(2.69)

1.2 AC_INIT()

AC_INIT宏初始化autoconf系统。

AC_INIT最多接受五个参数:package名称,version,和可选的bug-report地址,tarname和url。如下的例子指定了前三个。

AC_INIT([helloauto], [1.0], [[email protected]])

package名称使用一种标准化的形式。automake生成的压缩包被默认命名为tarname-version.tar.gz,tarname被设置为标准化的软件包名(小写,所有标点被转化为下划线)。

bug-report参数,通常设置为一个E-Mail地址,但是任何文本字符串都是有效的。

version参数,最为广泛使用的惯例是传递marjor.minor。但用marjor.minor.reversion也没有错误。如果你喜欢,你甚至可以添加非数字文本到这个宏,例如0.15.alpha。

autoconf从AC_INIT的参数,生成一些替换变量,如:
@PACKAGE_NAME@,
@PACKAGE_VERSION@,
@PACKAGE_TARNAME@,
@PACKAGE_STRING@ ,
@PACKAGE_BUGREPORT@

1.3 AM_INIT_AUTOMAKE

AM_INIT_AUTOMAKEH是auotmake的宏。它初始化automake,参数是调用automake使用的参数(与编译器没有关系)。

例子如下:

AM_INIT_AUTOMAKE([-Wall -Werror foreign])

1.4 PKG_CHECK_MODULES

PKG_CHECK_MODULES是pkg-config工具提供的宏。它检查指定的库是否存在并符合要求。如果是,则设置变量XXX_CFLAGS和XXX_LIBS的值。其中XXX是PKG_CHECK_MODULES宏的第一个参数。

如下的例子,检查libdrm.so是否存在并且版本不低于2.4。如果是,设置变量video_drm的值为yes,否则设置为no。

PKG_CHECK_MODULES(DRM, [libdrm >= 2.4], video_drm="yes",video_drm="no")

1.5 AC_CONFIG_SRCDIR

AC_CONFIG_SRCDIR宏的目的,是让configure脚本知道,它执行的目录是否真是工程的目录。

configure需要能定位自己,因为工程代码可能是来自一个远程目录。AC_CONFIG_SRCDIR给了一个在正确位置查找的重要提示。

AC_CONFIG_SRCDIR指定的文件,应该尽量选择你的项目独有的文件,这样configure不容易把其它项目的目录当成是自己的。

如下的例子指定src/main.c作为这个文件。

AC_CONFIG_SRCDIR([src/main.c])

1.6 AC_CONFIG_HEADERS

AC_CONFIG_HEADERS宏允许指定一个或多个config.status从模板文件生成的头文件。可以在你的头文件模板里放置多个像这样的声明,每行一个。

如下面的例子指定了头文件config.h。当configure.ac修改时,config.status会基于AC_CONFIG_HEADERS宏重新生成config.h。

AC_CONFIG_HEADERS([config.h])

1.7 AC_CHECK_PROG

AC_CHECK_PROG宏检查指定的程序是否存在。

如下面的例子,如果ranlib存在,则变量RANLIB设置为ranlib,否则设置为:。

AC_CHECK_PROG([RANLIB], [ranlib], [:])

1.8 AC_CHECK_TOOL

AC_CHECK_TOOL宏与AC_CHECK_PROG功能类似,它检查指定的程序是否存在。不同的是,它会先检查--host值作为前缀的命令。

举一个例子。如果如下调用configure:

./configure --build=x86_64-gnu --host=i386-gnu

则AC_CHECK_TOOL宏先检查i386-gnu-ranlib是否存在,如果不存在,才继续检查ranlib是否存在。如果程序存在,将RANLIB变量相应地设置为i386-gnu-ranlib或ranlib。

AC_CHECK_TOOL([RANLIB], [ranlib], [:])

1.9 AC_PROG_CC 与 AC_PROG_CXX

AC_PROG_CC宏决定使用哪个C编译器。如果指定了参数,则按照参数指定的顺序检查编译器是否可用。最后将编译器名称写入变量CC。

如下的例子指定按gcc、cc的顺序进行检查。

AC_PROG_CC([gcc cc])

AC_PROG_CXX宏与AC_PROG_CC功能类似,不同的是,它决定使用哪个C++编译器,编译器名称写入变量CXX。

1.8 AC_PROG_INSTALL

AC_PROG_INTALL宏设置变量INSTALL。如果在当前PATH环境下能找到install程序,则将INSTALL设置为install,否则设置为'install-sh -c'。autoconf包中有install-sh,应该将它复制到工程中。

如下是一个例子。

AC_PROG_INSTALL

1.9 AC_SUBST

对于AC_SUBST宏, automake会在Makefile.in中生成一个输出变量,这样Makefile.am中可以使用这个变量,变量的值是它的当前值。

如下的例子生成变量HBLIBSUFFIX。

AC_SUBST(HBLIBSUFFIX)

Makefile.am可以如下使用HBLIBSUFFIX。

lib_LTLIBRARIES += libharfbuzz@[email protected]

1.10 AC_DEFINE 和 AC_DEFINE_UNQUOTED

AC_DEFINE宏和AC_DEFINE_UNQUOTED宏,定义C预编译符号。

缺省情况下,AC_OUTPUT宏把这些符号输出到变量DEFS中,configure将它们传递给编译器;如果configure.ac中调用了AC_CONFIG_HEADERS宏,AC_OUTPUT把它们保存在头文件中,每个符号对应一个#define行。

如下AC_DEFINE的例子定义符号HAVE_VPRINTF=1。第三个参数是说明。只有调用了AC_CONFIG_HEADERS宏才有意义,它是附加在#define行后的注释。

AC_DEFINE([HAVE_VPRINTF], [1], [Define if vprintf exists.])

AC_DEFINE_UNQUOTED与AC_DEFINE不同的地方在于,它能扩展shell符号,包括$(变量展开), `(命令替换),和\ (换行消除)。

如下的例子,先展开conf变量,然后定义符号ETCFILENAME。

AC_DEFINE_UNQUOTED(ETCFILENAME, "${conf}", [MiniGUI configure file name])

1.11 AC_CHECK_HEADERS

AC_CHECK_HEADERS宏检查指定的系统头文件是否存在。

如下的例子检查系统头文件stdlib.h是否存在。

AC_CHECK_HEADERS([stdlib.h])

1.12 AC_CHECK_LIB

AC_CHECK_LIB宏检查指定库中指定的函数是否存在。如果存在,向输出变量LIBS中,加入-llib。

如下的例子检查pthread库是否存在函数pthread_rwlock_init()。

AC_CHECK_LIB([pthread], [pthread_rwlock_init])

1.13 AC_CHECK_FUNC 与 AC_CHECK_FUNCS

AC_CHECK_FUNC宏检查指定的C函数是否可用。如果可用,则定义ac_cv_func_XXX变量并且设置为yes。

如下的例子检查函数vprintf()是否可用。如果可用,则调用AC_DEFINE宏定义变量HAVE_VPRINTF=1。然后根据检查结果继续处理。如果可用(ac_cv_func_vprintf=yes),则继续检查__doprnt()是否可用。

AC_CHECK_FUNC([vprintf], [AC_DEFINE([HAVE_VPRINTF], [1], [Define if vprintf exists.])])
if test "x$ac_cv_func_vprintf" != xyes; then
    AC_CHECK_FUNC([_doprnt], [AC_DEFINE([HAVE_DOPRNT], [1], [Define if _doprnt exists.])])
fi

AC_CHECK_FUNCS宏检查一组函数(名字用空白符分割)是否可用,对于每个可用的函数,定义变量HAVE_XXX。

如下的例子检查C函数time(), mktime(),和localtime()是否可用。

AC_CHECK_FUNCS(time mktime localtime)

1.14 AC_CHECK_DECL 与 AC_CHECK_DECLS

AC_CHECK_DECL宏检查指定的符号(函数、变量、或常量)是否定义。

如下的例子检查变量_MGRM_PROCESSES是否定义。如果是,则变量minigui_runmode赋值procs。

AC_CHECK_DECL(_MGRM_PROCESSES, minigui_runmode="procs")

AC_CHECK_DECLS宏检查一组符号是否定义。这组符号以逗号分隔。对于每一个符号,如果存在,则定义变量HAVE_DECL_XXX,并赋值为1, 否则赋值为0。其中XXX是符号名。

如下的例子。如果列表中的函数(如malloc)已定义,则定义变量HAVE_DECL_MALLOC=1。

AC_CHECK_DECLS([malloc, realloc, calloc, free])

1.15 AS_HELP_STRING

AS_HELP_STRING宏是用于打印"configure --help"输出中,类似如下的格式化信息。

--with-foo    use foo (default is no)

AS_HELP_STRING有两个参数,对应于信息的左右两边,"--with-foo" 和 "use foo (default is no)"。如下是AS_HELP_STRING对应的例子。

AS_HELP_STRING([--with-foo], [use foo (default is no)])

1.16 AC_ARG_ENABLE

你的软件包可能有些可选的特性。执行configure时,用户可以选择使能或禁用某个特性。

configure --enable-feature=yes

使用AC_ARG_ENABLE宏可以创建一个--enable-XXX选项。四个参数依次是特性名称、提示字符串、用户指定--enable-XXX选项时的动作(yes或no),没指定选项时的动作。

如果用户指定了--enable-XXX选项,则指定的值会保存在变量enableval中。

如下的例子指定了特性debug。如果用户指定了选项,则检查enableval值,如果要求使能选项,则设置变量debug为true,否则设置为false,其他值报告错误;如果没指定选项,设置debug为false。

AC_ARG_ENABLE([debug],
  [--enable-debug Turn on debugging],
  [case "${enableval}" in
     yes) debug = true ;;
     no) debug = false ;;
     *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;;
   esac], 
  [debug = false])

1.17 AC_ARG_WITH

工程可能依赖第三方软件包,这个包是否存在,会导致你的软件的不同行为。执行configure时,可以允许软件的使用者指定是否使用第三方包。

configure --with-foo=yes

使用AC_ARG_WITH宏可以创建一个--with-XXX选项。宏的四个参数依次是第三方包的名称、提示字符串、用户指定--with-XXX选项时的动作(不管是yes,还是no或其他),没指定选项时的动作。

如果用户指定了--with-XXX选项,则指定的值会保存在变量withval中。

如下的例子指定了包名foo,用户指定选项时,设置use_foo变量为$withval,没指定则设置为no。注意,这里用AS_HELP_STRING宏构造了提供格式化的字符串。

AC_ARG_WITH([foo],
    [AS_HELP_STRING([--with-foo], [use foo (default is no)])],
    [use_foo=$withval],
    [use_foo=no])

1.18 AM_CONDITIONAL

AM_CONDITIONAL宏检查指定的条件,并定义变量和赋值。这个变量是在configure运行时赋值的,比如根据用户给configure指定的参数。

下面的例子定义DEBUG变量,并根据AC_ARG_ENABLE宏定义的变量debug赋值。

AC_ARG_ENABLE([debug],
  [--enable-debug Turn on debugging],
  [case "${enableval}" in
     yes) debug = true ;;
     no) debug = false ;;
     *) AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;;
   esac], [debug = false])
AM_CONDITIONAL([DEBUG], [test x$debug = xtrue])

1.19 AC_CONFIG_FILES

AC_CONFIG_FILES宏将模板文件实例化,输出文件。它的参数是用空白符或换行符分割的一组文件名。参数中的文件是输出文件名,它假设模板文件名是输出文件名加后缀.in。

如下面的例子,从模板文件Makefile.in,生成Makefile,从src/Makefile.in生成src/Makefile。这样在Makefile.in修改后,对应的Makefile会相应得到更新。

AC_CONFIG_FILES([Makefile src/Makefile])

1.20 AC_OUTPUT

AC_OUTPUT宏产生config.status,并执行它。config.status负责产生Makefile和其他文件。

AC_OUTPUT

1.21 AC_MSG_CHECKING 与 AC_MSG_RESULT

这两个宏是配对使用的,用于检查某个系统特性。

AC_MSG_CHECKING宏打印出类似"Checking XXX ..."的提示,XXX是是它的参数。AC_MSG_RESULT宏输出检查结果,如yes、no或其他内容。

如下是一个例子:

hb_os_win32=no
AC_MSG_CHECKING([for native Win32])
case "$host" in
  *-*-mingw*)
    hb_os_win32=yes
    ;;  
esac
AC_MSG_RESULT([$hb_os_win32])

它的输出可能是:

Checking for native Win32 ... yes

1.22 AC_MSG_XXX

有一组宏用于打印不同级别的脚本调试信息。

AC_MSG_NOTICE:打印调试信息。
AC_MSG_WARN:打印警告信息,不终止configure运行。
AC_MSG_ERROR:打印错误信息,中止configure运行。
AC_MSG_FAILURE:打印错误信息,写入config.log

如下是AC_MSG_NOTICE宏的例子,它展开enable_doc变量,然后打印字符串。

AC_MSG_NOTICE([build configuration: documentation:${enable_doc}])

2. configure.ac的例子

如下是helloauto工程的布局。其中用[]包括的文件是用autotools生成的文件。configure.ac也可以在autoscan工具生成的configure.scan基础上修改得到。

- helloauto
  ├── src
  │   ├── main.c
  │   ├── Makefile.am
  │   ├── [config.h.in]
  │   └── [config.h]
  ├── configure.ac
  ├── Makefile.am
  └── [configure]

使用的configure.ac如下:

# configure.ac
 
AC_PREREQ([2.69])
AC_INIT([helloauto], [1.0], [[email protected]])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])
 
# Checks for programs.
AC_PROG_CC
AC_PROG_INSTALL
 
# Checks for libraries.
 
# Checks for header files.
AC_CHECK_HEADERS([stdlib.h])
 
# Checks for typedefs, structures, and compiler characteristics.
 
# Checks for library functions.
AC_CONFIG_FILES([Makefile src/Makefile])

AC_OUTPUT

参考文档

官方文档之autoconf宏索引
configure.ac与Makefile.am宏定义说明
pkg-config使用指南

你可能感兴趣的:(【转】GNU autotools(四)编写configure.ac)