获取规范的系统类型
下列的宏使得configure脚本可以获得系统类型。它们运行shell脚本config.guess以确定用户在命令行中没有给出的、它们需要的关于主机、目标和创建类型的所有值。它们运行config.sub对用户给出的任何别名进行规范化。如果你使用这些宏,你必须把这两个shell脚本与你的源代码一同发布。关于 AC_CONFIG_AUX_DIR的信息,你可以通过该宏设置configure查找这些脚本的目录,请参见创建输出文件。如果你没有使用这些宏中的任意一个,configure 就忽略任何传递给它的`--host'、`--target'和`--build'选项。
宏: AC_CANONICAL_SYSTEM
检测系统类型并把输出变量设置成规范的系统类型。关于该宏设置变量的细节,参见系统类型变量。
宏: AC_CANONICAL_HOST
只执行AC_CANONICAL_SYSTEM中关于主机类型功能的子集。对于不是编译工具链(compiler toolchain)一部分的程序,这就是所需要的全部功能。
宏: AC_VALIDATE_CACHED_SYSTEM_TUPLE (cmd)
如果缓存文件与当前主机、目标和创建系统类型不一致,就执行cmd或者打印一个缺省的错误消息。
系统类型变量
在调用了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
为方便而提供的规范名称的独立部分。
使用系统类型
你将如何使用规范的系统类型?通常,你在`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。如果可能,创建一个符号连接,否则就创建硬连接。dest和source应该是相对于顶层源代码目录或者创建目录的相对路径。可以多次调用本宏。
例如,下列调用:
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的信息,参见对普通程序和文件的检查。
站点配置
configure脚本支持几种本地配置决策方式。它们是用户指明外部软件的位置,包括或除去可选的特征,以修改过的名称安装的程序,以及为configure选项设置缺省值的手段。
与外部软件一起工作
有些软件包需要,或者可选地使用其它已经安装的软件包。用户可以把命令行选项传递给configure 以指明使用那个外部软件。选项采用下列形式之一:
--with-package[=arg]
--without-package
例如,`--with-gnu-ld'的意思是使用GNU连接器而不是任何其它连接器。`--with-x'的意思是使用X Window系统。
用户可以给出包名加`='加参数的命令行参数。`no'是关于包的缺省参数;它表示不使用包。既不是`yes'又不是`no'的参数将包含其它包的名字或者版本号,以便更精确地指定本程序可以与之协同工作的包。如果没有给出参数,`--without-package'的缺省参数为`yes'。 `--without-package'等价于`--with-package=no'。
configure脚本并不对它们不支持的`--with-package'选项发出警告。本特征允许顶层目录中的configure脚本配置一个包含多个包的源代码树。在包支持不同的选项的时候,不会因为给出了只有一部分包支持的选项而导致不必要的错误消息。一个不幸的副作用是选项的拼写错误就不能被检查出来了。迄今为止还没有处理该问题的更好办法。
对于每个可能使用的外部软件包,`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。你将需要用`['和`]'包围它以生成前导空格。
宏: AC_WITH (package,action-if-given [,action-if-not-given])
这是不支持求助字符串的AC_ARG_WITH的过时版本。
选择包选项
如果软件包含有可选的编译时(compile-time)特征,用户就可以在调用configure时使用命令行选项来指明是否编译它们。选项采用如下形式之一:
--enable-feature[=arg]
--disable-feature
这些选项允许用户选择可选的选项进行创建和安装。`--enable-feature'选项永远不要使特征的行为变得不同或者导致一个特征代替另一个特征。它们只应该导致程序的一部分被创建而另一部分不创建。
用户可以通过在特征名之后添加`='和参数来给出参数。给出参数`no'表示不能使用该特征。一个带有参数的特征看起来就像`--enable-debug=stabs'。如果没有给出参数,它的缺省值就是`yes'。`-- disable-feature'等价于 `--enable-feature=no'。
configure脚本并不对它们所不支持的`--enable-feature'选项发出警告。本特征允许顶层目录中的configure脚本配置一个包含多个包的源代码树。在包支持不同的选项的时候,不会因为给出了只有一部分包支持的选项而导致不必要的错误消息。一个不幸的副作用是选项的拼写错误就不能被检查出来了。迄今为止还没有处理该问题的更好办法。
对于每个可选的特征,`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_feature。help- string参数类似于 AC_ARG_WITH中相应的参数(参见与外部软件一起工作)。
宏: AC_ENABLE (feature,action-if-given [,action-if-not-given])
这是不支持求助字符串的AC_ARG_ENABLE的过时版本。
配置站点细节
有些软件包需要复杂的与站点相关(site-specific)的信息。例如用于某种服务、公司名称和email联系地址的主名(host names)。因为有些配置脚本是通过Metaconfig方式交互地询问这些信息生成的,人们有时对于按非交互方式,由Autoconf生成配置脚本如何获取这些信息感到困惑。
这些站点配置信息应该被储存在一个仅仅由用户,而不是程序,编辑的文件中。文件的位置既可以基于 prefix变量,也可以是一个标准的位置,比如说用户的home目录。它甚至可能通过一个环境变量给出。程序应该在运行时,而不是在编译时,检查那个文件。运行时配置对于用户来说更为方便,并且使得配置过程比在配置时获取这些信息要简单。关于存放数据文件的地点的详细信息,参见GNU编码标准中的 `为安装目录而提供的变量'。
在安装的时候改变程序的名称
Autoconf支持在安装程序的时候修改程序的名称。为了使用这些变换,`configure.in'必须调用宏 AC_ARG_PROGRAM。
宏: AC_ARG_PROGRAM
把对被安装的程序的名称进行替换的sed命令序列存入输出变量program_transform_name中。
如果把下列任意选项传递给了configure,程序名就据此进行变换。否则,如果已经调用了AC_CANONICAL_SYSTEM并且`-- target'的值给出了与主机类型(用`--host'给出的,或者是在config.sub中设置的缺省值)不同的类型,就把末尾附加了破折号的目标类型作为前缀。否则,就不进行程序名变换。
转换选项
你可以把下列命令行选项传递给configure以指定名称的转换:
--program-prefix=prefix
为名称添加前缀prefix;
--program-suffix=suffix
为名称添加后缀suffix;
--program-transform-name=expression
对名字作sed替换expression。
转换的例子
这些变换对于作为交叉编译开发环境的一部分的程序是有用的。例如,用`--target=i960-vxworks'选项配置的运行在Sun 4上的交叉汇编器通常以`i960-vxworks-as'为名称进行安装,而不是以`as'为名安装,该名称将于原来的Sun 4汇编器混淆。
如果你不希望安装在你的系统上的GNU程序遮蔽具有相同名称的其它程序,你可以强行要求程序名以`g'开头。例如,如果你使用`--program- prefix=g'来配置GNU diff,那么在你运行`make install' 的时候,它就安装到`/usr/local/bin/gdiff'。
作为更复杂的例子,你可以使用
--program-transform-name='s/^/g/; s/^gg/g/; s/^gless/less/'
在源代码树中的大部分程序的名字之前附加`g',已经含有一个`g'的程序,诸如gdb,和不是GNU程序的程序,比如说less和lesskey,除外。(它假定你有一个包含了设置成使用这些特征的程序的源代码树。)
同时安装某些程序的多个版本的一种方法是为其中一个程序的名称或为所有程序的名称附加版本号。例如,如果你还希望把 Autoconf版本1保留一段时间,你可以使用`--program-suffix=2'来配置Autoconf第2版,并且以名称 `/usr/local/bin/autoconf2'、`/usr/local/bin/autoheader2'等等来安装程序。
转换的规则
下面是如何在`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手册进行替换。
设定站点缺省值
Autoconf生成的configure脚本允许你的站点(site)为某些配置值提供缺省值。你可以通过创建站点范围(site-wide)或者系统范围(system-wide)的初始化文件来达到这个目的。
如果设置了环境变量CONFIG_SITE,configure就把它的值作为读入的shell脚本的名称。否则如果 `prefix/share/config.site'存在,它就读入该脚本,否则如果`prefix/etc/config.site'存在,它就读入该脚本。因此,如果出现冲突,在机器特定文件中的设置将覆盖那些与机器独立的文件中的设置。
站点文件(site files)可以是任意shell脚本,但只能包含某种适于包含在其中的代码。因为configure在它读入所有站点文件之后读取任何缓存文件,站点文件可以定义一个缺省的缓存文件以便在本系统中运行的所有Autoconf生成的 configure之间共享。如果你在站点文件中设置了缺省缓存文件,那么再在那个站点文件中设置输出变量 CC就是个好主意,这是因为缓存文件仅仅对特定的编译器来说是合法的,但许多系统还有好几个可用的编译器。
你可以在站点文件中检验或者覆盖由命令行选项设置的值;与选项对应的shell变量的名称与选项的名字的唯一区别是选项名中所有的破折号应变换成的下划线。选项`--without-'和`--disable-'是个例外,出现它们就如同出现对应的 `--with-'或者`--enable-'并且把值设置为`no'。因此, `--cache-file=localcache'把变量cache_file的值设置为`localcache'; `--enable-warnings=no'或者`--disable-warnings'把变量enable_warnings 的值设置为`no';`--prefix=/usr'把变量prefix设置为`/usr';等等。
如果你需要为其它输出变量设置与缺省值不同的值(你通常不得不在命令行中重复地进行设置),比如说CFLAGS,站点文件就是进行这种设置的好地方。如果你为prefix或者exec_prefix设置了非缺省值(你放置站点文件的地方),如果你用环境变量CONFIG_SITE给出了站点文件,你就可以在站点文件中设置这些非缺省值。
你可以在站点文件中设置一些缓存值。如果你正在进行交叉编译,这样做就是有用的,以避免对需要运行测试程序的特征进行检查。你可以为 `prefix/etc/config.site'中的系统正确地设置这些值来“预备缓存(prime cache)”。为了找到你要设置的缓存变量名,可以在受到影响的configure脚本中寻找带有`_cv_'的shell变量,也可以在 Autoconf m4源代码中寻找这些宏。
缓存文件将十分谨慎而不至于覆盖任何在站点文件中设置的变量。类似地,你不应该在站点文件中覆盖命令行选项。你的代码应该在修改诸如prefix和cache_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脚本
下面是关于如何配置使用configure脚本的软件包的说明,适用于包中的`INSTALL'文件。你可能要使用的普通文本的`INSTALL'与Autoconf一同发行。
重新创建一个配置
configure脚本创建一个名为`config.status'的文件,用它描述在包最后一次进行配置时给出的配置选项。该文件是一个shell脚本文件,如果运行它,将重新创建相同的配置。
你可以用`--recheck'选项调用`config.status'以更新它自身。如果你修改了configure,该选项是有用的,这是因为某些测试的结果可能会与上一次运行的结果不同。选项`--recheck'以与从前使用的参数相同的参数,再加上`--no-create'选项以防止 configure运行`config.status'并创建 `Makefile'和其它文件,再加上`--no-recursion'选项以防止configure在子目录中运行其它的configure,来重新运行configure。(这样做是让其它的`Makefile'规则可以在 `config.status'改变时运行它;关于一个例子,参见自动地重新创建)。
`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的问题。下面是被提及的一些问题。
发布configure脚本
对发行由Autoconf生成的configure有什么限制?它们是如何影响我那些使用它们的程序的?
关于由Autoconf生成的配置脚本是如何发行和如何被使用的,并没有限制。在Autoconf第1版中,它们是服从GNU通用公共许可证的。我们仍然鼓励软件的作者按照诸如GPL的条款发行他们的作品,但Autoconf并不要求这样做。
关于可能由configure使用的其它文件,`config.h.in'服从你为你的`configure.in'而使用的任何版权规定,这是因为它是从那个文件和公有文件`acconfig.h'中派生出来的。当`config.sub'和 `config.guess'被用于由Autoconf生成的、允许你按照与你的软件包其它部分相同的条款发布的configure 脚本中时,它们就是GPL的一个例外。`install-sh'是来自于X Consortium并且是没有版权的。
为什么需要使用GNU m4?
为什么Autoconf需要使用GNU m4?
许多m4的实现含有编码性(hard-coded)的,对宏的大小和数量的限制,Autoconf超过了这些限制。它们还缺少一些内置宏,没有它们,诸如Autoconf之类的复杂应用程序将难以应付,它们包括:
builtin
indir
patsubst
__file__
__line__
因为只有软件维护者需要使用Autoconf,并且因为GNU m4易于配置和安装,需要安装GNU m4 好像是合理的。许多GNU和其它自由软件的维护者,因为他们更喜爱GNU工具,都已经安装了大部分GNU工具。