Autoconf Notes

Source EN: http://www.gnu.org/software/autoconf/manual/autoconf.html(version 2.68)

CN: http://www.linuxforum.net/books/autoconf.html(version 2.13)

Edition 2.13, for Autoconf version 2.13

    1. 介绍

A physicist, an engineer, and a computer scientist were discussing the 
nature of God. Surely a Physicist, said the physicist, because 
early in the Creation, God made Light; and you know, Maxwell's equations, 
the dual nature of electro-magnetic waves, the relativist consequences... 
An Engineer!, said the engineer, because before making Light,
 God split the Chaos into Land and Water; it takes a hell of 
an engineer to handle that bigamount of mud, and orderly 
separation of solids from liquids... The computer scientist 
shouted: And the Chaos, where do you think it was coming from, hmm?
                                                                          ---Anonymous

对于在C程序中的#ifdef中使用的宏的名字,Autoconf施加了一些限制 (参见预处理器符号索引)。

    1. 创建configure脚本

Autoconf生成的配置脚本通常被称为configure。在运行的时候,configure 创建一些文件,在这些文件中以适当的值替换配置参数。由configure创建的文件有:

  • 一个或者多个`Makefile’文件,在包的每个子目录中都有一个(参见 Makefile中的替换);
  • 有时创建一个C头文件,它的名字可以被配置,该头文件包含一些#define命令 (参见配置头文件);
  • 一个名为`config.status’shell脚本,在运行时,它将重新创建上述文件。 (参见重新创建一个配置);
  • 一个名为`config.cache’shell脚本,它储存了许多测试的运行结果 (参见缓存文件);
  • 一个名为`config.log’的文件,它包含了由编译器生成的许多消息,以便于 在configure出现错误时进行调试。

为了使用Autoconf创建一个configure脚本,你需要编写一个Autoconf的输入文件 `configure.in’并且对它运行autoconf。如果你自行编写了特征测试以补充 Autoconf所提供的测试,你可能还要编写一个名为`aclocal.m4′的文件和一个名为 `acsite.m4′的文件。如果你使用了包含#define指令的C头文件,你可能 还要编写`acconfig.h’,并且你需要与软件包一同发布由Autoconf生成的文件 `config.h.in’

下面是一个说明了在配置中使用的文件是如何生成的图。运行的程序都标以后缀`*’。 可能出现的文件被方括号(`[]’)括起来。autoconfautoheader 还读取安装了的Autoconf宏文件(通过读取`autoconf.m4′)。

在准备发布软件包的过程中使用的文件:

你的源文件 --> [autoscan*] --> [configure.scan] --> configure.in

configure.in --. .------> autoconf* -----> configure
                          +---+
[aclocal.m4] --+ `---.
[acsite.m4] ---' |
                                        +--> [autoheader*] -> [config.h.in]
[acconfig.h] ----. |
                             +-----'
[config.h.top] --+
[config.h.bot] --'

Makefile.in -------------------------------> Makefile.in

在配置软件包的过程中使用的文件:

                                       .-------------> config.cache
configure* ------------+-------------> config.log
                                       |
[config.h.in] -. v .-> [config.h] -.
                         +--> config.status* -+ +--> make*
Makefile.in ---' `-> Makefile ---'
    1. 编写`configure.in’

为了为软件包创建configure脚本,需要编写一个名为`configure.in’ 的文件,该文件包含了对那些你的软件包需要或者可以使用的系统特征进行测试的Autoconf宏的调用。程序autoscan可以为你编写`configure.in’ 开个好头(详情请参见autoscan创建`configure.in’)。

在每个`configure.in’中,必须在进行任何测试之间包含一个对AC_INIT的调用, 并且在结尾处包含一个对AC_OUTPUT的调用(参见创建输出文件)。 此外,有些宏要求其他的宏在它们之前被调用,这是因为它们通过检查某些变量在前面设定的值以决定作些什么。 这些宏在独立的说明中给出(参见现有的测试),而且如果没有 按照顺序调用宏,在生成configure时会向你发出警告。

为了提高一致性,下面是调用Autoconf宏的推荐顺序。通常,在本列表中靠后的项目依赖于表中靠前的项目。 例如,库函数可能受到typedefs和库的影响。

AC_INIT(file)
checks for programs
checks for libraries
checks for header files
checks for typedefs
checks for structures
checks for compiler characteristics
checks for library functions
checks for system services
AC_OUTPUT([file...])

在调用带参数的宏的时候,在宏名和左括号之间不能出现任何空格。如果参数被m4 引用字符`[‘`]’所包含,参数就可以多于一行。如果你有一个长行, 比如说一个文件名列表,你通常可以在行的结尾使用反斜线以便在逻辑上把它与下一行进行连接 (这是由shell实现的,Autoconf对此没有进行任何特殊的处理)。

你可以在文件`configure.in’中添加注释。注释以m4预定义宏dnl 开头,该宏丢弃在下一个新行之前的所有文本。这些注释并不在生成的configure脚本中 出现。例如,把下面给出的行作为文件`configure.in’的开头是有好处的:

dnl Process this file with autoconf to produce a configure script.
    1. autoscan创建`configure.in’

程序autoscan可以帮助你为软件包创建`configure.in’文件。如果在命令行中给出了目录, autoscan就在给定目录及其子目录树中检查源文件,如果没有给出目录,就在当前目录及其子目录树中 进行检查。它搜索源文件以寻找一般的移植性问题并创建一个文件`configure.scan’,该文件就是软件包 的`configure.in’预备版本。

只有在你安装了Perl的情况下才安装autoscanautoscan接受如下选项:

–help
打印命令行选项的概述并且退出。
–macrodir=dir
在目录dir中,而不是在缺省安装目录中寻找数据文件。你还可以把环境变量AC_MACRODIR设置成 一个目录;本选项将覆盖该环境变量。
–verbose
打印它检查的文件名称以及在这些文件中发现的可能感兴趣的符号。它的输出可能很冗长。
–version
打印Autoconf的版本号并且退出。
    1. ifnames列举条件

在为一个软件包编写`configure.in’时,ifnames可以提供一些帮助。它打印出包已经在C预处理条件 中使用的标识符。如果包已经被设置得具备了某些可移植性,该程序可以帮助你找到configure所需要进行 的检查。它可能有助于补足由autoscan生成的`configure.in’中的某些缺陷。 (参见autoscan创建`configure.in’)。

ifnames接受如下选项:

–help
-h
打印命令行选项的概述并且退出。
–macrodir=dir
-m dir
在目录dir中,而不是缺省安装目录中寻找Autoconf宏文件。仅仅被用于获取版本号。 你还可以把环境变量AC_MACRODIR设置成一个目录;本选项将覆盖该环境变量。
–version
打印Autoconf的版本号并且退出。
    1. autoconf创建configure

为了从`configure.in’生成configure,不带参数地运行程序autoconfautoconf用使用Autoconf宏的m4宏处理器处理`configure.in’。 如果你为autoconf提供了参数,它读入给出的文件而不是`configure.in’并且 把配置脚本输出到标准输出而不是configure。如果你给autoconf以参数`-‘, 它将从标准输入,而不是`configure.in’中读取并且把配置脚本输出到标准输出。

autoconf首先读入它们。 而后它在包含了发布的Autoconf宏文件的目录中寻找可能出现的文件`acsite.m4′,并且在当前目录中寻找 可能出现的文件`aclocal.m4′

autoconf接受如下参数:

–help
-h
输出命令行选项的概述并且退出。
–localdir=dir
-l dir
在目录dir中,而不是当前目录中寻找包文件`aclocal.m4′
–macrodir=dir
-m dir
在目录dir中寻找安装的宏文件。你还可以把环境变量AC_MACRODIR设置成 一个目录;本选项将覆盖该环境变量。
–version
打印Autoconf的版本号并且退出。
    1. autoreconf更新configure脚本

autoreconf接受如下选项:

–help
-h
打印命令行选项的概述并且退出。
–force
-f
即使在`configure’脚本和配置头文件比它们的输入文件(`configure.in’,如果出现 了`aclocal.m4′,也包括它)更新的时候,也要重新创建它们。
–localdir=dir
-l dir
autoconfautoheader在目录dir中,而不是在每个包含`configure.in’ 的目录中寻找包文件`aclocal.m4′和(仅指autoheader`acconfig.h’ (但不包括`file.top’`file.bot’)。
–macrodir=dir
-m dir
在目录dir中,而不是缺省安装目录中寻找Autoconf宏文件。你还可以把环境变量 AC_MACRODIR设置成一个目录;本选项将覆盖该环境变量。
–verbose
打印autoreconf运行autoconf(如果适当,还有autoheader) 的每个目录的目录名。
–version
打印Autoconf的版本号并且退出。
    1. 初始化和输出文件

      1. 寻找configure的输入文件

所有configure脚本在作任何其他事情之前都必须调用AC_INIT。此外唯一必须调用的宏是 AC_OUTPUT(参见创建输出文件)。

宏: AC_INIT (unique-file-in-source-dir)
处理所有命令行参数并且寻找源代码目录。unique-file-in-source-dir是一些在包的源代码目录中文件; configure在目录中检查这些文件是否存在以确定该目录是否包含源代码。 人们可能偶尔会用`–srcdir’给出错误的目录;这是一种安全性检查。 详情请参见运行configure脚本

对于需要手工配置或者使用install程序的包来说,虽然在缺省源代码位置在大部分情况 下看起来是正确的,包还是可能需要通过调用AC_CONFIG_AUX_DIR来告诉 configure到那里去寻找一些其他的shell脚本。

宏: AC_CONFIG_AUX_DIR (dir)
在目录dir中使用`install-sh’`config.sub’`config.guess’Cygnus configure配置脚本。它们是配置中使用的辅助文件。dir既可以是绝对路径, 也可以是相对于`srcdir’的相对路径。缺省值是在`srcdir’或者 `srcdir/..’或者`srcdir/../..’中首先找到`install-sh’ 的目录。不对其他文件进行检查,以便使AC_PROG_INSTALL不会自动地发布其他辅助文件。它还要 检查`install.sh’,但因为有些make程序包含了在没有`Makefile’的情况下 从`install.sh’中创建`install’的规则,所以那个名字过时了。
      1. 创建输出文件

每个Autoconf生成的configure脚本必须以对AC_OUTPUT的调用结尾。它是一个创建 作为配置结果的`Makefile’以及其他一些可能的文件的宏。此外唯一必须调用的宏是AC_INIT (参见寻找configure的输入文件

宏: AC_OUTPUT ([file… [, extra-cmds [, init-cmds]]])
创建输出文件。在`configure.in’的末尾调用本宏一次。参数file…是一个以空格分隔的输出文件 的列表;它可能为空。本宏通过从一个输入文件(缺省情况下名为`file.in’)中复制,并替换输出 变量的值以创建每个给出的`file’。 关于使用输出变量的详情,请参见Makefile中的替换。 关于创建输出变量的详情,请参见设定输出变量。 如果输出文件所在的目录不存在,本宏将创建该目录(但不会创建目录的父目录)。通常,`Makefile’是按照这种 方式创建的,但其他文件,例如`.gdbinit’,也可以这样创建。
如果调用了AC_CONFIG_HEADERAC_LINK_FILES或者AC_CONFIG_SUBDIRS,本宏 也将创建出现在它们的参数中的文件。
一个典型的对AC_OUTPUT调用如下:
AC_OUTPUT(Makefile src/Makefile man/Makefile X/Imakefile)
你可以通过在file之后添加一个用冒号分隔的输入文件列表以自行设定输入文件名。例如:
AC_OUTPUT(Makefile:templates/top.mk lib/Makefile:templates/lib.mk)
AC_OUTPUT(Makefile:templates/vars.mk:Makefile.in:templates/rules.mk)
这样做可以使得你的文件名能够被MS-DOS接受,或者可以把模板文件(boilerplate)添加到文件的开头或者结尾。
如果你给出了extra-cmds,那么这些命令将被插入到`config.status’中以便在`config.status’ 完成了其他的所有处理之后运行extra-cmds。如果给出了init-cmds,它们就被插入 extra-cmds之前,并且在configure中将对它们进行shell变量、命令和反斜线替换。你可以用 init-cmds把变量从configure中传递到extra-cmds。如果调用了 AC_OUTPUT_COMMANDS,在其中给出的命令将紧贴在由本宏给出的命令之前运行。
宏: AC_OUTPUT_COMMANDS (extra-cmds [, init-cmds])
指定在`config.status’末尾运行的附加的shell命令,以及用于初始化来自于configure 的所有变量的shell命令。本宏可以被调用多次。下面是一个不太实际的例子:
fubar=27
AC_OUTPUT_COMMANDS([echo this is extra $fubar, and so on.], fubar=$fubar)
AC_OUTPUT_COMMANDS([echo this is another, extra, bit], [echo init bit])

如果你在子目录中运行make,你应该通过使用make变量MAKE来运行它。 make的大部分版本把MAKE设置成make的程序名以及它所需要的任何选项。 (但许多版本并没有把在命令行中设定的变量的值包括进来,因此它们没有被自动地传递。)一些老版本的 make并不设定这个变量。以下的宏使你可以在这些版本上使用它。

宏: AC_PROG_MAKE_SET
如果make预定义了变量MAKE,把输出变量SET_MAKE定义为空。否则,把 SET_MAKE定义成`MAKE=make’。为SET_MAKE调用AC_SUBST

为了使用这个宏,在每个其他的、运行MAKE的目录中的`Makefile.in’添加一行:

@SET_MAKE@
    1. Makefiles中的替换

发布版本中每个包含了需要被编译或者被安装的文件的目录都应该含有一个文件`Makefile.in’configure将利用它在那个目录中创建一个`Makefile’。 为了创建`Makefile’configure进行一个简单的变量替换:用configure `@variable@’选取的值,在`Makefile.in’中对它们进行替换。 按照这种方式被替换到输出文件中的变量被称为输出变量。在configure中,它们是普通 的shell变量。为了让configure把特殊的变量替换到输出文件中,必须把那个变量的名字作为调用 AC_SUBST的参数。其他变量的任何`@variable@’都保持不变。关于 使用AC_SUBST创建输出变量的详情,请参见设定输出变量

      1. 预定义输出变量

有些输出变量是由Autoconf宏预定义的。一部分Autoconf宏设置一些附加的输出变量,这些变量在对这些宏的描述 中被说明。关于输出变量的完整列表,参见输出变量索引。下面是每个预 定义变量所包含的内容。关于变量名以`dir’结尾的变量,参见GNU编码标准中的 `为安装目录而提供的变量

变量: bindir
用于安装由用户运行的可执行文件的目录。
变量: configure_input
一个用于说明文件是由configure自动生成的,并且给出了输入文件名的注释。 AC_OUTPUT在它创建的每个`Makefile’文件的开头添加一个包括了这个变量的注释行。 对于其他文件,你应该在每个输入文件开头处的注释中引用这个变量。例如,一个输入shell脚本应该以如下 行开头:
#! /bin/sh
# @configure_input@
这一行的存在也提醒了人们在编辑这个文件之后需要用configure进行处理以使用它。
变量: datadir
用于安装只读的与结构无关的数据的目录。
变量: exec_prefix
与结构有关的文件的安装前缀。
变量: includedir
用于安装C头文件的目录。
变量: infodir
用于安装Info格式文档的目录。
变量: libdir
用于安装目标代码库的目录。
变量: libexecdir
用于安装由其他程序运行的可执行文件的目录。
变量: localstatedir
用于安装可以被修改的单机数据的目录。
变量: mandir
用于安装man格式的文档的顶层目录。
变量: oldincludedir
用于安装由非gcc编译器使用的C头文件的目录。
变量: prefix
与结构无关的文件的安装前缀。
变量: sbindir
用于安装由系统管理员运行的可执行文件的目录。
变量: sharedstatedir
用于安装可以修改的、与结构无关的数据的目录。
变量: srcdir
包含了由`Makefile’使用的源代码的目录。
变量: sysconfdir
用于安装只读的单机数据的目录。
变量: top_srcdir
包的顶层源代码目录。在目录的顶层,它与srcdir相同。
变量: CFLAGS
C编译器提供的调试和优化选项。如果在运行configure时,没有在环境中设置它,就在你 调用AC_PROG_CC的时候设置它的缺省值(如果你没有调用AC_PROG_CC,它就为空)。 configure在编译程序以测试C的特征时,使用本变量。
变量: CPPFLAGS
C预处理器和编译器提供头文件搜索目录选项(`-Idir’)以及其他各种选项。如果在运行 configure时,在环境中没有设置本变量,缺省值就是空。configure在编译或者预处理 程序以测试C的特征时,使用本变量。
变量: CXXFLAGS
C++编译器提供的调试和优化选项。如果在运行configure时,没有在环境中设置本变量,那么 就在你调用AC_PROG_CXX时设置它的缺省值(如果你没有调用AC_PROG_CXX,它就为空)。 configure在编译程序以测试C++的特征时,使用本变量。
变量: FFLAGS
Fortran 77编译器提供的调试和优化选项。如果在运行configure时,在环境中没有设置本变量,那么它的 缺省值就在你调用AC_PROG_F77时被设置(如果你没有调用AC_PROG_F77,它就为空)。 configure在编译程序以测试Fortran 77的特征时,使用本变量。
变量: DEFS
传递给C编译器的`-D’选项。如果调用了AC_CONFIG_HEADERconfigure就用 `-DHAVE_CONFIG_H’代替`@DEFS@’(参见配置头文件)。 在configure进行它的测试时,本变量没有被定义,只有在创建输出文件时候才定义。关于如何检查从前的 测试结果,请参见设定输出变量
变量: LDFLAGS
为连接器提供的Stripping`-s’)选项和其他各种选项。如果在运行configure时, 在环境中没有设置本变量,它的缺省值就是空。 configure在连接程序以测试C的特征时使用本变量。
变量: LIBS
传递给连接器的`-l’`-L’选项。
      1. 创建目录

为了支持VPATH,每个`Makefile.in’文件都应该包含下列两行:

srcdir = @srcdir@
VPATH = @srcdir@

不要把VPATH设置成其他变量的值,比如说`VPATH = $(srcdir)’,这是因为 某些版本的make并不对VPATH的值进行变量替换。

      1. 自动地重新创建

你可以在包的顶层目录中的`Makefile.in’文件中添加如下的规则,以使得在你更新了配置文件之后 可以自动地更新配置信息。这个例子包括了所有可选的文件,例如`aclocal.m4′和那些与配置头文件 有关的文件。从`Makefile.in’规则中忽略所有你的所不需要的文件。

因为VPATH机制的限制,应该包含`${srcdir}/’前缀。

在重新创建不改变`config.h.in’`config.h’的内容的情况下,就不会改变这两个文件的时间标记 ,因此需要`stamp-‘文件。这个特征避免了不必要的重新编译工作。你应该把文件`stamp-h.in’ 包含在你的包的发布中,以便make能够把`config.h.in’看作是更新了的文件。在一些 老的BSD系统中,touch或者任何可能导致空文件的命令不会更改时间标记,所以使用诸如echo 之类的命令。

${srcdir}/configure: configure.in aclocal.m4
        cd ${srcdir} && autoconf

# autoheader might not change config.h.in, so touch a stamp file.
${srcdir}/config.h.in: stamp-h.in
${srcdir}/stamp-h.in: configure.in aclocal.m4 acconfig.h \
    config.h.top config.h.bot
        cd ${srcdir} && autoheader
        echo timestamp > ${srcdir}/stamp-h.in

config.h: stamp-h
stamp-h: config.h.in config.status
        ./config.status

Makefile: Makefile.in config.status
        ./config.status

config.status: configure
        ./config.status --recheck

此外,你应该把`echo timestamp > stamp-h’作为extra-cmds参数传递给AC_OUTPUT, 以便`config.status’能够确认`config.h’是更新了的。关于AC_OUTPUT的详情,请参见 创建输出文件

    1. 配置头文件

在包测试的C预处理器符号比较多的时候,用于把`-D’传递给编译器的命令行就会变得很长。 这导致了两个问题。一个是通过观察寻找make输出中的错误变得困难了。更严重的是,命令行 可能超过某些操作系统的长度限制。作为把`-D’选项传递给编译器的替代办法,configure 脚本可以创建一个包含了`#define’指令的C头文件。宏AC_CONFIG_HEADER 选择了这种输出。它应该在AC_INIT之后立即调用。

包应该在引入其他任何头文件之前`#include’配置头文件,以防止出现声明中的不一致性 (例如,配置头文件可能重定义了const)。使用`#include <config.h>’ 并且把选项`-I.’(或者是`-I..’;或者是任何包含`config.h’ 的目录)传递给C编译器,而不是使用`#include “config.h”‘。按照这种方式,即使源代码 自行进行配置(可能是创建发布版本),其他创建目录也可以在没有找到`config.h’的情况下, 从源代码目录进行配置。

宏: AC_CONFIG_HEADER (header-to-create …)
使得AC_OUTPUT创建出现在以空格分隔的列表header-to-create中的文件, 以包含C预处理器#define语句,并在生成的文件中用`-DHAVE_CONFIG_H’ ,而不是用DEFS的值,替换`@DEFS@’。常用在header-to-create 中的文件名是`config.h’
如果header-to-create给出的文件已经存在并且它的内容和AC_OUTPUT将要生成的 内容完全一致,这些文件就保持不变。这样做就使得对配置的某些修改不会导致对依赖于头文件的目标文件进行 不必要的重新编译。
通常输入文件被命名为`header-to-create.in’;然而,你可以通过在header-to-create 之后添加由冒号分隔的输入文件列表来覆盖原输入文件名。 例:
AC_CONFIG_HEADER(defines.h:defines.hin)
AC_CONFIG_HEADER(defines.h:defs.pre:defines.h.in:defs.post)
这样做使得你的文件名能够被MS-DOS所接受,或者可以把模板(boilerplate)添加到文件的开头和/或结尾。
      1. 配置头文件模板

你的发布版本应该包含一个如你所望的最终的头文件那样的模板文件,它包括注释、以及#define 语句的缺省值。例如,假如你的`configure.in’进行了下列调用:

AC_CONFIG_HEADER(conf.h)
AC_CHECK_HEADERS(unistd.h)

那么你就应该在`conf.h.in’中包含下列代码。 在含有`unistd.h’的系统中,configure应该把0改成1。在其他系统中,这一行将保持不变。

/* Define as 1 if you have unistd.h. */
#define HAVE_UNISTD_H 0

如果你的代码使用#ifdef而不是#if来测试配置选项,缺省值就可能是取消对一个变量 的定义而不是把它定义成一个值。在含有`unistd.h’的系统中,configure将修改读入的第二行 `#define HAVE_UNISTD_H 1′。在其他的系统中,(在系统预定义了那个符号的情况下) configure将以注释的方式排除这一行。

/* Define if you have unistd.h. */
#undef HAVE_UNISTD_H
      1. autoheader创建`config.h.in’

程序autoheader可以创建含有C`#define’语句的模板文件以供configure使用。 如果`configure.in’调用了AC_CONFIG_HEADER(file)autoheader就创建 `file.in’;如果给出了多文件参数,就使用第一个文件。否则,autoheader就创建 `config.h.in’

如果你为autoheader提供一个参数,它就使用给出的文件而不是`configure.in’,并且把头文件输出 到标准输出中去,而不是输出到`config.h.in’。如果你把`-‘作为参数提供给autoheader ,它就从标准输入中,而不是从`configure.in’中读出,并且把头文件输出到标准输出中去。

autoheader扫描`configure.in’并且找出它可能要定义的C预处理器符号。它从一个名为 `acconfig.h’的文件中复制注释、#define#undef语句,该文件与Autoconf一同发布 并且一同安装。如果当前目录中含有`acconfig.h’文件,它也会使用这个文件。如果你用AC_DEFINE 定义了任何附加的符号,你必须在创建的那个`acconfig.h’文件中包含附加的符号。对于由 AC_CHECK_HEADERSAC_CHECK_FUNCSAC_CHECK_SIZEOF或者 AC_CHECK_LIB定义的符号,autoheader生成注释和#undef语句,而不是从一个 文件中复制它们,这是因为可能的符号是无限的。

autoheader创建的文件包含了大部分#define#undef语句,以及相关的注释。 如果`./acconfig.h’包含了字符串`@TOP@’autoheader就把在包含`@TOP@’ 的行之前的所有行复制到它生成的文件的开头。相似地,如果`./acconfig.h’包含了字符串`@BOTTOM@’autoheader就把那一行之后的所有行复制到它生成的文件的末尾。这两个字符串的任何一个都可以被忽略, 也可以被同时忽略。

autoheader接受如下选项:

–help
-h
打印对命令行选项的概述并且退出。
–localdir=dir
-l dir
在目录dir中,而不是在当前目录中,寻找包文件`aclocal.m4′`acconfig.h’ (但不包括`file.top’`file.bot’)。
–macrodir=dir
-m dir
在目录dir中寻找安装的宏文件和`acconfig.h’。你还可以把环境变量AC_MACRODIR 设置成一个目录;本选项将覆盖该环境变量。
–version
打印Autoconf的版本号并且退出。
    1. 在子目录中配置其它包

在大多数情况下,调用AC_OUTPUT足以在子目录中生成`Makefile’。然而,控制了多于一个 独立包的configure脚本可以使用AC_CONFIG_SUBDIRS来为每个子目录中的其他包运行 configure脚本。

宏: AC_CONFIG_SUBDIRS (dir …)
使得AC_OUTPUT在每个以空格分隔的列表中给出的子目录dir中运行configure。 如果没有发现某个给出的dir,不会作为错误报告,所以一个configure脚本可以配置一个 大的源代码树中出现的任何一个部分。如果在给出的dir中包含了`configure.in’,但没有包含 configure,就使用由AC_CONFIG_AUXDIR找到的Cygnus configure脚本。
    1. 缺省的前缀

在缺省状态下,configure把它所安装的文件的前缀设置成`/usr/local’configure的用户可以通过选项`–prefix’`–exec-prefix’选择一个不同的前缀。 有两种方式修改缺省的行为:在创建configure时,和运行configure时。

有些软件包在缺省情况下可能需要安装到`/usr/local’以外的目录中。为此,使用宏AC_PREFIX_DEFAULT

宏: AC_PREFIX_DEFAULT (prefix)
把缺省的安装前缀设置成prefix,而不是`/usr/local’

对于用户来说,让configure根据它们已经安装的相关程序的位置来猜测安装前缀,可能会带来方便。如果你 希望这样做,你可以调用AC_PREFIX_PROGRAM

宏: AC_PREFIX_PROGRAM (program)
如果用户没有给出安装前缀(使用选项`–prefix’),就按照shell的方式,在PATH中寻找 program,从而猜出一个安装前缀。如果找到了program,就把前缀设置成包含program 的目录的父目录;否则,就不改变在`Makefile.in’中给定的前缀。例如,如果programgcc,并且PATH包括了`/usr/local/gnu/bin/gcc’,就把前缀设置为 `/usr/local/gnu’
    1. configure中的版本号

宏:AC_PREREQ (version)
确保使用的是足够新的Autoconf版本。如果用于创建configureAutoconf的版本比version 要早,就在标准错误输出打印一条错误消息并不会创建configure。例如:
AC_PREREQ(1.8)
宏:AC_REVISION(revision-info)
把删除了任何美元符或者双引号的修订标记(revision stamp)复制到configure脚本中。 本宏使得你的从`configure.in’传递到configure的修订标记不会在你提交(check inconfigure的时候被RCS或者CVS修改。你可以容易地决定一个特定的configure 对应与`configure.in’的哪个修订版。
把本宏放在AC_INIT之前是个好主意,它可以使修订号接近`configure.in’configure 的开头。为了支持你这样做,AC_REVISION就像configure通常作的那样,以 `#! /bin/sh’开始它的输出。
例如,在`configure.in’中这一行为:
AC_REVISION($Revision: 1.30 $)dnl
configure中产生了:
#! /bin/sh
# From configure.in Revision: 1.30

现有的测试

    1. 对程序的选择

      1. 对特定程序的检查

宏:AC_DECL_YYTEXT
如果yytext的类型是`char *’而不是`char []’,就定义YYTEXT_POINTER。 本宏还把输出变量LEX_OUTPUT_ROOT设置由lex生成的文件名的基文件名;通常是`lex.yy’, 但有时是其他的东西。它的结果依使用lex还是使用flex而定。
宏: AC_PROG_AWK
按顺序查找mawkgawknawkawk,并且把输出变量AWK 的值设置成第一个找到的程序名。首先寻找mawk是因为据说它是最快的实现。
宏: AC_PROG_CC
确定C的编译器。如果在环境中没有设定CC,就查找gcc,如果没有找到,就使用cc。 把输出变量CC设置为找到的编译器的名字。
如果要使用GNU C编译器,把shell变量GCC设置为`yes’,否则就设置成空。如果还没有设置输出变量 CFLAGS,就为GNU C编译器把CFLAGS设置成`-g -O2′(在GCC不接受`-g’ 的系统中就设置成`-O2′),为其他编译器把CFLAGS设置成`-g’
如果被使用的C编译器并不生成可以在configure运行的系统上运行的可执行文件,就把shell变量 cross_compiling设置成`yes’,否则设置成`no’。换句话说,它检查创建系统类型 是否与主机系统类型不同(目标系统与本测试无关)。关于对交叉编译的支持,参见手工配置
宏: AC_PROG_CC_C_O
对于不能同时接受`-c’`-o’选项的C编译器,定义NO_MINUS_C_MINUS_O
宏:AC_PROG_CPP
把输出变量CPP设置成运行C预处理器的命令。如果`$CC -E’不能工作,就使用`/lib/cpp’。 只有对以`.c’为扩展名的文件运行CPP才是可以移植的(portable)。
如果当前语言是C(参见对语言的选择),许多特定的测试宏通过调用AC_TRY_CPPAC_CHECK_HEADERAC_EGREP_HEADER或者AC_EGREP_CPP,间接地使用了CPP的值。
宏: AC_PROG_CXX
确定C++编译器。检查环境变量CXX或者CCC(按照这个顺序)是否被设置了;如果设置了,就把输出变量 CXX设置成它的值。否则就搜索类似名称(c++g++gccCCcxxcc++)的C++编译器。如果上述测试都失败了,最后的办法就是把CXX设置成 gcc
如果使用GNU C++编译器,就把shell变量GXX设置成`yes’,否则就设置成空。 如果还没有设置输出变量CXXFLAGS,就为GNU C++编译器把CXXFLAGS设置成`-g -O2′ (在G++不接受`-g’的系统上设置成`-O2′),或者为其他编译器把CXXFLAGS设置成 `-g’.
如果使用的C++编译器并不生成在configure运行的系统上运行的可执行文件,就把shell变量cross_compiling 设置成`yes’,否则就设置成`no’。换句话说,它检查创建系统类型是否与主机系统类型不同 (目标系统类型与本测试无关)。关于对交叉编译的支持,参见手工配置
宏: AC_PROG_CXXCPP
把输出变量CXXCPP设置成运行C++预处理器的命令。如果`$CXX -E’不能工作,使用`/lib/cpp’。 只有对以`.c’`.C’或者`.cc’为扩展名的文件运行CPP才是可以移植的(portable)。
如果当前语言是C++(参见对语言的选择),许多特定的测试宏通过调用 AC_TRY_CPPAC_CHECK_HEADERAC_EGREP_HEADER或者AC_EGREP_CPP, 间接地使用了CXXCPP的值。
宏: AC_PROG_F77
确定Fortran 77编译器。如果在环境中没有设置F77,就按顺序检查g77f77f2c。把输出变量F77设置成找到的编译器的名字。
如果使用g77GNU Fortran 77编译器),那么AC_PROG_F77将把shell变量G77设置成 `yes’,否则就设置成空。如果在环境中没有设置输出变量FFLAGS,那么就为g77 FFLAGS设置成`-g -02′(或者在g77不支持`-g’的时候设置成 `-O2′)。否则,就为所有其它的Fortran 77编译器把FFLAGS设置成`-g’
宏: AC_PROG_F77_C_O
测试Fortran 77编译器是否能够同时接受选项`-c’`-o’,并且如果不能同时接受的话,就 定义F77_NO_MINUS_C_MINUS_O
宏: AC_PROG_GCC_TRADITIONAL
如果在没有给出`-traditional’的情况下,用GNU Cioctl不能正确地工作,就把 `-traditional’添加到输出变量CC中。这通常发生在旧系统上没有安装修正了的头文件 的时候。因为新版本的GNU C编译器在安装的时候自动地修正了头文件,它就不是一个普遍的问题了。
宏: AC_PROG_INSTALL
如果在当前PATH中找到了一个与BSD兼容的install程序,就把输出变量INSTALL设置 成到该程序的路径。否则,就把INSTALL设置成`dir/install-sh -c’,检查由 AC_CONFIG_AUX_DIR指明的目录(或者它的缺省目录)以确定dir(参见 创建输出文件)。本宏还把变量INSTALL_PROGRAMINSTALL_SCRIPT 设置成`${INSTALL}’,并且把INSTALL_DATA设置成`${INSTALL} -m 644′
本宏忽略各种已经确认的不能工作的install程序。为了提高速度,它更希望找到一个C程序而不是shell脚本。 除了`install-sh’,它还能够使用`install.sh’,但因为有些make含有一条在没有 `Makefile’的情况下,从`install.sh’创建`install’的规则,所以这个名字过时了。
宏:AC_PROG_LEX
如果找到了flex,就把输出变量LEX设置成`flex’,并且在flex库在标准位置的时候, 把LEXLIB设置成`-lfl’。否则,就把LEX设置成`lex’并且把 LEXLIB设置成`-ll’
宏: AC_PROG_LN_S
如果`ln -s’能够在当前文件系统中工作(操作系统和文件系统支持符号连接),就把输出变量 LN_S设置成`ln -s’,否则就把它设置成`ln’
如果连接出现在其他目录而不是在当前目录中,它的含义依赖于是使用了`ln’,还是使用了`ln -s’。 为了用`$(LN_S)’安全地创建连接,既可以找到正在使用的形式并且调整参数,也可以总是在创建连接的 目录中调用ln
换句话说,它不能像下面那样工作:
$(LN_S) foo /x/bar
而是要:
(cd /x && $(LN_S) foo bar)
宏:AC_PROG_RANLIB
如果找到了ranlib,就把输出变量RANLIB设置成`ranlib’,否则就设置成 `:’(什么也不作)。
宏: AC_PROG_YACC
如果找到了bison,就把输出变量YACC设置成`bison -y’。 否则,如果找到了byacc。就把YACC设置成`byacc’。否则, 就把YACC设置成`yacc’
      1. 对普通程序和文件的检查

这些宏用于寻找没有包含在特定程序测试宏中的程序。如果你除了需要确定程序是否存在,还需要检测程序的行为,你就 不得不为它编写你自己的测试了(参见编写测试)。在缺省情况下,这些宏使用 环境变量PATH。如果你需要检查可能不会出现在PATH中的程序,你可能要按照下面的方式 给出修改了的路径:

AC_PATH_PROG(INETD, inetd, /usr/libexec/inetd,
  $PATH:/usr/libexec:/usr/sbin:/usr/etc:etc)
宏: AC_CHECK_FILE (file [, action-if-found [, action-if-not-found]])
检查文件file是否出现在本地系统中。如果找到了,就执行action-if-found。否则,就在给出了 action-if-not-found的时候执行action-if-not-found
宏: AC_CHECK_FILES (files[, action-if-found [, action-if-not-found]])
为每个在files中给出的文件运行AC_CHECK_FILE。并且为每个找到的文件定义 `HAVEfile’,定义成1
宏: AC_CHECK_PROG (variable, prog-to-check-for, value-if-found [, value-if-not-found [, path, [ reject ]]])
检查程序prog-to-check-for是否存在于PATH之中。如果找到了,就把变量 variable设置成value-if-found,否则就在给出了value-if-not-found的时候 把variable设置成它。即使首先在搜索路径中找到reject(一个绝对文件名),本宏也会忽略它; 在那种情况下,用找到的prog-to-check-for,不同于reject的绝对文件名来设置variable。 如果variable已经被设置了,就什么也不作。为variable调用AC_SUBST
宏: AC_CHECK_PROGS (variable, progs-to-check-for [, value-if-not-found [, path]])
PATH中寻找每个出现在以空格分隔的列表progs-to-check-for中的程序。 如果找到了,就把variable设置成那个程序的名字。否则,继续寻找列表中的下一个程序。如果列表 中的任何一个程序都没有被找到,就把variable设置成value-if-not-found;如果没有 给出value-if-not-foundvariable的值就不会被改变。为variable调用 AC_SUBST
宏: AC_CHECK_TOOL (variable, prog-to-check-for [, value-if-not-found [, path]])
除了把AC_CANONICAL_HOST确定的主机类型和破折号作为前缀之外,类似于AC_CHECK_PROG, 寻找prog-to-check-for(参见获取规范的系统类型)。 例如,如果用户运行`configure –host=i386-gnu’,那么下列调用:
AC_CHECK_TOOL(RANLIB, ranlib, :)
`i386-gnu-ranlib’PATH中存在的时候,就把RANLIB设置成`i386-gnu-ranlib’, 或者当`ranlib’PATH中存在的时候,就把RANLIB设置成`ranlib’, 或者在上述两个程序都不存在的时候,把RANLIB设置成`:’
宏: AC_PATH_PROG (variable, prog-to-check-for [, value-if-not-found [, path]])
类似于AC_CHECK_PROG,但在找到prog-to-check-for的时候,把variable设置 成prog-to-check-for的完整路径。
宏: AC_PATH_PROGS (variable, progs-to-check-for [, value-if-not-found [, path]])
类似于AC_CHECK_PROGS,但在找到任何一个progs-to-check-for的时候,把variable 设置成找到的程序的完整路径。
    1. 库文件

下列的宏检查某些CC++或者Fortran 77库文件是否存在。

宏: AC_CHECK_LIB (library, function [, action-if-found [, action-if-not-found [, other-libraries]]])
依赖于当前的语言(参见对语言的选择),试图通过检查一个测试程序是否可以和 库library进行连接以获取CC++或者Fortran 77函数function,从而确认函数function 是可以使用的。library是库的基本名字;例如,为了检查`-lmp’,就把`mp’作为 参数library
action-if-found是一个在与库成功地进行了连接的时候运行的shell命令列表; action-if-not-found是一个在与库的连接失败的时候运行的shell命令列表。 如果没有给出action-if-found,缺省的动作就是把`-llibrary’添加到 LIBS中,并且定义`HAVE_LIBlibrary’(全部使用大写字母)。
如果与library的连接导致了未定义符号错误(unresolved symbols),而这些错误可以通过与其他库的连接来解决, 就把这些库用空格分隔,并作为other-libraries参数给出:`-lXt -lX11′。否则,本宏 对library是否存在的检测将会失败,这是因为对测试程序的连接将总是因为含有未定义符号错误而失败。
宏: AC_HAVE_LIBRARY (library, [, action-if-found [, action-if-not-found [, other-libraries]]])
本宏等价于function参数为main的,对AC_CHECK_LIB的调用。 此外,library可以写作`foo’`-lfoo’或者`libfoo.a’。 对于以上任一种形式,编译器都使用`-lfoo’。但是,library不能是一个shell变量; 它必须是一个文字名(literal name)。本宏是一个过时的宏。
宏: AC_SEARCH_LIBS (function, search-libs [, action-if-found [, action-if-not-found [, other-libraries]]])
如果function还不可用,就寻找一个定义了function的库。这等同于首先不带库调用 AC_TRY_LINK_FUNC,而后为每个在search-libs中列举的库调用AC_TRY_LINK_FUNC
如果找到了函数,就运行action-if-found。否则运行action-if-not-found
如果与库library的连接导致了未定义符号错误,而这些错误可以通过与附加的库进行连接来解决,就把这些库 用空格分隔,并作为other-libraries参数给出:`-lXt -lX11′。否则,本宏对function 是否存在的检测将总是失败,这是因为对测试程序的连接将总是因为含有未定义符号错误而失败。
宏: AC_SEARCH_LIBS (function, search-libs[, action-if-found [, action-if-not-found]])
本宏等价于为每个在search-libs中列举的库调用一次AC_TRY_LINK_FUNC。为找到的第一个含有 function的库,把`-llibrary’添加到LIBS中,并且执行 action-if-found。否则就执行action-if-not-found
    1. 库函数

      1. 对特定函数的检查

这些宏用于检测特定的C函数它们是否存在,以及在某些情况下,当给出了特定的参数时,它们是如何响应的。

宏: AC_FUNC_ALLOCA
检测如何获得alloca。本宏试图通过检查`alloca.h’或者预定义C预处理器宏 __GNUC___AIX来获得alloca的内置(builtin)版本。 如果本宏找到了`alloca.h’,它就定义HAVE_ALLOCA_H
如果上述尝试失败了,本宏就在标准C库中寻找函数。如果下列任何方法成功了,本宏就定义HAVE_ALLOCA。 否则,它把输出变量ALLOCA设置成`alloca.o’并且定义C_ALLOCA (这样程序就可以周期性地调用`alloca(0)’以进行垃圾的收集)。本变量是从LIBOBJS中 分离出来的,因此在只有一部分程序使用LIBOBJS中的代码时,多个程序就可以不必创建实际的库而 共享ALLOCA的值。
使用alloca的源文件应该以如下一段代码开头,以正确地声明它。在某些AIX版本中,对alloca 的声明必须在除了注释和预处理指令之前的任何东西之前出现。#pragma指令被缩进(indented),以便让 预标准C编译器(pre-ANSI C compiler)忽略它,而不是导致错误(choke on it)。
/* AIX requires this to be the first thing in the file. */
#ifndef __GNUC__
# if HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifdef _AIX
 #pragma alloca
# else
# ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca ();
# endif
# endif
# endif
#endif
宏:AC_FUNC_CLOSEDIR_VOID
如果函数closedir不返回有意义的值,就定义CLOSEDIR_VOID。否则,调用者就应该 把它的返回值作为错误指示器来进行检查。
宏:AC_FUNC_FNMATCH
如果可以使用fnmatch函数,并且能够工作(不象SunOS 5.4中的fnmatch那样), 就定义HAVE_FNMATCH
宏:AC_FUNC_GETLOADAVG
检查如何才能获得系统平均负载。如果系统含有getloadavg函数,本宏就定义HAVE_GETLOADAVG, 并且把为了获得该函数而需要的库添加到LIBS中。

否则,它就把`getloadavg.o’添加到输出变量LIBOBJS之中,并且可能定义几个其他的C预处理器 宏和输出变量:

  1. 如果在相应的系统中,就根据系统类型定义宏SVR4DGUXUMAX或者UMAX4_3
  2. 如果它找到了`nlist.h’,就定义NLIST_STRUCT
  3. 如果结构`struct nlist’含有成员`n_un’,就定义NLIST_NAME_UNION
  4. 如果在编译`getloadavg.c’时定义了LDAV_PRIVILEGED,为了使getloadavg能够 工作,程序就必须特殊地安装在系统中,并且本宏定义GETLOADAVG_PRIVILEGED
  5. 本宏设置输出变量NEED_SETGID。如果需要进行特别的安装,它的值就是`true’,否则 值就是`false’。如果NEED_SETGID`true’,本宏把KMEM_GROUP 设置成将拥有被安装的程序的组(group)的名字。
宏: AC_FUNC_GETMNTENT
Irix 4PTXUnixware在库`sun’`seq’`gen’中分别查找getmntent函数。 那么,如果可以使用getmntent,就定义HAVE_GETMNTENT
宏: AC_FUNC_GETPGRP
如果getpgrp不接受参数(POSIX.1版),就定义GETPGRP_VOID。否则,它就是一个把 进程ID作为参数的BSD版本。本宏根本不检查getpgrp是否存在;如果你需要检查它的存在性,就首先为 getpgrp函数调用AC_CHECK_FUNC
宏: AC_FUNC_MEMCMP
如果不能使用memcmp函数,或者不能处理8位数据(就像SunOS 4.1.3中的那样),就把`memcmp.o’ 添加到输出变量LIBOBJS中去。
宏: AC_FUNC_MMAP
如果函数mmap存在并且能够正确地工作,就定义HAVE_MMAP。只检查已经映射(already-mapped) 的内存的私有固定映射(private fixed mapping
宏: AC_FUNC_SELECT_ARGTYPES
确定函数select的每个参数的正确类型,并且把这些类型分别定义成SELECT_TYPE_ARG1SELECT_TYPE_ARG234SELECT_TYPE_ARG5SELECT_TYPE_ARG1的缺省值 是`int’SELECT_TYPE_ARG234的缺省值是`int *’SELECT_TYPE_ARG5的缺省值是`struct timeval *’
宏: AC_FUNC_SETPGRP
如果setpgrp不接受参数(POSIX.1版),就定义SETPGRP_VOID。否则,该函数就是一个 把两个进程ID作为参数的BSD版本。本宏并不检查函数setpgrp是否存在;如果你需要检查该函数的存在 性,就首先为setpgrp调用AC_CHECK_FUNC
宏: AC_FUNC_SETVBUF_REVERSED
如果函数setvbuf的第二个参数是缓冲区的类型并且第三个参数是缓冲区指针,而不是其他形式, 就定义SETVBUF_REVERSED。这是在System V3版以前的情况。
宏: AC_FUNC_STRCOLL
如果函数strcoll存在并且可以正确地工作,就定义HAVE_STRCOLL。 由于有些系统包含了错误定义的strcoll,这时就不应该使用strcoll, 因此本宏要比`AC_CHECK_FUNCS(strcoll)’多作一些检查。
宏: AC_FUNC_STRFTIME
对于SCO UNIX,在库`intl’中查找strftime。而后,如果可以使用strftime, 就定义HAVE_STRFTIME
宏: AC_FUNC_UTIME_NULL
如果`utime(file, NULL)’file的时间标记设置成现在,就定义 HAVE_UTIME_NULL
宏: AC_FUNC_VFORK
如果找到了`vfork.h’,就定义HAVE_VFORK_H。如果找不到可以工作的vfork, 就把vfork定义成fork。本宏检查一些已知的vfork实现中的错误 并且认为如果vfork的实现含有任何一个错误,系统就不含有可以工作的vfork。 由于子进程很少改变它们的信号句柄(signal handler),所以如果子进程的signal调用(invocation) 修改了父进程的信号句柄,将不会被当作实现的错误。
宏: AC_FUNC_VPRINTF
如果找到了vprintf,就定义HAVE_VPRINTF。否则,如果找到了_doprnt, 就定义HAVE_DOPRNT。(如果可以使用vprintf,你就可以假定也可以使用vfprintf vsprintf。)
宏: AC_FUNC_WAIT3
如果找到了wait3并且该函数填充它的第三个参数的内容(`struct rusage *’), 就定义HAVE_WAIT3。在HP-UX中,该函数并不这样做。
      1. 对普通函数的检查

这些宏被用于寻找没有包括在特定函数测试宏中的函数。如果函数可能出现在除了缺省C库以外的库中,就 要首先为这些库调用AC_CHECK_LIB。如果你除了需要检查函数是否存在之外,还要检查函数 的行为,你就不得不为此而编写你自己的测试(参见编写测试)。
宏: AC_CHECK_FUNC (function, [action-if-found [, action-if-not-found]])
如果可以使用C函数function,就运行shell命令action-if-found,否则运行 action-if-not-found。如果你只希望在函数可用的时候定义一个符号,就考虑使用 AC_CHECK_FUNCS。由于C++C更加标准化,即使在调用了AC_LANG_CPLUSPLUS 的时候,本宏仍然用C的连接方式对函数进行检查。(关于为测试选择语言的详情,请参见 对语言的选择
宏: AC_CHECK_FUNCS (function… [, action-if-found [, action-if-not-found]])
对于每个在以空格分隔的函数列表function中出现的函数,如果可用,就定义HAVE_function (全部大写)。如果给出了action-if-found,它就是在找到一个函数的时候执行的附加的shell代码。你可以给出 `break’以便在找到第一个匹配的时候跳出循环。如果给出了action-if-not-found,它就在找不到 某个函数的时候执行。
宏: AC_REPLACE_FUNCS (function…)
本宏的功能就类似于以将`function.o’添加到输出变量LIBOBJSshell 代码为参数action-if-not-found,调用AC_CHECK_FUNCS。你可以通过用 `#ifndef HAVE_function’包围你为函数提供的替代版本的原型来声明函数。 如果系统含有该函数,它可能在一个你应该引入的头文件中进行声明,所以你不应该重新声明它,以避免声明冲突。
    1. 头文件

下列宏检查某些C头文件是否存在。
      1. 对特定头文件的检查

这些宏检查特定的系统头文件它们是否存在,以及在某些情况下它们是否定义了特定的符号。

宏: AC_DECL_SYS_SIGLIST
如果在系统头文件,`signal.h’或者`unistd.h’,中定义了变量sys_siglist, 就定义SYS_SIGLIST_DECLARED
宏: AC_DIR_HEADER
类似于调用AC_HEADER_DIRENTAC_FUNC_CLOSEDIR_VOID,但为了指明找到了 哪个头文件而定义了不同的一组C预处理器宏。本宏和它定义的名字是过时的。它定义的名字是:
`dirent.h’
DIRENT
`sys/ndir.h’
SYSNDIR
`sys/dir.h’
SYSDIR
`ndir.h’
NDIR
此外,如果closedir不能返回一个有意义的值,就定义VOID_CLOSEDIR
宏: AC_HEADER_DIRENT
对下列头文件进行检查,并且为第一个找到的头文件定义`DIR’,以及列出的C预处理器宏:
`dirent.h’
HAVE_DIRENT_H
`sys/ndir.h’
HAVE_SYS_NDIR_H
`sys/dir.h’
HAVE_SYS_DIR_H
`ndir.h’
HAVE_NDIR_H
源代码中的目录库声明应该以类似于下面的方式给出:
#if HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
#else
# define dirent direct
# define NAMLEN(dirent) (dirent)->d_namlen
# if HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
# if HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
# if HAVE_NDIR_H
# include <ndir.h>
# endif
#endif
使用上述声明,程序应该把变量定义成类型struct dirent,而不是struct direct,并且应该 通过把指向struct direct的指针传递给宏NAMLEN来获得目录项的名称的长度。
本宏还为SCO Xenix检查库`dir’`x’
宏: AC_HEADER_MAJOR
如果`sys/types.h’没有定义majorminormakedev, 但`sys/mkdev.h’定义了它们,就定义MAJOR_IN_MKDEV; 否则,如果`sys/sysmacros.h’定义了它们,就定义MAJOR_IN_SYSMACROS
宏: AC_HEADER_STDC
如果含有标准CANSI C)头文件,就定义STDC_HEADERS。 特别地,本宏检查`stdlib.h’`stdarg.h’`string.h’`float.h’; 如果系统含有这些头文件,它可能也含有其他的标准C头文件。本宏还检查`string.h’是否定义了memchr (并据此对其他mem函数做出假定),`stdlib.h’是否定义了free(并据此 对malloc和其他相关函数做出假定),以及`ctype.h’宏是否按照标准C的要求而可以 用于被设置了高位的字符。
因为许多含有GCC的系统并不含有标准C头文件,所以用STDC_HEADERS而不是__STDC__ 来决定系统是否含有服从标准(ANSI-compliant)的头文件(以及可能的C库函数)。
在没有标准C头文件的系统上,变种太多,以至于可能没有简单的方式对你所使用的函数进行定义以 使得它们与系统头文件声明的函数完全相同。某些系统包含了ANSIBSD函数的混合;某些基本上是标准(ANSI) 的,但缺少`memmove’;有些系统在`string.h’或者`strings.h’中以宏的方式 定义了BSD函数;有些系统除了含有`string.h’之外,只含有BSD函数;某些系统在`memory.h’ 中定义内存函数,有些在`string.h’中定义;等等。对于一个字符串函数和一个内存函数的检查可能 就够了;如果库含有这些函数的标准版,那么它就可能含有其他大部分函数。如果你在`configure.in’ 中安放了如下代码:
AC_HEADER_STDC
AC_CHECK_FUNCS(strchr memcpy)
那么,在你的代码中,你就可以像下面那样放置声明:
#if STDC_HEADERS
# include <string.h>
#else
# ifndef HAVE_STRCHR
# define strchr index
# define strrchr rindex
# endif
char *strchr (), *strrchr ();
# ifndef HAVE_MEMCPY
# define memcpy(d, s, n) bcopy ((s), (d), (n))
# define memmove(d, s, n) bcopy ((s), (d), (n))
# endif
#endif
如果你使用没有等价的BSD版的函数,诸如memchrmemsetstrtok 或者strspn,那么仅仅使用宏就不够了;你必须为每个函数提供一个实现。以memchr为例, 一种仅仅在需要的时候(因为系统C库中的函数可能经过了手工优化)与你的实现协作的简单方式是把实现放入 `memchr.c’并且使用`AC_REPLACE_FUNCS(memchr)’
宏: AC_HEADER_SYS_WAIT
如果`sys/wait.h’存在并且它和POSIX.1相兼容,就定义HAVE_SYS_WAIT_H。 如果`sys/wait.h’不存在,或者如果它使用老式BSD union wait,而不是 int来储存状态值,就可能出现不兼容。如果`sys/wait.h’不与POSIX.1兼容, 那就不是引入该头文件,而是按照它们的常见解释定义POSIX.1宏。下面是一个例子:
#include <sys/types.h>
#if HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
#ifndef WEXITSTATUS
# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
#endif
#ifndef WIFEXITED
# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
#endif
宏: AC_MEMORY_H
`string.h’中,如果没有定义memcpy, memcmp等函数,并且`memory.h’ 存在,就定义NEED_MEMORY_H。本宏已经过时;可以用AC_CHECK_HEADERS(memory.h)来代替。 参见为AC_HEADER_STDC提供的例子。
宏: AC_UNISTD_H
如果系统含有`unistd.h’,就定义HAVE_UNISTD_H。本宏已经过时;可以用 `AC_CHECK_HEADERS(unistd.h)’来代替。
检查系统是否支持POSIX.1的方式是:
#if HAVE_UNISTD_H
# include <sys/types.h>
# include <unistd.h>
#endif

#ifdef _POSIX_VERSION
/* Code for POSIX.1 systems. */
#endif
POSIX.1系统中包含了`unistd.h’的时候定义_POSIX_VERSION。 如果系统中没有`unistd.h’,那么该系统就一定不是POSIX.1系统。但是,有些非POSIX.1non-POSIX.1) 系统也含有`unistd.h’
宏: AC_USG
如果系统并不含有`strings.h’rindexbzero等头文件或函数,就定义USG。 定义USG就隐含地表明了系统含有`string.h’strrchrmemset等头文件或函数。
符号USG已经过时了。作为本宏的替代,参见为AC_HEADER_STDC提供的例子。
      1. 对普通头文件的检查

这些宏被用于寻找没有包括在特定测试宏中的系统头文件。如果你除了检查头文件是否存在之外还要检查它的内容, 你就不得不为此而编写你自己的测试(参见编写测试)。

宏: AC_CHECK_HEADER (header-file, [action-if-found [, action-if-not-found]])
如果系统头文件header-file存在,就执行shell命令action-if-found, 否则执行action-if-not-found。如果你只需要在可以使用头文件的时候定义一个符号,就考虑使用 AC_CHECK_HEADERS
宏: AC_CHECK_HEADERS (header-file… [, action-if-found [, action-if-not-found]])
对于每个在以空格分隔的参数列表header-file出现的头文件,如果存在,就定义 HAVE_header-file(全部大写)。如果给出了action-if-found, 它就是在找到一个头文件的时候执行的附加shell代码。你可以把`break’作为它的值 以便在第一次匹配的时候跳出循环。如果给出了action-if-not-found,它就在找不到 某个头文件的时候被执行。
    1. 结构

以下的宏检查某些结构或者某些结构成员。为了检查没有在此给出的结构,使用AC_EGREP_CPP (参见检验声明)或者使用AC_TRY_COMPILE (参见检验语法)。

宏: AC_HEADER_STAT
如果在`sys/stat.h’中定义的S_ISDIRS_ISREG等宏不能正确 地工作(返回错误的正数),就定义STAT_MACROS_BROKEN。这种情况出现在Tektronix UTekVAmdahl UTSMotorola System V/88上。
宏: AC_HEADER_TIME
如果程序可能要同时引入`time.h’`sys/time.h’,就定义TIME_WITH_SYS_TIME。 在一些老式系统中,`sys/time.h’引入了`time.h’,但`time.h’没有用多个包含保护 起来,所以程序不应该显式地同时包含这两个文件。例如,本宏在既使用struct timevalstruct timezone,又使用struct tm程序中有用。它最好和 HAVE_SYS_TIME_H一起使用,该宏可以通过调用AC_CHECK_HEADERS(sys/time.h)来检查。
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
宏: AC_STRUCT_ST_BLKSIZE
如果struct stat包含一个st_blksize成员,就定义HAVE_ST_BLKSIZE
宏: AC_STRUCT_ST_BLOCKS
如果struct stat包含一个st_blocks成员,就定义HAVE_ST_BLOCKS。 否则,就把`fileblocks.o’添加到输出变量LIBOBJS中。
宏: AC_STRUCT_ST_RDEV
如果struct stat包含一个st_rdev成员,就定义HAVE_ST_RDEV
宏: AC_STRUCT_TM
如果`time.h’没有定义struct tm,就定义TM_IN_SYS_TIME,它意味着 引入`sys/time.h’将得到一个定义得更好的struct tm
宏: AC_STRUCT_TIMEZONE
确定如何获取当前的时区。如果struct tmtm_zone成员,就定义HAVE_TM_ZONE。 否则,如果找到了外部数组tzname,就定义HAVE_TZNAME
    1. 类型定义

以下的宏检查C typedefs。如果没有为你需要检查的typedef定义特定的宏,并且你不需要检查该类型 的任何特殊的特征,那么你可以使用一个普通的typedef检查宏。
      1. 对特定类型定义的检查

这些宏检查在`sys/types.h’`stdlib.h’(如果它存在)中定义的特定的C typedef

宏: AC_TYPE_GETGROUPS
GETGROUPS_T定义成getgroups的数组参数的基类型gid_t或者int
宏: AC_TYPE_MODE_T
如果没有定义mode_t,就把mode_t定义成int
宏: AC_TYPE_OFF_T
如果没有定义off_t,就把off_t定义成long
宏: AC_TYPE_PID_T
如果没有定义pid_t,就把pid_t定义成int
宏: AC_TYPE_SIGNAL
如果`signal.h’signal声明成一个指向返回值为void的函数的指针, 就把RETSIGTYPE定义成void;否则,就把它定义成int
把信号处理器(signal handler)的返回值类型定义为RETSIGTYPE
RETSIGTYPE
hup_handler ()
{
...
}
宏: AC_TYPE_SIZE_T
如果没有定义size_t,就把size_t定义成unsigned
宏: AC_TYPE_UID_T
如果没有定义uid_t,就把uid_t定义成int并且把 gid_t定义成int
      1. 对普通类型定义的检查

本宏用于检查没有包括在特定类型测试宏中的typedef

宏: AC_CHECK_TYPE (type, default)
如果`sys/types.h’或者`stdlib.h’或者`stddef.h’存在,而类型 type没有在它们之中被定义,就把type定义成C(或者C++)预定义类型 default;例如,`short’或者`unsigned’
    1. C编译器的特征

下列宏检查C编译器或者机器结构的特征。为了检查没有在此列出的特征,使用AC_TRY_COMPILE (参见检验语法)或者AC_TRY_RUN (参见检查运行时的特征)

宏: AC_C_BIGENDIAN
如果字(word)按照最高位在前的方式储存(比如MotorolaSPARC,但不包括IntelVAXCPUS),就定义 WORDS_BIGENDIAN
宏: AC_C_CONST
如果C编译器不能完全支持关键字const,就把const定义成空。有些编译器并不定义 __STDC__,但支持const;有些编译器定义__STDC__,但不能完全支持 const。程序可以假定所有C编译器都支持const,并直接使用它;对于那些不能完全 支持const的编译器,`Makefile’或者配置头文件将把const定义为空。
宏: AC_C_INLINE
如果C编译器支持关键字inline,就什么也不作。如果C编译器可以接受__inline__或者__inline,就把inline定义成可接受的关键字,否则就把inline定义为空。
宏: AC_C_CHAR_UNSIGNED
除非C编译器预定义了__CHAR_UNSIGNED__,如果C类型char是无符号的,就定义 __CHAR_UNSIGNED__
宏: AC_C_LONG_DOUBLE
如果C编译器支持long double类型,就定义HAVE_LONG_DOUBLE。 有些C编译器并不定义__STDC__但支持long double类型;有些编译器定义 __STDC__但不支持long double
宏: AC_C_STRINGIZE
如果C预处理器支持字符串化操作符(stringizing operator),就定义HAVE_STRINGIZE。字符串化操作符是 `#’并且它在宏定义中以如下方式出现:
#define x(y) #y
宏: AC_CHECK_SIZEOF (type [, cross-size])
SIZEOF_uctype定义为C(或C++)预定义类型type的,以字节为单位的大小, 例如`int’ or `char *’。如果编译器不能识别`type’,它就被定义为0uctype就是把type中所有小写字母转化为大写字母,空格转化成下划线,星号转化成`P’ 而得到的名字。在交叉编译中,如果给出了cross-size,就使用它,否则configure就 生成一个错误并且退出。
例如,调用
AC_CHECK_SIZEOF(int *)
DEC Alpha AXP系统中,把SIZEOF_INT_P定义为8
宏: AC_INT_16_BITS
如果C类型int16为宽,就定义INT_16_BITS。本宏已经过时;更常见的方式是用 `AC_CHECK_SIZEOF(int)’来代替。
宏: AC_LONG_64_BITS
如果C类型long int64位宽,就定义LONG_64_BITS。 本宏已经过时;更常见的方式是用`AC_CHECK_SIZEOF(long)’来代替。
    1. Fortran 77编译器的特征

下列的宏检查Fortran 77编译器的特征。为了检查没有在此列出的特征,使用AC_TRY_COMPILE (参见检验语法)或者AC_TRY_RUN (参见检验运行时的特征),但首先必须确认当前语言被设置成 Fortran 77 AC_LANG_FORTRAN77(参见对语言的选择)。

宏: AC_F77_LIBRARY_LDFLAGS
为成功地连接Fotran 77或者共享库而必须的Fortran 77内置函数(intrinsic)和运行库确定连接选项 (例如,`-L’`-l’)。输出变量FLIBS被定义为这些选项。
本宏的目的是用于那些需要把C++Fortran 77源代码混合到一个程序或者共享库中的情况 (参见GNU Automake中的`Mixing Fortran 77 With C and C++’节)。
例如,如果来自C++Fortran 77编译器的目标文件必须被连接到一起,那么必须用C++编译器/连接器来连接 (因为有些C++特定的任务要在连接时完成,这样的任务有调用全局构造函数、模板的实例化、启动例外 (exception)支持,等等)。
然而,Fortran 77内置函数和运行库也必须被连接,但C++编译器/连接器在缺省情况下不知道如何添加这些 Fortran 77库。因此,就创建AC_F77_LIBRARY_LDFLAGS宏以确认这些Fortran 77库。
    1. 系统服务

下列宏检查操作系统服务或者操作系统能力。

宏: AC_CYGWIN
检查Cygwin环境。如果存在,就把shell变量CYGWIN设置成`yes’。 如果不存在,就把CYGWIN设置成空字符串。
宏: AC_EXEEXT
根据编译器的输出,定义替换变量EXEEXT,但不包括.c.o.obj文件。 对于Unix来说典型的值为空,对Win32来说典型的值为`.exe’或者`.EXE’
宏: AC_OBJEXT
根据编译器的输出,定义替换变量OBJEXT,但不包括.c文件。 对于Unix来说典型的值为`.o’,对Win32来说典型的值为`.obj’
宏: AC_MINGW32
检查MingW32编译环境。如果存在,就把shell变量MINGW32设置成`yes’。 如果不存在,就把MINGW32设置成空。
宏: AC_PATH_X
试图找到X Window系统的头文件和库文件。如果用户给出了命令行选项`–x-includes=dir’`–x-libraries=dir’,就使用这些目录。如果没有给出任一个选项,或者都没有给出,就通过 运行xmkmf以处理一个测试`Imakefile’,并且检查它所生成的`Makefile’,来得到没有 给出的目录。如果这失败了(比如说,xmkmf不存在),就在它们通常存在的几个目录中寻找。如果任何一种 方法成功了,就把shell变量x_includesx_libraries设置成相应的位置,除非这些目录就在 编译器搜索的缺省目录中。
如果两种方法都失败了,或者用户给出命令行选项`–without-x’,就把shell变量no_x 设置成`yes’;否则就把它设置成空字符串。
宏: AC_PATH_XTRA
AC_PATH_X的增强版。它把X需要的C编译器选项添加到输出变量X_CFLAGS,并且把 X的连接选项添加到X_LIBS。如果不能使用X系统,就把`-DX_DISPLAY_MISSING’ 设置成X_CFLAGS
本宏还检查在某些系统中为了编译X程序而需要的特殊库。它把所有系统需要的库添加到输出变量X_EXTRA_LIBS。 并且它检查需要在`-lX11′之前被连接的特殊X11R6库,并且把找到的所有库添加到输出变量X_PRE_LIBS
宏: AC_SYS_INTERPRETER
检查系统是否支持以形式为`#! /bin/csh’的行开头的脚本选择执行该脚本的解释器。 在运行本宏之后,configure.in中的shell代码就可以检查shell变量interpval; 如果系统支持`#!’interpval将被设置成`yes’,如果不支持 就设置成`no’
宏: AC_SYS_LONG_FILE_NAMES
如果系统支持长于14个字符的文件名,就定义HAVE_LONG_FILE_NAMES
宏: AC_SYS_RESTARTABLE_SYSCALLS
如果系统自动地重新启动被信号所中断的系统调用,就定义HAVE_RESTARTABLE_SYSCALLS

编写测试

    1. 检验声明

AC_TRY_CPP用于检测某个特定的头文件是否存在。你可以一次检查一个头文件,或者如果你为了某些目的 而希望多个头文件都存在,也可以一次检查多个头文件。

宏: AC_TRY_CPP (includes, [action-if-true [, action-if-false]])
includesCC++#include语句和声明,对于它,将进行shell变量、反引用(backquote)、以及反斜线 (backslash)替换。(实际上,它可以是任何C程序,但其它的语句可能没有用。)如果预处理器在处理它的时候没有报告错误, 就运行shell命令action-if-true。否则运行shell命令action-if-false
本宏使用CPPFLAGS,而不使用CFLAGS,这是因为`-g’`-O’等选项对于 许多C预处理器来说都是不合法的选项。

下面是如何确认在某个头文件中是否包含一个特定的声明,比如说typedef、结构、结构成员或者一个函数。使用 AC_EGREP_HEADER而不是对头文件直接运行grep;在某些系统中,符号可能是在另一个你所检查的 `#include’文件。

宏: AC_EGREP_HEADER (pattern, header-file, action-if-found [, action-if-not-found])
如果对系统头文件header-file运行预处理器所产生的输出与egrep常规表达式pattern相匹配, 就执行shell命令action-if-found,否则执行action-if-not-found

为了检查由头文件或者C预处理器预定义的C预处理器符号,使用AC_EGREP_CPP。下面是后者的一个例子:

AC_EGREP_CPP(yes,
[#ifdef _AIX
  yes
#endif
], is_aix=yes, is_aix=no)
宏: AC_EGREP_CPP (pattern, program, [action-if-found [, action-if-not-found]])
programC或者C++的程序文本,对于它,将进行shell变量、反引号(backquote)以及反斜线(backslash)替换。 如果对program运行预处理器产生的输出与egrep常规表达式(regular expressionpattern 相匹配,就执行shell命令action-if-found,否则执行action-if-not-found
如果宏还没有调用AC_PROG_CPP或者AC_PROG_CXXCPP(根据当前语言来确定使用那个宏, 参见对语言的选择),本宏将调用它。
    1. 检验语法

为了检查CC++或者Fortran 77编译器的语法特征,比如说它是否能够识别某个关键字,就使用AC_TRY_COMPILE 来尝试编译一个小的使用该特征的程序。你还可以用它检查不是所有系统都支持的结构和结构成员。

宏: AC_TRY_COMPILE (includes, function-body, [action-if-found [, action-if-not-found]])
创建一个CC++或者Fortran 77测试程序(依赖于当前语言,参见对语言的选择), 来察看由function-body组成的函数是否可以被编译。
对于CC++includes是所有function-body中的代码需要的#include语句 (如果当前选择的语言是Fortran 77includes将被忽略)。如果当前选择的语言是C或者C++,本宏还将 在编译的时侯使用CFLAGS或者CXXFLAGS,以及CPPFLAGS。如果当前选择的 语言是Fortran 77,那么就在编译的时候使用FFLAGS
如果文件被成功地编译了,就运行shell命令action-if-found,否则运行action-if-not-found
本宏并不试图进行连接;如果你希望进行连接,使用AC_TRY_LINK (参见检验库)。
    1. 检验库

少数系统的连接器在出现找不到的函数错误(unresolved functions)时不返回失败的退出状态。这个错误使得由Autoconf 生成的配置脚本不能在这样的系统中使用。然而,有些这样的连接器允许给出选项以便正确地返回错误状态。 Autoconf目前还不能自动地处理这个问题。如果用户遇到了这样的问题,他们可能可以通过在环境中设置LDFLAGS 以把连接器所需要的选项(例如,`-Wl,-dn’ on MIPS RISC/OS)传递给连接器,从而解决这个问题。
AC_TRY_LINK用于编译测试程序,以测试函数和全局变量。AC_CHECK_LIB还用本宏把被测试的库 暂时地加入LIBS并试图连接一个小程序,从而对库进行检查(参见库文件)。
宏: AC_TRY_LINK (includes, function-body, [action-if-found [, action-if-not-found]])
根据当前语言(参见对语言的选择),创建一个测试程序以察看一个 函数体为function-body的函数是否可以被编译和连接。
CC++来说,includes给出了所有function-body中的代码需要的#include语句 (如果当前选定的语言是Fortran 77includes将被忽略)。如果当前语言是C或者C++,本宏在编译时还将使用 CFLAGS或者CXXFLAGS,以及CPPFLAGS。如果当前选定的语言是Fortran 77,那么 在编译时将使用FFLAGS。然而,在任何情况下,连接都将使用LDFLAGSLIBS
如果文件被成功地编译和连接了,就运行shell命令action-if-found,否则就运行action-if-not-found
宏: AC_TRY_LINK_FUNC (function, [action-if-found [, action-if-not-found]])
根据当前语言(参见对语言的选择),创建一个测试程序以察看一个含有function 原型和对它的调用的程序是否可以被编译和连接。
如果文件被成功地编译和连接了,就运行shell命令action-if-found,否则就运行action-if-not-found
宏: AC_TRY_LINK_FUNC (function, [action-if-found [, action-if-not-found]])
试图编译并且连接一个与function相连接的小程序。如果文件被成功地编译和连接了,就运行shell命令 action-if-found,否则就运行action-if-not-found
宏: AC_COMPILE_CHECK (echo-text, includes, function-body, action-if-found [, action-if-not-found])
本宏是AC_TRY_LINK的一个过时的版本。此外,如果echo-text不为空,它首先还要把 `checking for echo-text’打印到标准输出。用AC_MSG_CHECKING AC_MSG_RESULT来代替本宏的打印消息的功能(参见打印消息
    1. 检验运行时的特征

如果你实在需要在配置时刻检查运行时的特征,你可以编写一个测试程序以确定结果,并且通过AC_TRY_RUN 来编译和运行它。如果可能就避免运行测试程序,这是因为使用它们使得人们不能对你的包进行交叉编译。
      1. 运行测试程序

如果你希望在配置的时候测试系统运行时的特征,就使用如下的宏。

宏: AC_TRY_RUN (program, [action-if-true [, action-if-false [, action-if-cross-compiling]]])
programC程序的文本,将对该文本进行shell变量和反引用(backquote)替换。如果它被成功地编译和连接了并且 在执行的时候返回的退出状态为0,就运行shell命令action-if-true。否则就运行shell命令action-if-false; 程序的退出状态可以通过shell变量`$?’得到。本宏在编译时使用CFLAGS或者CXXFLAGS以及 CPPFLAGSLDFLAGSLIBS
如果使用的C编译器生成的不是在configure运行的系统上运行的可执行文件,那么测试程序就不运行。 如果给出了可选的shell命令action-if-cross-compiling,它们就代替生成的可执行文件执行。否则, configure打印一条错误消息并且退出。

当交叉编译使运行时测试变得不可能的时候,就尝试提供一个应急(pessimistic)的缺省值以供使用。你通过把可选的最后一个参数 传递给AC_TRY_RUN来完成这个工作。在每次生成configure的过程中,每次遇到没有提供 action-if-cross-compiling参数的AC_TRY_RUN调用时,autoconf都打印一条警告消息。 虽然用户将不能为交叉编译你的包而进行配置,你仍可以忽略该警告。与Autoconf一同发行的少数宏产生该警告消息。

为了为交叉编译进行配置,你还可以根据规范系统名(canonical system name)为这些参数选择值 (参见手工配置)。另一种方式是把测试缓存文件设置成目标系统的正确值 (参见缓存结果)。

为了给嵌入到其它宏(包括少数与Autoconf一同发行的宏)中的,对AC_TRY_RUN的调用提供缺省值, 你可以在它们运行之前调用AC_PROG_CC。那么,如果shell变量cross_compiling被设置成 `yes’,就使用另一种方法来获取结果,而不是调用宏。

      1. 测试程序指南

测试程序不应该向标准输出输出任何信息。如果测试成功,它们应该返回0,否则返回非0,以便于把成功的执行 从core dump或者其它失败中区分出来;段冲突(segmentation violations)和其它失败产生一个非0的退出状态。 测试程序应该从mainexit,而不是return,这是因为在某些系统中 (至少在老式的Sun上),mainreturn的参数将被忽略。

测试程序可以使用#if或者#ifdef来检查由已经执行了的测试定义的预处理器宏的值。 例如,如果你调用AC_HEADER_STDC,那么在`configure.in’的随后部分,你可以使用一个有 条件地引入标准C头文件的测试程序:

#if STDC_HEADERS
# include <stdlib.h>
#endif

如果测试程序需要使用或者创建数据文件,其文件名应该以`conftest’开头,例如`conftestdata’。 在运行测试程序之后或者脚本被中断时,configure将通过运行`rm -rf conftest*’来清除数据文件。

      1. 测试函数

在测试程序中的函数声明应该条件地含有为C++提供的原型。虽然实际上测试程序很少需要带参数的函数。

#ifdef __cplusplus
foo(int i)
#else
foo(i) int i;
#endif

测试程序声明的函数也应该有条件地含有为C++提供的,需要`extern “C”‘的原型。要确保不要引入 任何包含冲突原型的头文件。

#ifdef __cplusplus
extern "C" void *malloc(size_t);
#else
char *malloc();
#endif
    1. 可移植的Shell编程

#! /usr/bin/perl

如果你忽略了路径之前的空格,那么基于4.2BSD的系统(比如说Sequent DYNIX)将忽略这一行,这是因为它们把 `#! /’看作一个四字节的魔数(magic number)。

    1. 测试值和文件

如果你需要通过test创建多个检查,就用shell操作符`&&’`||’ 把它们组合起来,而不是使用test操作符`-a’`-o’。在System V中, `-a’`-o’相对于unary操作符的优先级是错误的;为此,POSIX并未给出它们,所以使用它们是 不可移植的。如果你在同一个语句中组合使用了`&&’`||’,要记住它们的 优先级是相同的。

另一个不可移植的shell编程结构是

var=${var:-value}

它的目的是仅仅在没有设定var的值的情况下,把var设置成value, 但如果var已经含有值,即使是空字符串,也不修改var。老式BSD shell,包括 Ultrix sh,不接受这个冒号,并且给出错误并停止。一个可以移植的等价方式是

: ${var=value}
    1. 对语言的选择

既使用C又使用C++的包需要同时测试两个编译器。Autoconf生成的configure脚本 在缺省情况下检查C的特征。以下的宏决定在`configure.in’的随后部分使用那个语言的编译器。

宏: AC_LANG_C
使用CCCPP进行编译测试并且把`.c’作为测试程序的扩展名。 如果已经运行过AC_PROG_CC,就把把shell变量cross_compiling的值设置成该宏计算的结果, 否则就设置为空。
宏: AC_LANG_CPLUSPLUS
使用CXXCXXPP进行编译测试并且把`.C’作为测试程序的扩展名。 如果已经运行过AC_PROG_CXX,就把把shell变量cross_compiling的值设置成该宏计算的结果, 否则就设置为空。
宏: AC_LANG_FORTRAN77
使用F77进行编译测试并且把`.f’作为测试程序的扩展名。 如果已经运行过AC_PROG_F77,就把把shell变量cross_compiling的值设置成该宏计算的结果, 否则就设置为空。
宏: AC_LANG_SAVE
在堆栈中记录当前的语言(由AC_LANG_CAC_LANG_CPLUSPLUS或者AC_LANG_FORTRAN77 所设定)。不改变当前使用的语言。在需要暂时地切换到其它特殊语言的宏之中使用本宏和AC_LANG_RESTORE
宏: AC_LANG_RESTORE
选择储存在栈顶的,由AC_LANG_SAVE设置的语言,并且把它从栈顶删除。本宏等价于运行在最后被调用的 AC_LANG_SAVE之前最近的AC_LANG_CAC_LANG_CPLUSPLUS或者 AC_LANG_FORTRAN77
调用本宏的次数不要多于调用AC_LANG_SAVE的次数。
宏: AC_REQUIRE_CPP
确认已经找到了当前用于测试的预处理器。本宏根据当前选择的语言,以AC_PROG_CPP或者AC_PROG_CXXCPP 为参数调用AC_REQUIRE(参见首要的宏)。

测试的结果

一旦configure确定了某个特征是否存在,它将如何记录这一信息?这里有四种记录方式: 定义一个C预处理器符号、在输出文件中设置一个变量、为将来运行configure而把结果储存到一个缓存文件中, 以及打印一条消息以便让用户知道测试的结果。

    1. 定义C预处理器符号

对一个特征的检测的常见回应是定义一个表示测试结果的C预处理器符号。这是通过调用AC_DEFINE 或者AC_DEFINE_UNQUOTED来完成的。

在缺省状态下,AC_OUTPUT把由这些宏定义的符号放置到输出变量DEFS中,该变量为每个 定义了的符号添加一个选项`-Dsymbol=value’。与Autoconf1版不同,在运行时 不定义DEFS变量。为了检查Autoconf宏是否已经定义了某个C预处理器符号,就检查适当的缓存变量的值, 例子如下:

AC_CHECK_FUNC(vprintf, AC_DEFINE(HAVE_VPRINTF))
if test "$ac_cv_func_vprintf" != yes; then
AC_CHECK_FUNC(_doprnt, AC_DEFINE(HAVE_DOPRNT))
fi

如果已经调用了AC_CONFIG_HEADER,那么就不是创建DEFS,而是由AC_OUTPUT 创建一个头文件,这是通过在一个暂时文件中把正确的值替换到#define语句中来实现的。 关于这种输出的详情,请参见配置头文件

宏: AC_DEFINE (variable [, value [, description]])
定义C预处理器变量variable。如果给出了value,就把variable设置成那个值(不加任何改变), 否则的话就设置为1value不应该含有新行,同时如果你没有使用AC_CONFIG_HEADER,它就不应该含有 任何`#’字符,这是因为make将删除它们。为了使用shell变量(你需要使用该变量定义一个包含了 m4引用字符`[‘或者`]’的值),就使用AC_DEFINE_UNQUOTED。只有在 你使用AC_CONFIG_HEADER的时候,description才有用。在这种情况下,description被 作为注释放置到生成的`config.h.in’的宏定义之前;不必在`acconfig.h’中提及该宏。下面的例子把 C预处理器变量EQUATION的值定义成常量字符串`”$a > $b”‘
AC_DEFINE(EQUATION, "$a > $b")
宏: AC_DEFINE_UNQUOTED (variable [, value [, description]])
类似于AC_DEFINE,但还要对variablevalue进行三种shell替换(每种替换只进行一次): 变量扩展(`$’),命令替换(“’),以及反斜线传义符(`\’)。值中的单引号和双引号 没有特殊的意义。在variable或者value是一个shell变量的时候用本宏代替AC_DEFINE。例如:
AC_DEFINE_UNQUOTED(config_machfile, "${machfile}")
AC_DEFINE_UNQUOTED(GETGROUPS_T, $ac_cv_type_getgroups)
AC_DEFINE_UNQUOTED(${ac_tr_hdr})

由于Bourne shell在语法上的特异性,不要用分号来分隔对AC_DEFINE或者AC_DEFINE_UNQUOTED的调用和 其它的宏调用或者shell代码;这将在最终的configure脚本中导致语法错误。你既可以使用空格,也可以使用 换行。就是这样:

AC_CHECK_HEADER(elf.h, AC_DEFINE(SVR4) LIBS="$LIBS -lelf")

或者:

AC_CHECK_HEADER(elf.h,
  AC_DEFINE(SVR4)
  LIBS="$LIBS -lelf")

而不是:

AC_CHECK_HEADER(elf.h, AC_DEFINE(SVR4); LIBS="$LIBS -lelf")
    1. 设置输出变量

记录测试结果的一种方式是设置输出变量,该变量是shell变量,它的值将被替换到configure输出的文件中。 下面的两个宏创建新的输出变量。关于总是可用的输出变量的列表,参见预定义输出变量

宏: AC_SUBST (variable)
从一个shell变量创建一个输出变量。让AC_OUTPUT把变量variable替换到输出文件中(通常是一个或多个 `Makefile’)。这意味着AC_OUTPUT将把输入文件中的`@variable@’实例替换成 调用AC_OUTPUTshell变量variable的值。variable的值不能包含新行。
宏: AC_SUBST_FILE (variable)
另一种从shell变量创建输出变量的方式。让AC_OUTPUT把由shell变量variable给出的文件名的文件的内容 (不进行替换)插入到输出文件中。这意味着AC_OUTPUT将在输出文件中(比如`Makefile.in’)把输入文件中 的`@variable@’实例替换为调用AC_OUTPUTshell变量variable的值指明的文件 的内容。如果没有文件可以插入,就把变量设置成`/dev/null’
本宏用于把包含特殊依赖性或者为特殊主机或目标机准备的其它make指令的`Makefile’片断插入 `Makefile’。例如,`configure.in’可以包含:
AC_SUBST_FILE(host_frag)dnl
host_frag=$srcdir/conf/sun4.mh
那么`Makefile.in’就应该包含:
@host_frag@
    1. 缓存结果

为了避免在各种configure脚本中重复地对相同的特征进行检查(或者重复地运行同一个脚本), configure把它的检查的许多结果储存在缓存文件。如果在configure脚本运行时,它找到了 缓存文件,它就从中读取从前运行的结果并且不再重新运行这些检查。因此,configure将比每次都运行所有的检查 要快得多。

宏: AC_CACHE_VAL (cache-id, commands-to-set-it)
确认由cache-id指定的检查的结果是可用的。如果检查的结果在读入的缓存文件中,并且configure 没有用`–quiet’或者`–silent’调用,就打印一条消息以说明该结果已经被缓存了;否则,就运行 shell命令commands-to-set-it。这些命令不应具有副作用,但设置变量cache-id除外。它们尤其不应该调用 AC_DEFINE;紧随与对AC_CACHE_VAL的调用之后的代码应该根据缓存的值调用AC_DEFINE 作这件事。此外,它们不应该打印任何消息,比如说使用AC_MSG_CHECKING;应该在调用AC_CACHE_VAL 之前打印,以便不论测试的结果是从缓存中检索而得到的,还是通过运行shell命令而确定的,都会打印消息。如果是运行 shell命令以确定值,该值将在configure创建它的输出文件之前被储存到缓存文件中。关于如何选择 cache-id变量的名称,参见缓存变量名
宏: AC_CACHE_CHECK (message, cache-id, commands)
这是一个更详尽地处理了打印消息的AC_CACHE_VAL版本。本宏为这些宏的最常见的应用提供了便捷的缩写。 它为message调用AC_MSG_CHECKING,而后以cache-idcommands为参数 调用AC_CACHE_VAL,最后以cache-id为参数调用AC_MSG_RESULT
宏: AC_CACHE_LOAD
从已经存在的缓存文件中装入值,如果找不到缓存文件,就创建一个新的缓存文件。本宏由AC_INIT自动调用。
宏: AC_CACHE_SAVE
把所有缓存的值刷新到缓存文件中。本宏由AC_OUTPUT自动调用,但在configure.in的关键点调用 AC_CACHE_SAVE是十分有用的。假如配置脚本中途失败(abort)了,这些关键点仍然可以缓存一部分结果。
      1. 缓存变量名

缓存变量的名字应该符合如下格式:

package-prefix_cv_value-type_specific-value[_additional-options]

例如,`ac_cv_header_stat_broken’或者`ac_cv_prog_gcc_traditional’。 变量名的各个部分为:

package-prefix
你的包或者组织的缩写;除了为了方便而使用小写字母以外,与你使用的作为本地Autoconf宏的开头的前缀一样。 对于由发布的Autoconf宏使用的缓存值,它是`ac’
_cv_
表明本shell变量是一个缓存值。
value-type
关于缓存值类别的惯例,以生成一个合理的命名系统。在Autoconf中使用的值在宏名中列出。
specific-value
指明本测试应用于缓存值类的那个成员。 例如,那个函数(`alloca’)、程序(`gcc’)或者输出变量(`INSTALL’)。
additional-options
给出应用本测试的特定成员的任何特殊行为。例如,`broken’或者`set’。 如果没有用,名字的这个部分可能被忽略掉。

赋予缓存变量的值不能含有新行。通常,它们的是将是布尔(`yes’`no’)或者文件名或者函数名; 所以,这并不是一个重要的限制。

      1. 缓存文件

在缺省情况下,configure`./config.cache’作为缓存文件,如果它还不存在,就创建它。 configure接受选项`–cache-file=file’以使用不同的缓存文件; 这就是configure在调用子目录中的configure脚本时所作的工作。 关于使用宏AC_CONFIG_SUBDIRS在子目录中进行配置的信息,参见 在子目录中配置其它包

给出`–cache-file=/dev/null’会关闭缓存,这是为调试configure提供的。 只有在调用`config.status’时给出选项`–recheck’,这将导致它重新运行configure, 它才会注意到缓存文件。如果你预计需要一个长的调试时期,你还可以通过在`configure.in’的开头重新定义 缓存宏而关闭对configure脚本的装入和储存:

define([AC_CACHE_LOAD], )dnl
define([AC_CACHE_SAVE], )dnl
AC_INIT(whatever)
 ... rest of configure.in ...

试图为特定的系统类型发布缓存文件是错误的。这里存在太多的导致错误的空间,并带来太多的用于维护它们的管理开销。 对于任何不能被自动猜测出来的特征,应使用规范系统类型和连接文件的方法(参见手工配置)。

如果你的配置脚本,或者configure.in中的宏调用,偶尔导致配置过程的失败,在几个关键点进行缓存可能是有用的。 在有希望修正导致上次运行的错误的时候,这样做将减少重新运行configure脚本的时间。

 ... AC_INIT, etc. ...
dnl checks for programs
AC_PROG_CC
AC_PROG_GCC_TRADITIONAL
 ... more program checks ...
AC_CACHE_SAVE

dnl checks for libraries
AC_CHECK_LIB(nsl, gethostbyname)
AC_CHECK_LIB(socket, connect)
 ... more lib checks ...
AC_CACHE_SAVE

dnl Might abort...
AM_PATH_GTK(1.0.2, , exit 1)
AM_PATH_GTKMM(0.9.5, , exit 1)
    1. 打印消息

configure脚本需要为运行它们的用户提供几种信息。下列的宏为每种信息以适当的方式打印消息。 所有宏的参数都应该由shell双引号括起来,以便shell可以对它们进行变量替换和反引号替换。你可以把消息用 m4引用字符括起来以打印包含括号的消息:

AC_MSG_RESULT([never mind, I found the BASIC compiler])

这些宏都是对shell命令echo的封装。configure应该很少需要直接运行echo来为 用户打印消息。使用这些宏使得修改每种消息如何打印及何时打印变得容易了;这些修改只需要对宏的定义进行就行了, 而所有的调用都将自动地改变。

宏: AC_MSG_CHECKING (feature-description)
告知用户configure正在检查特定的特征。本宏打印一条以`checking ‘开头,以`…’ 结尾,而且不带新行的消息。它必须跟随一条对AC_MSG_RESULT的调用以打印检查的结果和新行。 feature-description应该是类似于 `whether the Fortran compiler accepts C++ comments’或者`for c89′的东西。
如果运行configure给出了选项`–quiet’或者选项`–silent’,本宏什么也不打印。
宏: AC_MSG_RESULT (result-description)
告知用户测试的结果。result-description几乎总是检查的缓存变量的值,典型的值是`yes’`no’或者文件名。本宏应该在AC_MSG_CHECKING之后调用,并且result-description 应该完成由AC_MSG_CHECKING所打印的消息。
如果运行configure给出了选项`–quiet’或者选项`–silent’,本宏什么也不打印。
宏: AC_MSG_ERROR (error-description)
告知用户一条使configure不能完成的错误。本宏在标准错误输出中打印一条错误消息并且以非零状态退出 configureerror-description应该是类似于`invalid value $HOME for \$HOME’的东西。
宏: AC_MSG_WARN (problem-description)
告知configure的使用者可能出现的问题。本宏在标准错误输出中打印消息;configure继续向后运行, 所以调用AC_MSG_WARN的宏应该为它们所警告的情况提供一个缺省的(备份)行为。 problem-description应该是类似于`ln -s seems to make hard links’的东西。

下列两个宏是AC_MSG_CHECKINGAC_MSG_RESULT的过时的替代版本。

宏: AC_CHECKING (feature-description)
除了在feature-description之后打印新行,本宏与AC_MSG_CHECKING相同。 它主要用于打印对一组特征测试的整体目的的描述,例如:
AC_CHECKING(if stack overflow is detectable)
宏: AC_VERBOSE (result-description)
除了应该在AC_CHECKING,而不是在AC_MSG_CHECKING之后调用,本宏与AC_MSG_RESULT相同; 它在打印消息前首先打印一个tab。它已经过时了。

编写宏

    1. 宏定义

Autoconf宏是用宏AC_DEFUN定义的,该宏与m4的内置define宏相似。 除了定义一个宏,AC_DEFUN把某些用于限制宏调用顺序的代码添加到其中。 (参见首要的宏)。

一个Autoconf宏像下面那样定义:

AC_DEFUN(macro-name, [macro-body])

这里的方括号并不表示可选的文本:它们应当原样出现在宏定义中,以避免宏扩展问题 (参见引用)。你可以使用`$1′`$2′等等来访问 传递给宏的任何参数。

关于编写m4宏的更完整的信息,参见GNU m4中的`如何定义新宏
    1. 宏名

所有Autoconf宏都以`AC_’起头以防止偶然地与其它文本发生冲突。所有它们用于内部目的的shell变量 几乎全部是由小写字母组成的,并且以`ac_’开头的名字。为了确保你的宏不会与现在的或者将来的Autoconf宏冲突, 你应该给你自己的宏名和任何它们因为某些原因而需要使用的shell变量添加前缀。它可能是你名字的开头字符,或者 你的组织或软件包名称的缩写。

`AC_’之后的第一个单词通常给出被测试特征的类别。下面是Autoconf为特殊测试宏使用的类别, 它们是你很可能要编写的宏。它们的全小写形式还用于缓存变量。在可能的地方使用它们;如果不能,就发明一个你自己的类别。

C
C语言内置特征。
DECL
在头文件中对C变量的声明。
FUNC
库中的函数。
GROUP
文件的UNIX组拥有者(group owner)。
HEADER
头文件。
LIB
C库。
PATH
包括程序在内的,到文件的全路径名。
PROG
程序的基本名(base name)。
STRUCT
头文件中对C结构的定义。
SYS
操作系统特征。
TYPE
C内置或者声明类型。
VAR
库中的C变量。

在类别之后就是特定的被测试特征的名称。宏名中所有的其它单词指明了特征的特殊方面。 例如,AC_FUNC_UTIME_NULL检查用NULL指针调用utime函数时该函数的行为。

一个作为另一个宏的内部子程序的宏的名字应该以使用它的宏的名字开头,而后是说明内部宏作了什么的一个或多个单词。 例如,AC_PATH_X有内部宏AC_PATH_X_XMKMFAC_PATH_X_DIRECT

    1. 引用

由其他的宏调用的宏将被m4进行几次求值;每次求值都可能需要一层引号以防止对宏或者m4 内置宏的不必要扩展,例如说`define’`$1′。引号还需要出现在含有逗号的宏参数中, 这是因为逗号把参数与参数分隔开来。还有,把所有含有新行和调用其它宏的宏参数引起来是一个好主意。

Autoconfm4的引用字符从缺省的“’`”改为`[‘`]’, 这是因为许多宏使用“’`”,这不方便。然而,在少数情况下,宏需要使用方括号(通常在C程序文本 或者常规表达式中)。在这些情况下,它们使用m4内置命令changequote暂时地把引用字符改为 `<<‘`>>’。 (有时,如果它们不需要引用任何东西,它们就通过把引用字符设置成空字符串以完全关闭引用。)下面是一个例子:

AC_TRY_LINK(
changequote(<<, >>)dnl
<<#include <time.h>
#ifndef tzname /* For SGI. */
extern char *tzname[]; /* RS6000 and others reject char **tzname. */
#endif>>,
changequote([, ])dnl
[atoi(*tzname);], ac_cv_var_tzname=yes, ac_cv_var_tzname=no)

当你用新编写的宏创建configure脚本时,仔细地验证它以检查你是否需要在你的宏之中添加更多的引号。 如果一个或多个单词在m4的输出中消失了,你就需要更多的引号。当你不能确定的时候,就使用引号。

但是,还有放置了过多层的引号的可能。如果这发生了,configure脚本的结果将包含未扩展的宏。 程序autoconf通过执行`grep AC_ configure’来检查这个问题。

    1. 宏之间的依赖性

      1. 首要的宏

你编写的宏可能需要使用从前有其它宏计算出来的结果。例如,AC_DECL_YYTEXT要检验flexlex的输出,所以它要求首先调用AC_PROG_LEX以设置shell变量LEX

比强制宏的用户跟踪宏以前的依赖性更好的是,你可以使用宏AC_REQUIRE以自动地完成这一任务。 AC_REQUIRE可以确保只在需要的时候调用宏,并且只被调用一次。

宏: AC_REQUIRE (macro-name)
如果还没有调用m4macro-name,就调用它(不带任何参数)。确保macro-name 用方括号引起来了。macro-name必须已经用AC_DEFUN定义了,或者包含一个对AC_PROVIDE 的调用以指明它已经被调用了。

一个替代AC_DEFUN的方法是使用define并且调用AC_PROVIDE。 因为这个技术并不防止出现嵌套的消息,它已经是过时的了。

宏: AC_PROVIDE (this-macro-name)
记录this-macro-name已经被调用了的事实。this-macro-name应该是调用AC_PROVIDE的宏的名字。 一个获取它的简单方式是从m4内置变量$0中获得,就像:
AC_PROVIDE([$0])
      1. 建议的顺序

AC_BEFORE([$0], [AC_PROG_CPP])dnl

如果在调用AC_PROG_CC时,已经调用了AC_PROG_CPP,它就警告用户。

宏: AC_BEFORE (this-macro-name, called-macro-name)
如果已经调用了called-macro-name,就让m4在标准错误输出上打印一条警告消息。 this-macro-name应该是调用AC_BEFORE的宏的名字。macro-name必须已经用 AC_DEFUN定义了,或者包含一个对AC_PROVIDE的调用以指明它已经被调用了。
      1. 过时的宏

宏: AC_OBSOLETE (this-macro-name [, suggestion])
m4在标准错误输出上打印一条消息以警告this-macro-name是过时的,并且给出调用 过时的宏的文件名和行号。this-macro-name应该是调用AC_OBSOLETE的宏的名字。 如果给出了suggestion,就在警告消息的末尾打印它;例如,它可以建议用某个宏来代替 this-macro-name

手工配置

    1. 指定系统的类型

类似与其它GNU configure脚本,Autoconf生成的configure脚本可以根据系统类型的规范名 (canonical name)做出决定,该规范系统名的形式为:

cpu-company-system

configure通常可以猜测出它正在运行的系统类型的规范名。为此,它运行一个称为config.guess 的脚本,该脚本使用uname或者预定义的C预处理器符号来推断系统类型的规范名。

另外,用户可以通过给configure传递命令行参数而指定系统类型。在交叉编译时必须这样作。 在大多数交叉编译的复杂情况下,要涉及到三种系统类型。用于指定它们的选项是:

–build=build-type
对包进行配置和编译的系统类型(很少用到);
–host=host-type
包将运行的系统类型;
–target=target-type
包中任何编译器工具将生成的代码的系统类型。

如果用户给configure一个非选项参数,如果用户没有显式地用选项指明,它就作为缺省情况表示主机类型、 目标类型和创建系统类型。如果给出了主机类型而没有给出目标类型和创建类型,目标类型和创建类型就被设置为主机类型。 如果你正在交叉编译,你仍然必须在configure的命令行中给出你使用的交叉工具(cross-tools)的名称, 特别是C编译器。例如,

CC=m68k-coff-gcc configure --target=m68k-coff

configure能够识别许多系统类型的短别名;例如,可以在命令行中给出`decstation’而不是 `mips-dec-ultrix4.2′configure运行一个被称为config.sub的脚本以使 系统类型别名规范化。

    1. 获取规范的系统类型

下列的宏使得configure脚本可以获得系统类型。它们运行shell脚本config.guess以确定 用户在命令行中没有给出的、它们需要的关于主机、目标和创建类型的所有值。它们运行config.sub对 用户给出的任何别名进行规范化。
如果你没有使用这些宏中的任意一个,configure 就忽略任何传递给它的`–host’`–target’`–build’选项。
宏: AC_CANONICAL_SYSTEM
检测系统类型并把输出变量设置成规范的系统类型。关于该宏设置变量的细节,参见系统类型变量
宏: AC_CANONICAL_HOST
只执行AC_CANONICAL_SYSTEM中关于主机类型功能的子集。 对于不是编译工具链(compiler toolchain)一部分的程序,这就是所需要的全部功能。
宏: AC_VALIDATE_CACHED_SYSTEM_TUPLE (cmd)
如果缓存文件与当前主机、目标和创建系统类型不一致,就执行cmd或者打印一个缺省的错误消息。
    1. 系统类型变量

在调用了AC_CANONICAL_SYSTEM之后,下列输出变量包含了系统类型信息。在调用了AC_CANONICAL_HOST 之后,只设置了下列host变量。

build, host, target
规范系统名称;
build_alias, host_alias, target_alias
如果使用了config.guess,就是用户指定的名称或者规范名称;
build_cpu, build_vendor, build_os
host_cpu, host_vendor, host_os
target_cpu, target_vendor, target_os
为方便而提供的规范名称的独立部分
    1. 使用系统类型

你将如何使用规范的系统类型?通常,你在`configure.in’中的一个或多个case语句中使用它来 选择系统特定的C文件。而后把那些使用基于系统名的文件名的文件连接到诸如`host.h’`target.c’的 普通的文件上。case语句模型允许使用shell通配符对多种情况进行编组,就像下面的片断:

case "$target" in
i386-*-mach* | i386-*-gnu*) obj_format=aout emulation=mach bfd_gas=yes ;;
i960-*-bout) obj_format=bout ;;
esac
宏: AC_LINK_FILES (source…, dest…)
使得AC_OUTPUT把每个存在文件的source连接到对应连接名dest。 如果可能,创建一个符号连接,否则就创建硬连接。destsource应该是相对于顶层源代码目录或者 创建目录的相对路径。可以多次调用本宏。
例如,下列调用:
AC_LINK_FILES(config/${machine}.h config/${obj_format}.h, host.h object.h)
在当前目录中创建`host.h’,它是一个到`srcdir/config/${machine}.h’的连接, 并且创建`object.h’,它是一个到`srcdir/config/${obj_format}.h’的连接。

你还可以使用主机系统类型以寻找交叉编译工具。关于完成该任务的宏AC_CHECK_TOOL的信息, 参见对普通程序和文件的检查

站点配置

    1. 与外部软件一起工作

有些软件包需要,或者可选地使用其它已经安装的软件包。用户可以把命令行选项传递给configure 以指明使用那个外部软件。选项采用下列形式之一:

--with-package[=arg]
--without-package

例如,`–with-gnu-ld’的意思是使用GNU连接器而不是任何其它连接器。`–with-x’的意思是 使用X Window系统。

对于每个可能使用的外部软件包,`configure.in’都应该调用AC_ARG_WITH以检测 configure的用户是否要求使用它。确定在缺省状态下,是使用还是不使用每个包,以及那个参数是合法的, 是你的任务。

宏: AC_ARG_WITH (package, help-string [, action-if-given [, action-if-not-given]])
如果用户以选项`–with-package’或者`–without-package’调用 configure,就运行shell命令action-if-given。如果两个选项都没有给出,就运行shell命令 action-if-not-given。名字package给出了本程序应该与之协同工作的其它软件包。它应该仅仅由 字母、数字和破折号(dashes)组成。
shell命令action-if-given可以通过shell变量withval得到选项的参数,该变量的值实际上就是把 shell变量with_package的值中的所有`-‘字符替换为`_’而得的。 如果你愿意,可以使用变量with_package
参数help-string是对选项的描述,它看起来应该像:
  --with-readline support fancy command line editing
如果需要给出更多的细节,help-string可能多于一行。只要确保`configure –help’中的列的排列 就可以了。不要在求助字符串中使用tab。你将需要用`[‘`]’包围它以生成前导空格。
    1. 选择包选项

如果软件包含有可选的编译时(compile-time)特征,用户就可以在调用configure时使用命令行选项来指明 是否编译它们。选项采用如下形式之一:

--enable-feature[=arg]
--disable-feature

对于每个可选的特征,`configure.in’都应该调用AC_ARG_ENABLE以检测configure 的用户是否要求把该特征包含进来。确定在缺省情况下,每个特征是否被包含进来,以及那些选项是合法的,是你的任务。

宏: AC_ARG_ENABLE (feature, help-string [, action-if-given [, action-if-not-given]])
如果用户以选项`–enable-feature’或者`–disable-feature’调用 configure,就运行shell命令action-if-given。如果两个选项都没有给出,就运行shell命令 action-if-not-given。名称feature表示可选的用户级功能。它应该仅仅由字母、数字和破折号 (dashes)组成。
shell命令可以通过访问shell变量enableval来得到选项的参数,该变量的值实际上就是把shell变量 enable_feature的值中所有的`-‘字符替换成`_’而得到的。 如果你愿意,可以使用变量enable_featurehelp-string参数类似于 AC_ARG_WITH中相应的参数(参见与外部软件一起工作)。
    1. 配置站点细节

    2. 在安装的时候改变程序的名称

Autoconf支持在安装程序的时候修改程序的名称。为了使用这些变换,`configure.in’必须调用宏 AC_ARG_PROGRAM

宏: AC_ARG_PROGRAM
把对被安装的程序的名称进行替换的sed命令序列存入输出变量program_transform_name中。
如果把下列任意选项传递给了configure,程序名就据此进行变换。 否则,如果已经调用了AC_CANONICAL_SYSTEM并且`–target’的值给出了与主机类型 (用`–host’给出的,或者是在config.sub中设置的缺省值)不同的类型,就把末尾附加了 破折号的目标类型作为前缀。否则,就不进行程序名变换。
      1. 转换选项

你可以把下列命令行选项传递给configure以指定名称的转换:

–program-prefix=prefix
为名称添加前缀prefix
–program-suffix=suffix
为名称添加后缀suffix
–program-transform-name=expression
对名字作sed替换expression
      1. 转换的规则

下面是如何在`Makefile.in’中使用变量program_transform_name

transform=@program_transform_name@
install: all
        $(INSTALL_PROGRAM) myprog $(bindir)/`echo myprog|sed '$(transform)'`

uninstall:
        rm -f $(bindir)/`echo myprog|sed '$(transform)'`

如果你要安装多个程序,你可以通过一个循环来完成:

PROGRAMS=cp ls rm
install:
        for p in $(PROGRAMS); do \
          $(INSTALL_PROGRAM) $$p $(bindir)/`echo $$p|sed '$(transform)'`; \
        done

uninstall:
        for p in $(PROGRAMS); do \
          rm -f $(bindir)/`echo $$p|sed '$(transform)'`; \
        done

是否在文档文件中进行变换(Texinfo或者man)是个麻烦的问题;由于名称变换的几个原因,好像不存在完美的答案。 文档对于特定的结构来说并不特殊,并且Texinfo文件与系统文档并不冲突。但它们可能与同一文件的早期版本冲突,而且 man手册有时与系统文档冲突。作为一个折衷,可能最好是对man手册进行名称替换而不对Texinfo手册 进行替换。

    1. 设定站点缺省值

如果设置了环境变量CONFIG_SITEconfigure就把它的值作为读入的shell脚本的名称。 否则如果`prefix/share/config.site’存在,它就读入该脚本, 否则如果`prefix/etc/config.site’存在,它就读入该脚本。因此,如果出现冲突, 在机器特定文件中的设置将覆盖那些与机器独立的文件中的设置。

如果你需要为其它输出变量设置与缺省值不同的值(你通常不得不在命令行中重复地进行设置),比如说CFLAGS, 站点文件就是进行这种设置的好地方。如果你为prefix或者exec_prefix设置了非缺省值 (你放置站点文件的地方),如果你用环境变量CONFIG_SITE给出了站点文件,你就可以在站点文件中设置 这些非缺省值。

你可以在站点文件中设置一些缓存值。如果你正在进行交叉编译,这样做就是有用的,以避免对需要运行测试程序的特征 进行检查。你可以为`prefix/etc/config.site’中的系统正确地设置这些值来“预备缓存(prime cache)”。 为了找到你要设置的缓存变量名,可以在受到影响的configure脚本中寻找带有`_cv_’shell变量, 也可以在Autoconf m4源代码中寻找这些宏。

缓存文件将十分谨慎而不至于覆盖任何在站点文件中设置的变量。类似地,你不应该在站点文件中覆盖命令行选项。 你的代码应该在修改诸如prefixcache_file的变量之前,检查它们的缺省值(就是在 靠近configure开头的地方设置的值)。

下面是一个例子文件`/usr/share/local/gnu/share/config.site’。 (如果没有把CONFIG_SITE设置成其它文件,)命令`configure –prefix=/usr/share/local/gnu’ 将读入该文件。

# config.site for configure
#
# Change some defaults.
test "$prefix" = NONE && prefix=/usr/share/local/gnu
test "$exec_prefix" = NONE && exec_prefix=/usr/local/gnu
test "$sharedstatedir" = '${prefix}/com' && sharedstatedir=/var
test "$localstatedir" = '${prefix}/var' && localstatedir=/var
#
# Give Autoconf 2.x generated configure scripts a shared default
# cache file for feature test results, architecture-specific.
if test "$cache_file" = ./config.cache; then
  cache_file="$prefix/var/config.cache"
  # A cache file is only valid for one C compiler.
  CC=gcc
fi

重新创建一个配置

configure脚本创建一个名为`config.status’的文件,用它描述在包最后一次进行配置时 给出的配置选项。该文件是一个shell脚本文件,如果运行它,将重新创建相同的配置
你可以用`–recheck’选项调用`config.status’以更新它自身。如果你修改了configure, 该选项是有用的,这是因为某些测试的结果可能会与上一次运行的结果不同。选项`–recheck’以与从前使用的参数 相同的参数,再加上`–no-create’选项以防止configure运行`config.status’并创建 `Makefile’和其它文件,再加上`–no-recursion’选项以防止configure在子目录中运行 其它的configure,来重新运行configure
你可以用`–recheck’选项调用`config.status’以更新它自身。如果你修改了configure, 该选项是有用的,这是因为某些测试的结果可能会与上一次运行的结果不同。选项`–recheck’以与从前使用的参数 相同的参数,再加上`–no-create’选项以防止configure运行`config.status’并创建 `Makefile’和其它文件,再加上`–no-recursion’选项以防止configure在子目录中运行 其它的configure,来重新运行configure

`config.status’还接受选项`–help’,它打印`config.status’接受的选项的概述。 还接受选项`–version’,它打印用于创建生成`config.status’configure脚本的 Autoconf的版本号。

`config.status’检查几个能够改变它的行为的可选的环境变量:

变量: CONFIG_SHELL
用于运行带有`–recheck’选项的configure的脚本。它必须是Bourne兼容的。 缺省shell`/bin/sh’
变量: CONFIG_STATUS
shell脚本提供的,用于记录配置的文件名。缺省的文件名是`./config.status’。该变量在一个包使用了另一个 包的一部分,并且由于两个包是分开维护的而不能把configure合成一个的时候有用。

以下的变量为分开发布的包提供了一种共享由configure计算的结果的方式。如果某些包需要它们中某个包, 可能是一个通用库,所需要的特征的超集那么这样做就是有用的。这些变量允许一个`config.status’文件创建 由它的`configure.in’所指明的文件之外的文件,因此它就可以被用于不同的包。

变量: CONFIG_FILES
用于执行`@variable@’替换的文件。缺省的文件在`configure.in’中作为参数提供给 AC_OUTPUT
变量: CONFIG_HEADERS
用于替换C #define语句的文件。缺省的文件作为参数提供给AC_CONFIG_HEADER; 如果没有调用那个宏,`config.status’就忽略本变量。

这些变量还允许你编写只重新生成一部分文件的`Makefile’规则。例如,在上面给出的依赖性之中 (参见自动地重新创建),在`configure.in’发生改变时, `config.status’将运行两次。如果你对此感到厌烦,你可以使得每次运行都仅仅重新生成关于 那条规则的文件。

config.h: stamp-h
stamp-h: config.h.in config.status
        CONFIG_FILES= CONFIG_HEADERS=config.h ./config.status
        echo > stamp-h

Makefile: Makefile.in config.status
        CONFIG_FILES=Makefile CONFIG_HEADERS= ./config.status

(如果`configure.in’并不调用AC_CONFIG_HEADER,就不必在make规则中设置 CONFIG_HEADERS。)

关于Autoconf的问题

为什么Autoconf需要使用GNU m4

许多m4的实现含有编码性(hard-coded)的,对宏的大小和数量的限制,Autoconf超过了这些限制。 它们还缺少一些内置宏,没有它们,诸如Autoconf之类的复杂应用程序将难以应付,它们包括:

builtin
indir
patsubst
__file__
__line__
    1. 改变了的Makefile

在你的`Makefile.in’文件中添加`@CFLAGS@’`@CPPFLAGS@’`@LDFLAGS@’, 以便它们可以在configure运行的时候利用环境中的这些变量的值。这样做不是必须的,但对用户来说比较方便。

对于AC_OUTPUT的每个非`Makefile’的输入文件,你还应该添加一条含有 `@configure_input@’的注释, 以便输出文件将会包含一条注释以说明它们是由configure生成的。 自动地为每种人们在AC_OUTPUT中输出的文件选择正确的注释语法需要做太多的工作。

`config.log’`config.cache’添加到你要在distclean目标中删除的文件的列表中。

如果你的`Makefile.in’如下:

prefix = /usr/local
exec_prefix = ${prefix}

你必须把它修改成:

prefix = @prefix@
exec_prefix = @exec_prefix@

不使用`@’字符的老式的对这些变量的替换行为已经被删除了。

    1. 改变了的宏

Autoconf2版中,重新命名了许多宏。你仍然可以使用旧名字,但新名字更清晰,并且易于找到相关文档。 关于为旧宏名提供新宏名的列表,参见陈旧的宏名。 用autoupdate程序转换你的`configure.in’以使用新的宏名。 参见autoupdate更新configure

    1. autoupdate更新configure

如果没有给出参数,autoupdate就更新`configure.in’,并且通过添加后缀`~’ (或者在设置了环境变量SIMPLE_BACKUP_SUFFIX的时候,使用该环境变量的值)以备份原始版本。 如果你带参数调用autoupdate,它就读入那个文件而不是读入`configure.in’,并且把 更新的文件输出到标准输出。

autoupdate接受下列选项:

–help
-h
打印命令行选项的概述并且退出。
–macrodir=dir
-m dir
在目录dir中,而不是在缺省安装目录中寻找Autoconf宏文件。 你还可以把环境变量AC_MACRODIR设置成一个目录;本选项覆盖该环境变量。
–version
打印autoupdate的版本号并且退出。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*