Autoconf学习——编写configure脚本

3 Making configure Scripts

Autoconf产生的配置脚本通常叫做configure。configure运行的时候会产生几个文件,这几个文件包含了有合适的值的配置参数。

configure产生的文件包括:

  • 一个或者多个Makefile文件,通常每个子目录包含一个(see Makefile Substitutions);
  • 可选的一个C头文件,文件名是可配置的,包含#define 指令 (see Configuration Headers);
  • config.status——一个shell script——运行时重产生上述文件 (see config.status Invocation);
  • 通常命名为config.cache的文件 (运行`configure --config-cache'时产生的),保存测试产生的结果 (see Cache Files);
  • config.log文件——记录编译器产生的一切消息,当configure出错时帮助调试。

为了使用Autoconf产生configure文件,必须创建Autoconf输入文件configure.ac(configure.in)并在其上运行Autoconf。如果你想增加自己的特性测试,那么就要编写名称为aclocal.m4和acsite.m4的文件。如果想编写包含#define指令的C头文件,则必须运行autoheader,这将产生config.h.in文件。

下面这个图展示了在configuration中使用的文件怎样被产生。被执行的程序后缀为“*”。可选的文件使用“[]”括起。autoconf和autoheader也读取安装的Autoconf宏文件(也就是autoconf.m4)。

Files used in preparing a software package for distribution:
     your source files --> [autoscan*] --> [configure.scan] --> configure.ac

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

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

Files used in configuring a software package:

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

3.1 Writing ‘configure.ac’

为一个软件包产生一个配置脚本,需要创建一个configure.ac文件,该文件包含了用于测试软件包需要或者能够使用的系统特性的Autoconf宏的调用。Autoconf宏已经存在并
用于检查多个特性。如果要检查更多的特性,可以使用Autoconf模板宏自定义检查。对于特别重要或特定的属性,configure.ac可能需要包含手工写的shell命令。autoscan程
序能帮助你编写configure.ac文档。
先前版本的Autoconf使用的是configure.in,这可能有点模糊(需要处理该文件的工具在其扩展中并没有描述),且与config.h.in会有点混淆(.in意味着由configure处理)。现在
推荐使用configure.ac。

3.1.1 A Shell Script Compiler
shell脚本并不是在所有系统上都能运行,所以我们需要某种编译器——autoconf,运行一个Autoconf程序——'configure.ac',然后把它转换成可移植的shell脚本——configure。
Autoconf在现有的sh上进行封装,对于autoconf的实现很多是作为一个宏扩展器(macro expander):在输入文本上重复执行宏扩展,使用宏的文本值来代替宏名,最后产生一个纯粹的sh脚本。
我们不实现一个专用的Autoconf宏扩展器,而是使用已经存在的通用宏语言,如M4,并且实现扩展作为一个M4宏的集合。

3.1.2 The Autoconf Language
Autoconf语言与很多计算机语言是不同的,它对待实际代码为普通文本。例如,在C语言中数据和指令有不同的语法状态,但在Autoconf中他们就是一样的。因此,我们需要从要被扩展的文本中区别出字符串常量:
引用。

当调用带参的宏时,在宏名和圆括号之间不能有任何空白符。参数应该被封闭在M4的引用字符“【】”中,用逗号分隔。在参数前面的空格或者行号都会被忽略,除非被引用。也就是说,参数如果是另一个宏调用或者
出现逗号用“[]”括起,不管这个参数是什么表达式。参数与参数之间必须用逗号分隔。参数列表用“()”括起来,参数名和“()”之间不能有空白符。
例如:
AC_CHECK_HEADER([stdio.h],
[AC_DEFINE([HAVE_STDIO_H], [1],
[Define to 1 if you have <stdio.h>.])],
[AC_MSG_ERROR([Sorry, can’t do anything for you])])
是正确的,也可以进行简化:
AC_CHECK_HEADER([stdio.h],
[AC_DEFINE([HAVE_STDIO_H], 1,
[Define to 1 if you have <stdio.h>.])],
[AC_MSG_ERROR([Sorry, can’t do anything for you])])
因为'1'不能够包含一个宏调用。
Cautious Autoconf users would keep
the quotes, but many Autoconf users find such precautions annoying, and would rewrite
the example as follows:
AC_CHECK_HEADER(stdio.h,
[AC_DEFINE(HAVE_STDIO_H, 1,
[Define to 1 if you have <stdio.h>.])],
[AC_MSG_ERROR([Sorry, can’t do anything for you])])
这样写也是安全的,只要你命名命得好,保证宏名的定义不会是“HAVE_STDIO_H”,“stdio”,或者“h”。尽管这儿“Define to 1 if you have <stdio.h>.”可以不用“[]”,但是不推荐,因为一个消息字符串出现逗号的
概率是很大的。

下面的例子是错误且十分危险的:
AC_CHECK_HEADER(stdio.h,
AC_DEFINE(HAVE_STDIO_H, 1,
Define to 1 if you have <stdio.h>.),
AC_MSG_ERROR([Sorry, can’t do anything for you]))

在其他情况,你可能不得不使用到看起来像一个宏调用的文本。你必须把这部分文本用“[]”括起来,即使它并不是一个参数:
8 Autoconf
echo "Hard rock was here! --[AC_DC]"
which results in:
echo "Hard rock was here! --AC_DC"

为所有的字符串常量使用双层的引号是一个好主意:
AC_MSG_WARN([[AC_DC stinks --Iron Maiden]])

一条主要的规则就是无论什么时候你期待宏扩展,那么也期待引号扩展,也就是说这两者一般都是在一起的。例如,期待一级的引号被丢失。举例:

AC_COMPILE_IFELSE([char b[10];], [], [AC_MSG_ERROR([you lose])])是不正确的。

AC_COMPILE_IFELSE的第一个参数是 ‘char b[10];’ 并被扩展一次,这将导致‘char b10;’。作者的意思是第一个参数按字符串常量理解——"char b[10];",所以我们应该这样写:
AC_COMPILE_IFELSE([[char b[10];]], [], [AC_MSG_ERROR([you lose])])

另外一方面,描述(例如AC_DEFINE或AS_HELP_STRING宏的最后一个参数)不是字面常量——譬如他们受制于line breaking——不用对他们使用双重引号。即使这些描述是减短的
且实际上没有broken,双重引号将导致古怪的结果。
一些宏带有可选的参数,使用[arg]这种形式来表示,注意这里的“[]”不是前面说的引号。如果没有值,你只要留空或者使用'[]'即可,或者简单地省略尾部的逗号(这个可选参数是在参数列表的末尾)。
下面三行是等价的:
AC_CHECK_HEADERS([stdio.h], [], [], [])
AC_CHECK_HEADERS([stdio.h],,,)
AC_CHECK_HEADERS([stdio.h])

在configure.ac中,每一个宏调用最好由单独的一行。大部分宏并不添加额外的新行,在宏调用之后依赖于新行来结束命令。
在与宏调用的同一行上进行shell变量赋值是安全的,也就是将宏赋给shell变量?应该是的。
configure.ac文件中注释的起始符号是“#”。

3.1.3 Standard ‘configure.ac’ Layout

configure.ac调用Autoconf宏的顺序并不重要,除了个别情况。譬如,AC_INIT必须在check之前调用,而AC_OUTPUT必须在结尾调用,某些宏的运行会检查一些宏是否已经先运行。
一些变量决定了运行什么。这些宏被告知独立的描述,如果某些运行顺序混乱,他们也会告知用户。

为了保证一致性,这儿有一个调用Autoconf宏的建议顺序。将可能会被其他宏影响的宏尽量往后放,譬如宏函数会被类型和函数库影响。

Autoconf requirements
AC_INIT(package, version, bug-report-address)
information on the package
checks for programs
checks for libraries
checks for header files
checks for types
checks for structures
checks for compiler characteristics
checks for library functions
checks for system services
AC_CONFIG_FILES([file...])
AC_OUTPUT

3.2 Using autoscan to Create configure.ac


autoscan程序能够帮助你为一个软件包创建/维护一个configure.ac文件。autoscan根据作为一个命令行参数指定的目录作为根位置(如果没有指定则是当前工作目录)扫描检查整个目录树中的文件。它为了通用可
移植性问题搜查源文件,并创建一个configure.scan文件,该文件是configure.ac文件的前身,并且为了完整性检查存在的configure.ac文件。


在你要将configure.scan文件重命名为configure.ac之前,需要仔细检查一下该文件,譬如宏调用的顺序有问题。如果你想要包含一个配置头文件,那么可以使用AC_CONFIG_HEADERS宏(Configuration Headers)
。你可能不得不改变或者添加#if指令到你的程序中与Autoconf一起工作(ifnames Invocation)。

当使用autoscan来维护configure.ac文件的时候,简单地考虑添加它的建议。autoscan.log文件包含了一个宏为什么被请求的详细信息。

当autoscan在一个包的源代码文件中找到特殊的呼号时它使用几个数据文件(与Autoconf安装在一起)来决定输出哪个宏。这几个文件都有同样的格式:每一行由一个符号,一个或多个空格,对应该符号要输出的宏。
autoscan接受下面的选项:
--help
-h
Print a summary of the command line options and exit.

--version
-V
Print the version number of Autoconf and exit.

--verbose
-v
Print the names of the files it examines and the potentially interesting
symbols it finds in them. This output can be voluminous.

--debug
-d
Don't remove temporary files.

--include=dir
-I dir
Append dir to the include path. Multiple invocations accumulate.

--prepend-include=dir
-B dir
Prepend dir to the include path. Multiple invocations accumulate.

3.3 Using ifnames to List Conditionals


ifnames能够帮助你编写某一个软件包的configure.ac文件。它打印标识符——该软件包已经在C预处理条件中使用。如果一个包已经被设置为可移植的,ifnames能够帮助你指出它需要检查的配置。

ifnames扫描在命令行指定的C源文件(如果没有指定,则扫描标准输入的内容),并将输入中出现在#if,#elif,#ifdef或者#ifndef指令中的所有标识符按照顺序输出到标准输出中。每个标识符一行,后

面跟着出现该标识符的文件列表。


ifnames接受下列选项:
--help
-h
Print a summary of the command line options and exit.

--version
-V
Print the version number of Autoconf and exit.

3.4 Using autoconf to Create configure


要创建configure.ac文件,运行autoconf程序,没有任何参数。autoconf使用Autoconf宏调用M4宏处理器处理configure.ac文件。如果你指定autoconf一个参数,它将读取指定的文件而不是configure.ac,并且

写配置文件到标准输出而不是configure文件。
如果你给autoconf的参数是-,那么它将从标准输入中读入并将结果写出到标准输出。


Auto宏定义在几个文件中。一些文件跟着Autoconf一起发布,autoconf首先读取他们。然后再读取发布的Autoconf宏文件的目录中的可选acsite.m4文件,以及当前目录的aclocal.m4文件。这些文件可以包含
你的站点的或者软件包的自定义的Autoconf宏定义( Writing Autoconf Macros)。如果一个宏在autoconf读取的多个文件中定义,那么最后一个的定义将会覆盖掉前面的定义。

autoconf接受下列的选项:


--help
-h
Print a summary of the command line options and exit.

--version
-V
Print the version number of Autoconf and exit.

--verbose
-v
Report processing steps.

--debug
-d
Don't remove the temporary files.

--force
-f
Remake configure even if newer than its input files.

--include=dir
-I dir
Append dir to the include path. Multiple invocations accumulate.

--prepend-include=dir
-B dir
Prepend dir to the include path. Multiple invocations accumulate.

--output=file
-o file
Save output (script or trace) to file. The file - stands
for the standard output.

--warnings=category
-W category
Report the warnings related to category (which can actually be a
comma separated list). See Reporting Messages, macro
AC_DIAGNOSE, for a comprehensive list of categories. Special
values include:
`all'
report all the warnings

`none'
report none

`error'
treats warnings as errors

`no-category'
disable warnings falling into category

Warnings about `syntax' are enabled by default, and the environment
variable WARNINGS, a comma separated list of categories, is
honored as well. Passing -W category actually behaves as if
you had passed --warnings syntax,$WARNINGS,category. If
you want to disable the defaults and WARNINGS, but (for example)
enable the warnings about obsolete constructs, you would use -W
none,obsolete
.


Because autoconf uses autom4te behind the scenes, it
displays a back trace for errors, but not for warnings; if you want
them, just pass -W error. See autom4te Invocation, for some
examples.


--trace=macro[:format]
-t macro[:format]
Do not create the configure script, but list the calls to
macro according to the format. Multiple --trace
arguments can be used to list several macros. Multiple --trace
arguments for a single macro are not cumulative; instead, you should
just make format as long as needed.

The format is a regular string, with newlines if desired, and
several special escape codes. It defaults to `$f:$l:$n:$%'; see
autom4te Invocation, for details on the format.


--initialization
-i
By default, --trace does not trace the initialization of the
Autoconf macros (typically the AC_DEFUN definitions). This
results in a noticeable speedup, but can be disabled by this option.

It is often necessary to check the content of a configure.ac
file, but parsing it yourself is extremely fragile and error-prone. It
is suggested that you rely upon --trace to scan
configure.ac. For instance, to find the list of variables that
are substituted, use:


     $ autoconf -t AC_SUBST
configure.ac:2:AC_SUBST:ECHO_C
configure.ac:2:AC_SUBST:ECHO_N
configure.ac:2:AC_SUBST:ECHO_T
More traces deleted
 

下面的例子列出`$@',
`$*', and `$%'之间的不同。


     $ cat configure.ac
AC_DEFINE(This, is, [an
[example]])
$ autoconf -t 'AC_DEFINE:@: $@
*: $*
%: $%'
@: [This],[is],[an
[example]]
*: This,is,an
[example]
%: This:is:an [example]

The format gives you a lot of freedom:


     $ autoconf -t 'AC_SUBST:$$ac_subst{"$1"} = "$f:$l";'
$ac_subst{"ECHO_C"} = "configure.ac:2";
$ac_subst{"ECHO_N"} = "configure.ac:2";
$ac_subst{"ECHO_T"} = "configure.ac:2";
More traces deleted

A long separator can be used to improve the readability of complex
structures, and to ease their parsing (for instance when no single
character is suitable as a separator):


     $ autoconf -t 'AM_MISSING_PROG:${|:::::|}*'
ACLOCAL|:::::|aclocal|:::::|$missing_dir
AUTOCONF|:::::|autoconf|:::::|$missing_dir
AUTOMAKE|:::::|automake|:::::|$missing_dir
More traces deleted

3.5 Using autoreconf to Update configure Scripts


autopoint-- Gettext
automake -- Makefile.in etc. in each directory.
因为一些工具如automake已经被更新,或者一些源文件如configure.ac已经被更新,或者只是为了重新安装GNU Build系统,都需要重新安装各个组件。
autoreconf运行autoconf,autoheader,aclocal,automake,libtoolize和autopoint重新更新特定目录以及其子目录(see Subdirectories)的GNU Build系统。默认情况下,它只更新比源文件老的文件。

环境变量AUTOCONF,AUTOHEADER,AUTOMAKE,ACLOCAL,AUTOPOINT,LIBTOOLIZE,M4和MAKE可能被用于覆盖 各个工具的调用。


如果你安装了一些工具的新版本,你可以调用autoreconf重生产生所有的文件,只要给它指定一个--force选项即可。

See Automatic Remaking, for Make rules to automatically
rebuild configure scripts when their source files change. That
method handles the timestamps of configuration header templates
properly, but does not pass --autoconf-dir=dir or
--localdir=dir.

Gettext supplies the autopoint command to add translation
infrastructure to a source package. If you use autopoint,
your configure.ac should invoke both AM_GNU_GETTEXT and
AM_GNU_GETTEXT_VERSION(gettext-version). See Invoking the autopoint Program, for further details.


autoreconf accepts the following options:

--help
-h
Print a summary of the command line options and exit.

--version
-V
Print the version number of Autoconf and exit.

--verbose
-V
Print the name of each directory autoreconf examines and the
commands it runs. If given two or more times, pass --verbose
to subordinate tools that support it.

--debug
-d
Don't remove the temporary files.

--force
-f
Remake even configure scripts and configuration headers that are
newer than their input files (configure.ac and, if present,
aclocal.m4).

--install
-i
Install the missing auxiliary files in the package. By default, files
are copied; this can be changed with --symlink.

If deemed appropriate, this option triggers calls to
`automake --add-missing',
`libtoolize', `autopoint', etc.


--no-recursive
Do not rebuild files in subdirectories to configure (see Subdirectories,
macro AC_CONFIG_SUBDIRS).

--symlink
-s
When used with --install, install symbolic links to the missing
auxiliary files instead of copying them.

--make
-m
When the directories were configured, update the configuration by
running `./config.status --recheck && ./config.status', and then
run `make'.

--include=dir
-I dir
Append dir to the include path. Multiple invocations accumulate.
Passed on to autoconf and autoheader internally.

--prepend-include=dir
-B dir
Prepend dir to the include path. Multiple invocations accumulate.
Passed on to autoconf and autoheader internally.

--warnings=category
-W category
Report the warnings related to category (which can actually be a
comma separated list).
`cross'
related to cross compilation issues.

`obsolete'
report the uses of obsolete constructs.

`portability'
portability issues

`syntax'
dubious syntactic constructs.

`all'
report all the warnings

`none'
report none

`error'
treats warnings as errors

`no-category'
disable warnings falling into category

Warnings about `syntax' are enabled by default, and the environment
variable WARNINGS, a comma separated list of categories, is
honored as well. Passing -W category actually behaves as if
you had passed --warnings syntax,$WARNINGS,category. If
you want to disable the defaults and WARNINGS, but (for example)
enable the warnings about obsolete constructs, you would use -W
none,obsolete
.



If you want autoreconf to pass flags that are not listed here
on to aclocal, set ACLOCAL_AMFLAGS in your Makefile.am.
Due to a limitation in the Autoconf implementation these flags currently
must be set on a single line in Makefile.am, without any
backslash-newlines.

posted @ 2011-03-16 14:59  茫茫深海一条鱼  阅读(16962)  评论(0编辑  收藏  举报