Autoconf是一个用于生成可以自动地配置软件源代码包以适应多种Unix类系统的 shell脚本的工具。由Autoconf生成的配置脚本在运行的时候与Autoconf是无关的,就是说配置脚本的用户并不需要拥有Autoconf。
由Autoconf生成的配置脚本在运行的时候不需要用户的手工干预;通常它们甚至不需要通过给出参数以确定系统的类型。相反,它们对软件包可能需要的各种特征进行独立的测试。(在每个测试之前,它们打印一个单行的消息以说明它们正在进行的检测,以使得用户不会因为等待脚本执行完毕而焦躁。)因此,它们在混合系统或者从各种常见Unix变种定制而成的系统中工作的很好。没有必要维护文件以储存由各个Unix变种、各个发行版本所支持的特征的列表。
对于每个使用了Autoconf的软件包,Autoconf从一个列举了该软件包需要的,或者可以使用的系统特征的列表的模板文件中生成配置脚本。在shell代码识别并响应了一个被列出的系统特征之后,Autoconf允许多个可能使用(或者需要)该特征的软件包共享该特征。如果后来因为某些原因需要调整shell代码,就只要在一个地方进行修改;所有的配置脚本都将被自动地重新生成以使用更新了的代码。
Metaconfig包在目的上与Autoconf很相似,但它生成的脚本需要用户的手工干预,在配置一个大的源代码树的时候这是十分不方便的。不象Metaconfig脚本,如果在编写脚本时小心谨慎, Autoconf可以支持交叉编译(cross-compiling)。
Autoconf目前还不能完成几项使软件包可移植的工作。其中包括为所有标准的目标自动创建`Makefile';文件,包括在缺少标准库函数和头文件的系统上提供替代品。目前正在为在将来添加这些特征而工作。
对于在C程序中的#ifdef中使用的宏的名字,Autoconf施加了一些限制(参见预处理器符号索引)。
Autoconf需要GNU m4以便于生成脚本。它使用了某些UNIX版本的m4 所不支持的特征。它还会超出包括GNU m4 1.0在内的某些m4版本的内部限制。你必须使用GNU m4的1.1版或者更新的版本。使用1.3版或者更新的版本将比1.1 或1.2版快许多。
关于从版本1中升级的详情,参见从版本1中升级。关于Autoconf的开发历史,参见Autoconf的历史。对与Autoconf有关的常见问题的回答,参见关于Autoconf的问题。
把关于Autoconf的建议和bug报告发送到bug-gnu-utils@prep.ai.mit.edu。请把你通过运行`autoconf --version';而获得的Autoconf的版本号包括在内。
创建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';。
下面是一个说明了在配置中使用的文件是如何生成的图。运行的程序都标以后缀`*';。可能出现的文件被方括号(`[]';)括起来。autoconf和autoheader 还读取安装了的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 ---';
编写`configure.in';
为了为软件包创建configure脚本,需要编写一个名为`configure.in'; 的文件,该文件包含了对那些你的软件包需要或者可以使用的系统特征进行测试的Autoconf宏的调用。现有的Autoconf宏可以检测许多特征; 对于它们的描述可以参见现有的测试。对于大部分其他特征,你可以使用Autconf模板宏以创建定制的测试;关于它们的详情,参见 编写测试。对于特别古怪或者特殊的特征,`configure.in'; 可能需要包含一些手工编写的shell命令。程序autoscan可以为你编写`configure.in'; 开个好头(详情请参见用autoscan创建`configure.in';)。
除了少数特殊情况之外,在`configure.in';中调用Autoconf宏的顺序并不重要。在每个`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...])
最好让每个宏调用在`configure.in';中占据单独的一行。大部分宏并不添加额外的新行;它们依赖于在宏调用之后的新行以结束命令。这种方法使得生成的configure脚本在不必添加大量的空行的情况下比较容易阅读。在宏调用的同一行中设置shell变量通常是安全的,这是因为shell允许出现没有用新行间隔的赋值。
在调用带参数的宏的时候,在宏名和左括号之间不能出现任何空格。如果参数被m4 引用字符`[';和`]';所包含,参数就可以多于一行。如果你有一个长行,比如说一个文件名列表,你通常可以在行的结尾使用反斜线以便在逻辑上把它与下一行进行连接(这是由shell实现的,Autoconf对此没有进行任何特殊的处理)。
有些宏处理两种情况:如果满足了某个给定的条件就做什么,如果没有满足某个给定的条件就做什么。在有些地方,你可能希望在条件为真的情况下作些事,在为假时什么也不作。反之亦然。为了忽略为真的情况,把空值作为参数action-if-found传递给宏。为了忽略为假的情况,可以忽略包括前面的逗号在内的宏的参数action-if-not-found。
你可以在文件`configure.in';中添加注释。注释以m4预定义宏dnl 开头,该宏丢弃在下一个新行之前的所有文本。这些注释并不在生成的configure脚本中出现。例如,把下面给出的行作为文件`configure.in';的开头是有好处的:
dnl Process this file with autoconf to produce a configure script.
用autoscan创建`configure.in';
程序autoscan可以帮助你为软件包创建`configure.in';文件。如果在命令行中给出了目录, autoscan就在给定目录及其子目录树中检查源文件,如果没有给出目录,就在当前目录及其子目录树中进行检查。它搜索源文件以寻找一般的移植性问题并创建一个文件`configure.scan';,该文件就是软件包的`configure.in';预备版本。
在把`configure.scan';改名为`configure.in';之前,你应该手工地检查它;它可能需要一些调整。 autoscan偶尔会按照相对于其他宏的错误的顺序输出宏,为此autoconf将给出警告;你需要手工地移动这些宏。还有,如果你希望包使用一个配置头文件,你必须添加一个对AC_CONFIG_HEADER的调用。(参见配置头文件)。可能你还必须在你的程序中修改或者添加一些#if 指令以使得程序可以与Autoconf合作。(关于有助于该工作的程序的详情,参见 用ifnames列举条件)。
autoscan使用一些数据文件,它们是随发布的Autoconf宏文件一起安装的,以便当它在包中的源文件中发现某些特殊符号时决定输出那些宏。这些文件都具有相同的格式。每一个都是由符号、空白和在符号出现时应该输出的Autoconf 宏。以`#';开头的行是注释。
只有在你安装了Perl的情况下才安装autoscan。 autoscan接受如下选项:
--help
打印命令行选项的概述并且退出。
--macrodir=dir
在目录dir中,而不是在缺省安装目录中寻找数据文件。你还可以把环境变量AC_MACRODIR设置成一个目录;本选项将覆盖该环境变量。
--verbose
打印它检查的文件名称以及在这些文件中发现的可能感兴趣的符号。它的输出可能很冗长。
--version
打印Autoconf的版本号并且退出。
用ifnames列举条件
在为一个软件包编写`configure.in';时,ifnames可以提供一些帮助。它打印出包已经在C预处理条件中使用的标识符。如果包已经被设置得具备了某些可移植性,该程序可以帮助你找到configure所需要进行的检查。它可能有助于补足由autoscan生成的`configure.in';中的某些缺陷。(参见用autoscan创建`configure.in';)。
ifnames扫描所有在命令行中给出的C源代码文件(如果没有给出,就扫描标准输入)并且把排序后的、由所有出现在这些文件中的#if、#elif、#ifdef或者#ifndef 命令中的标识符列表输出到标准输出中。它为每个标识符输出单独的一行,行中标识符之后是一个由空格分隔的、使用了该标识符的文件名列表。
ifnames接受如下选项:
--help
-h
打印命令行选项的概述并且退出。
--macrodir=dir
-m dir
在目录dir中,而不是缺省安装目录中寻找Autoconf宏文件。仅仅被用于获取版本号。你还可以把环境变量AC_MACRODIR设置成一个目录;本选项将覆盖该环境变量。
--version
打印Autoconf的版本号并且退出。
用autoconf创建configure
为了从`configure.in';生成configure,不带参数地运行程序autoconf。 autoconf用使用Autoconf宏的m4宏处理器处理`configure.in';。如果你为autoconf提供了参数,它读入给出的文件而不是`configure.in';并且把配置脚本输出到标准输出而不是configure。如果你给autoconf以参数`-';,它将从标准输入,而不是`configure.in';中读取并且把配置脚本输出到标准输出。
Autoconf宏在几个文件中定义。在这些文件中,有些是与Autconf一同发布的;autoconf首先读入它们。而后它在包含了发布的Autoconf宏文件的目录中寻找可能出现的文件`acsite.m4';,并且在当前目录中寻找可能出现的文件`aclocal.m4';。这些文件可以包含你的站点的或者包自带的Autoconf宏定义(详情请参见 编写宏)。如果宏在多于一个由autoconf读入了的文件中被定义,那么后面的定义将覆盖前面的定义。
autoconf接受如下参数:
--help
-h
输出命令行选项的概述并且退出。
--localdir=dir
-l dir
在目录dir中,而不是当前目录中寻找包文件`aclocal.m4';。
--macrodir=dir
-m dir
在目录dir中寻找安装的宏文件。你还可以把环境变量AC_MACRODIR设置成一个目录;本选项将覆盖该环境变量。
--version
打印Autoconf的版本号并且退出。
用autoreconf更新configure脚本
如果你有大量由Autoconf生成的configure脚本,程序autoreconf可以保留你的一些工作。它重复地运行autoconf(在适当的情况下还运行autoheader)以重新创建以当前目录为根的目录树的Autoconf configure脚本和配置头文件。在缺省情况下,它只重新创建那些比对应的 `configure.in';或者(如果出现)`aclocal.m4';要旧的文件。由于在文件没有被改变的情况下, autoheader并不改变它的输出文件的时间标记(timestamp)。这是为了使工作量最小化,修改时间标记是不必要的。如果你安装了新版本的Autoconf,你可以以选项`--force';调用autoreconf而重新创建 所有的文件。
如果你在调用autoreconf时给出选项`--macrodir=dir';或者 `--localdir=dir';,它将把它们传递给autoconf和autoheader (相对路径将被正确地调整)。
在同一个目录树中,autoreconf不支持两个目录作为同一个大包的一部分(共享`aclocal.m4';和 `acconfig.h';),也不支持每个目录都是独立包(每个目录都有它们自己的`aclocal.m4';和 `acconfig.h';)。如果你使用了`--localdir';,它假定所有的目录都是同一个包的一部分。如果你没有使用 `--localdir';,它假定每个目录都是一个独立的包,这条限制在将来可能被取消。
关于在configure脚本的源文件发生变化的情况下自动地重新创建它们的`Makefile';规则的细节,参见自动地重新创建。这种方法正确地处理了配置头文件模板的时间标记,但并不传递`--macrodir=dir';或者`--localdir=dir';。
autoreconf接受如下选项:
--help
-h
打印命令行选项的概述并且退出。
--force
-f
即使在`configure';脚本和配置头文件比它们的输入文件(`configure.in';,如果出现了`aclocal.m4';,也包括它)更新的时候,也要重新创建它们。
--localdir=dir
-l dir
让autoconf和autoheader在目录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的版本号并且退出。
初始化和输出文件
Autoconf生成的configure脚本需要一些关于如何进行初始化,诸如如何寻找包的源文件,的信息;以及如何生成输出文件的信息。本节叙述如何进行初始化和创建输出文件。
寻找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';的规则,所以那个名字过时了。
创建输出文件
每个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_HEADER、AC_LINK_FILES或者AC_CONFIG_SUBDIRS,本宏也将创建出现在它们的参数中的文件。
一个典型的对AC_OUTPUT调用如下:
AC_OUTPUT(Makefile src/Makefile man/Makefile X/Imakefile)
你可以通过在file之后添加一个用冒号分隔的输入文件列表以自行设定输入文件名。例如:
AC_OUTPUT(Make文件:templates/top.mk lib/Make文件:templates/lib.mk)
AC_OUTPUT(Make文件: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@
Makefiles中的替换
发布版本中每个包含了需要被编译或者被安装的文件的目录都应该含有一个文件`Makefile.in';, configure将利用它在那个目录中创建一个`Makefile';。为了创建`Makefile';,configure进行一个简单的变量替换:用configure 为`@variable@';选取的值,在`Makefile.in';中对它们进行替换。按照这种方式被替换到输出文件中的变量被称为输出变量。在configure中,它们是普通的shell变量。为了让configure把特殊的变量替换到输出文件中,必须把那个变量的名字作为调用 AC_SUBST的参数。其他变量的任何`@variable@';都保持不变。关于使用AC_SUBST创建输出变量的详情,请参见设定输出变量。
使用configure脚本的软件应该发布文件`Makefile.in';,而不是`Makefile';;这样,用户就可以在编译它之前正确地为本地系统进行配置了。
关于应该把哪些东西放入`Makefile';的详情,请参见GNU编码标准中的`Makefile惯例';。
预定义输出变量
有些输出变量是由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_HEADER,configure就用 `-DHAVE_CONFIG_H';代替`@DEFS@';(参见配置头文件)。在configure进行它的测试时,本变量没有被定义,只有在创建输出文件时候才定义。关于如何检查从前的测试结果,请参见设定输出变量。
变量: LDFLAGS
为连接器提供的Stripping(`-s';)选项和其他各种选项。如果在运行configure时,在环境中没有设置本变量,它的缺省值就是空。 configure在连接程序以测试C的特征时使用本变量。
变量: LIBS
传递给连接器的`-l';和`-L';选项。
创建目录
你可以支持从一个软件包的一份源代码拷贝中为多种结构同时进行编译的功能。为每种结构生成的目标文件都在它们自己的目录中储存。
为了支持这个功能,make用变量VPATH来寻找储存在源代码目录中的文件。 GNU make和其他大部分近来的make程序都可以这样做。老版本的make 程序不支持VPATH;在使用它们的时候,源代码必须与目标代码处于同一个目录。
为了支持VPATH,每个`Makefile.in';文件都应该包含下列两行:
srcdir = @srcdir@
VPATH = @srcdir@
不要把VPATH设置成其他变量的值,比如说`VPATH = $(srcdir)';,这是因为某些版本的make并不对VPATH的值进行变量替换。
在configure生成`Makefile';的时候,它用正确的值对srcdir进行替换。
除非在隐含规则中,不要使用make变量$<,它将被展开成到源代码目录的文件的路径(通过VPATH找到的)。(诸如`.c.o';的隐含规则用于说明如何从`.c'; 文件创建`.o';文件)有些版本的make在隐含规则中不设置$<;它们被展开成空值。
`Makefile';命令行总是应该通过使用前缀`$(srcdir)/';来引用源代码文件。例如:
time.info: time.texinfo
$(MAKEINFO) $(srcdir)/time.texinfo
自动地重新创建
你可以在包的顶层目录中的`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
Make文件: 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的详情,请参见 创建输出文件。
关于处理与配置相关的依赖性问题的更多例子,请参见重新创建一个配置。
配置头文件
在包测试的C预处理器符号比较多的时候,用于把`-D';传递给编译器的命令行就会变得很长。这导致了两个问题。一个是通过观察寻找make输出中的错误变得困难了。更严重的是,命令行可能超过某些操作系统的长度限制。作为把`-D';选项传递给编译器的替代办法,configure 脚本可以创建一个包含了`#define';指令的C头文件。宏AC_CONFIG_HEADER 选择了这种输出。它应该在AC_INIT之后立即调用。
包应该在引入其他任何头文件之前`#include';配置头文件,以防止出现声明中的不一致性(例如,配置头文件可能重定义了const)。使用`#include '; 并且把选项`-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)添加到文件的开头和/或结尾。
配置头文件模板
你的发布版本应该包含一个如你所望的最终的头文件那样的模板文件,它包括注释、以及#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
用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_HEADERS、AC_CHECK_FUNCS、AC_CHECK_SIZEOF或者 AC_CHECK_LIB定义的符号,autoheader生成注释和#undef语句,而不是从一个文件中复制它们,这是因为可能的符号是无限的。
autoheader创建的文件包含了大部分#define和#undef语句,以及相关的注释。如果`./acconfig.h';包含了字符串`@TOP@';,autoheader就把在包含`@TOP@'; 的行之前的所有行复制到它生成的文件的开头。相似地,如果`./acconfig.h';包含了字符串`@BOTTOM@';, autoheader就把那一行之后的所有行复制到它生成的文件的末尾。这两个字符串的任何一个都可以被忽略,也可以被同时忽略。
产生相同效果的另一种办法是在当前目录中创建文件`file.top';(通常是`config.h.top';)和/或文件`file.bot';。如果它们存在,autoheader就把它们分别复制到它的输出的开头和末尾。不鼓励使用它们是因为它们的文件名含有两个点,并因此不能在MS-DOS中储存;它们在目录中多创建了两个文件。但如果你给出选项`--localdir=dir';以使用在其他目录中的`acconfig.h';,它们就为你提供了一种把定制的模板(boilerplate)放入各个独立的`config.h.in';中的方式。
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的版本号并且退出。
在子目录中配置其它包
在大多数情况下,调用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脚本。
用与本configure脚本完全相同的命令行参数调用子目录中的configure脚本,如果需要,会有较小的修改(例如,为缓冲文件或者源代码目录调整相对路径)。本宏还把输出变量subdirs设置成目录列表`dir...';。`Makefile';规则可以使用该变量以确定需要进入那些子目录。这个宏可以多次调用。
缺省的前缀
在缺省状态下,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';中给定的前缀。例如,如果program是 gcc,并且PATH包括了`/usr/local/gnu/bin/gcc';,就把前缀设置为 `/usr/local/gnu';。
configure中的版本号
以下的宏为configure脚本管理版本号。使用它们是可选的。
宏: AC_PREREQ (version)
确保使用的是足够新的Autoconf版本。如果用于创建configure的Autoconf的版本比version 要早,就在标准错误输出打印一条错误消息并不会创建configure。例如:
AC_PREREQ(1.8)
如果你的`configure.in';依赖于在不同Autoconf版本中改变了的、不明显的行为,本宏就是有用的。如果它仅仅是需要近来增加的宏,那么AC_PREREQ就不太有用,这是因为程序autoconf已经告诉了用户那些宏没有被找到。如果`configure.in';是由一个在提供AC_PREREQ之前的更旧的 Autoconf版本处理的,也会发生同样的事。
宏: AC_REVISION (revision-info)
把删除了任何美元符或者双引号的修订标记(revision stamp)复制到configure脚本中。本宏使得你的从`configure.in';传递到configure的修订标记不会在你提交(check in) configure的时候被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
现有的测试
这些宏测试了包可能需要或者需要使用的特定的系统特征。如果你要测试这些宏所不能测试的特征,可能你可以用适当的参数调用主测试宏来达到目的(参见编写测试)。
这些宏打印消息以告诉用户它们正在测试的特征,以及它们的测试结果。它们为未来运行的configure 储存测试结果(参见缓存结果)。
在这些宏中,有的宏设置输出变量。关于如何获取它们的值,请参见Makefile中的替换。在下面出现的术语“定义name”是“把C预处理符号name定义成1”的简称。关于如何把这些符号的定义放入你的程序中,参见定义C预处理器符号。
|