新闻  |   论坛  |   博客  |   在线研讨会
autoconf手册(六)
patton | 2008-07-03 09:35:47    阅读:2585   发布文章

AC_DEFINE(EQUATION, "$a > $b")
宏: AC_DEFINE_UNQUOTED (variable [, value [, description]])
类似于AC_DEFINE,但还要对variable和value进行三种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")

设置输出变量
记录测试结果的一种方式是设置输出变量,该变量是shell变量,它的值将被替换到configure输出的文件中。下面的两个宏创建新的输出变量。关于总是可用的输出变量的列表,参见预定义输出变量。
宏: AC_SUBST (variable)
从一个shell变量创建一个输出变量。让AC_OUTPUT把变量variable替换到输出文件中(通常是一个或多个 `Makefile')。这意味着AC_OUTPUT将把输入文件中的`@variable@'实例替换成调用AC_OUTPUT时shell变量variable的值。variable的值不能包含新行。
宏: AC_SUBST_FILE (variable)
另一种从shell变量创建输出变量的方式。让AC_OUTPUT把由shell变量variable给出的文件名的文件的内容(不进行替换)插入到输出文件中。这意味着AC_OUTPUT将在输出文件中(比如`Makefile.in')把输入文件中的`@variable@'实例替换为调用AC_OUTPUT时shell变量variable的值指明的文件的内容。如果没有文件可以插入,就把变量设置成`/dev/null'。

本宏用于把包含特殊依赖性或者为特殊主机或目标机准备的其它make指令的`Makefile'片断插入 `Makefile'。例如,`configure.in'可以包含:

AC_SUBST_FILE(host_frag)dnl
host_frag=$srcdir/conf/sun4.mh

那么`Makefile.in'就应该包含:

@host_frag@

缓存结果
为了避免在各种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-id和commands为参数调用AC_CACHE_VAL,最后以cache-id为参数调用AC_MSG_RESULT。
宏: AC_CACHE_LOAD
从已经存在的缓存文件中装入值,如果找不到缓存文件,就创建一个新的缓存文件。本宏由AC_INIT自动调用。
宏: AC_CACHE_SAVE
把所有缓存的值刷新到缓存文件中。本宏由AC_OUTPUT自动调用,但在configure.in的关键点调用 AC_CACHE_SAVE是十分有用的。假如配置脚本中途失败(abort)了,这些关键点仍然可以缓存一部分结果。

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

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')或者文件名或者函数名;所以,这并不是一个重要的限制。

缓存文件
缓存文件是一个缓存了在一个系统上进行配置测试的结果,以便在配置脚本和配置的运行之间共享的shell脚本。它对于其他系统来说是没有用的。如果它的内容因为某些原因而变得无效了,用户可以删除或者编辑它。

在缺省情况下,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脚本时,缓存文件将逐渐积累起来;缓存文件在一开始并不存在。运行configure会把新的缓存结果与现存的缓存文件结合起来。为了让它透明地工作,只要每次都使用相同的C编译器,站点初始化(site initialization)脚本可以指定一个站点范围(site-wide)的缓存文件以代替缺省的缓存文件。(参见设定本地缺省值)。

如果你的配置脚本,或者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)

打印消息
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不能完成的错误。本宏在标准错误输出中打印一条错误消息并且以非零状态退出 configure。error-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_CHECKING和AC_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。它已经过时了。

编写宏
当你编写了一个可以用于多个软件包的特征测试时,最好用一个新宏把它封装起来。下面是一些关于编写 Autoconf宏的要求(instructions)和指导(guidelines)。

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

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

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

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

为使用m4注释,使用m4内置的dnl;它使m4放弃本行中其后的所有文本。因为在调用AC_INIT之前,所有的输出都被取消,所以在`acsite.m4'和`aclocal.m4'中的宏定义之间不需要它。

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

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

大部分Autoconf宏的名字服从一个表明特征检查的种类命名惯例。宏名由几个单词组成,由下划线分隔,可以是最常见的,也可以是最特殊的。它们的缓存变量名服从相同的惯例。(关于它们的详细信息,参见缓存变量名)。

`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_XMKMF和AC_PATH_X_DIRECT。

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

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

AC_TRY_LINK(
changequote(<<, >>)dnl
<<#i nclude
#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'来检查这个问题。

宏之间的依赖性
为了正确地工作,有些Autoconf宏要求在调用它们之前调用其它的宏。Autoconf提供了一种方式以确保在需要时,某个宏已经被调用过了,以及一种在宏可能导致不正确的操作时给出警告的方式。

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

比强制宏的用户跟踪宏以前的依赖性更好的是,你可以使用宏AC_REQUIRE以自动地完成这一任务。 AC_REQUIRE可以确保只在需要的时候调用宏,并且只被调用一次。
宏: AC_REQUIRE (macro-name)
如果还没有调用m4宏macro-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])

建议的顺序
有些宏在都被调用的时候,一个宏就需要在另一个宏之前运行,但是它们并不要求调用另一个宏。例如,应该在任何运行C编译器的宏之前调用修改了C编译器行为的宏。在文档中给出了许多这样的依赖性。

当`configure.in'文件中的宏违背了这类依赖性,Autoconf就提供宏AC_BEFORE以警告用户。警告出现在从`configure.in'创建configure的时候,而不是在运行configure的时候。例如,AC_PROG_CPP检查C编译器是否可以在给出`-E'的情况下运行C预处理器。因而应该在任何改变将要使用的C编译器的宏之后调用它 。所以AC_PROG_CC包含:

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的调用以指明它已经被调用了。

过时的宏
配置和移植技术已经演化了好些年了。对于特定的问题,通常已经提出了更好的解决办法,或者同类的方法(ad-hoc approaches)已经被系统化了。结果就是有些宏现在已经被认为是过时了;它们仍然能工作,但不再被认为是最佳选择。 Autoconf提供了宏AC_OBSOLETE,当用户使用过时的宏时,就在生成configure脚本的时候对用户提出警告,以鼓励他们跟上潮流。一个调用实例是:

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

手工配置
有几种特征不能通过运行测试程序而自动猜测出来。例如,目标文件格式的细节,或者需要传递给编译器或连接器的特殊选项。你可以使用同类手段(ad-hoc means)来检查这类特征,比如说让configure检查uname程序的输出,或者寻找仅仅在特定系统中出现的库。然而,Autoconf为处理不可猜测的特征提供了统一的手段。

指定系统的类型
类似与其它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的脚本以使系统类型别名规范化。

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客