荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: sdymhua.bbs@Zero.cn-bbs.org (零起点), 信区: Linux
标  题: autoconf手册(八)
发信站: 零起点_BBS (Fri Dec  3 10:13:04 2004)
转信站: SZU!news.szu.edu.cn!news.uestc.edu.cn!Zero

autoconf手册(八)
我如何解开死结?
如果Autoconf需要GNU m4并且GNU m4还有一个Autoconf configure脚本,
我如何解开这个死结?它好像是一个类似于鸡和蛋的问题!
这实际上是一种误解。虽然GNU m4带有一个由Autoconf生成的configure脚本,但在运行脚
本及安装GNU m4的时候并不需要安装Autoconf。只有在你需要修改m4的configure 脚本的时
候,这只是少数几个人(主要是它的维护者)必须去作的事,才需要Autoconf。

为什么不使用Imake?
为什么不用Imake来代替configure脚本?
有些人已经提出了这个问题,所以在改编之后,我把给他们的解释写在这里。
下面是对Richard Pixley的问题的回答:
由Autoconf生成的脚本经常地在它以前从未设置过的机器上工作。这就是说,它善于推断新
系统的配置。而Imake不能做到。
Imake使用含有主机特定数据的通用数据库。对X11来说,这种方法具有意义是因为发布版本
是由一个控制整个数据库的总管机关管理的一组工具组成的。
GNU工具并不按这种方式发行。每个GNU工具都有一个维护者;这些维护者散布在世界各地。
使用统一的数据库将使维护变成噩梦。 Autoconf可能成为这类数据库,但实际上它没有。
不是列举主机的依赖性,它列举的是程序的需求。
如果你把GNU套件看作一组本地工具,那么问题就很相似了。但GNU开发工具可以作为交叉工
具(cross tools)而在几乎所有主机+目标机的组合中进行配置。所有的这些配置都可以同
时(concurrency)安装。它们甚至可以被配置成可以在不同主机上共享与主机独立的信息
的形式。Imake不能处理这些问题。
Imake模板是标准的一种形式。GNU编码标准在没有强加相同的限制的情况下,解决了相同的
问题。
下面是一些由Per Bothner撰写的进一步的解释:
Imake的一个长处是它易于通过使用cpp的`#include'和宏机制生成大的Makefile。然而,
cpp是不可编程的:它含有有限的条件工具,而不含有循环。而且cpp不能检查它的环境。
所有这些问题可以通过使用sh而不是cpp来解决。shell是完全可编程的、含有宏替换、可以
执行(或者编制)其它的shell脚本,并且可以检查它的环境。
Paul Eggert更详细地阐述:
使用Autoconf,安装者不必假定Imake自身已经被安装并且正常地工作了。这对于习惯使用
Imake的人们来说,看起来不是突出的长处。但在许多主机上,并没有安装Imake或者缺省的
安装不能很好地工作,为此,要求安装Imake就阻碍了在这些主机上使用由Imake配置的软件
包。例如,Imake模板和配置文件可能不能适当地安装在一个主机上,或者Imake创建过程可
能会错误地假定所有的源代码文件都在一个大目录树中,或者Imake配置可能使用某个编译
器而包或者安装器需要使用另一个编译器,或者包需要的Imake的版本号与系统支持的版本
号不匹配。这些问题在Autoconf中很少出现,这是因为包附带属于它自己的独立配置处理器

还有,Imake通常会在make和安装者的C预处理器之间遇到难以预期的影响。这里的基本问题
是,C预处理器是为处理C程序而不是`Makefile'而设计的。这对Autoconf来说问题小得多,
它使用通用目的预处理器m4,并且包的作者(而不是安装者)以标准的方式进行预处理。
最后,Mark Eichin解释道:
Imake还不是完全可扩展的。为了把新特征添加到Imake中,你需要提供你自己的项目模板,
并且复制已经存在的特征的主要部分。这意味着对于复杂的项目来说,使用由买主提供的(
vendor-provided)Imake模板不能提供任何平衡作用--这是因为它们不包括你自己的项目的
任何东西(除非它是一个X11程序)。

但是,另一方面:

一个Imake胜过configure的长处是: `Imakefile'总是趋向于比`Makefile.in'简短(同样
地,冗余较少)。但是,这儿有一个修正的方法--至少对于Kerberos V5树来说,我们已经
在整个树中进行了修改以调用通用的 `post.in'和`pre.in' `Makefile'片断。这意味着大
部分通用的东西,即使它们通常是在configure中设置的,也不必复制。

从版本1中升级
Autoconf第2版基本上与第1版是向后兼容的。但是,它给出了作某些事的更好方法,并且不
再支持版本1中一些丑陋的东西。因此,根据你的`configure.in'文件的复杂性,你可能必
须作一些手工的工作以升级到版本2。本章指出了一些在升级的时候需要注意的问题。还有
,可能你的configure脚本可以从版本2中的新特征中获得一些好处;在Autoconf发布包中的
`NEWS'文件概括了改变的部分。

首先,确认你安装了1.1版或者更高版本的GNU m4,最好是1.3版或者更高版本。在1.1版之
前的版本含有bug 以至于它不能与Autoconf版本2一同工作。版本1.3及其后的版本比早期的
版本更快一些,这是因为1.3版的GNU m4 对转换(diversions)进行了更有效的实现并且能
够在可以快速读回的文件中冻结(freeze)它的内部状态。

改变了的文件名
如果你随Autoconf一起安装了`aclocal.m4'(相对于特定软件包的源代码目录中的
`aclocal.m4'),你必须把它重命名为`acsite.m4'。参见用autoconf创建configure。

如果你与你的软件包一同发布`install.sh',就把它重命名为`install-sh'以便make的内置
规则不会无意地从该文件创建一个称为`install'的文件。AC_PROG_INSTALL将寻找这两个名
字的脚本,但最好使用新名字。

如果你使用`config.h.top'或者`config.h.bot',你仍然可以使用它们,但如果你把它们混
合到 `acconfig.h'之中,将减少你的麻烦。参见用autoheader创建`config.h.in'。

改变了的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@

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

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

有些宏已经被能够更好地完成工作的类似宏所代替,但在调用上并不兼容。如果你在运行
autoconf时受到了关于调用过时宏的警告,你可以安全地忽略它们,但如果你按照打印的建
议替换过时的宏,你的configure脚本通常可以工作的更好。特别地,报告测试结果的机制
已经改变了。如果你使用了echo或者AC_VERBOSE(可能是通过AC_COMPILE_CHECK),如果你
改用AC_MSG_CHECKING和AC_MSG_RESULT,你的configure脚本的输出将更加美观。参见打印
消息。这些宏能够更好地与缓存变量协同工作。参见缓存结果。

用autoupdate更新configure
程序autoupdate把使用Autoconf旧宏名的`configure.in'文件更新为使用当前宏名的文件。
在Autoconf第2版中,大部分宏被重命名以使用一个更统一、更具有描述性的命名机制。关
于对新的命名机制的描述,参见宏名。虽然旧宏名仍然可以工作(关于旧宏名和对应的新宏
名的列表,参见陈旧的宏名),如果你更新它们以使用新的宏名,你可以使你的
`configure.in'文件更加可读并且易于使用当前的Autoconf文档。

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

autoupdate接受下列选项:

--help
-h
打印命令行选项的概述并且退出。
--macrodir=dir
-m dir
在目录dir中,而不是在缺省安装目录中寻找Autoconf宏文件。你还可以把环境变量
AC_MACRODIR设置成一个目录;本选项覆盖该环境变量。
--version
打印autoupdate的版本号并且退出。
改变了的结果
如果你通过检验shell变量DEFS来检验以前测试的结果,你需要把这些检验替换为对那些测
试的缓存变量的检查。在configure运行的时候,DEFS不再存在;它仅仅在生成输出文件的
时候才被创建。这种与第1版的不同是因为正确地对变量实行引用(quoting)实在太麻烦而
且在每次调用AC_DEFINE都要实行引用是低效的。参见缓存变量名。

例如,下面是为Autoconf第1版编写的`configure.in'的片断:

AC_HAVE_FUNCS(syslog)
case "$DEFS" in
*-DHAVE_SYSLOG*) ;;
*) # syslog is not in the default libraries. See if it's in some other.
 saved_LIBS="$LIBS"
 for lib in bsd socket inet; do
  AC_CHECKING(for syslog in -l$lib)
  LIBS="$saved_LIBS -l$lib"
  AC_HAVE_FUNCS(syslog)
  case "$DEFS" in
  *-DHAVE_SYSLOG*) break ;;
  *) ;;
  esac
  LIBS="$saved_LIBS"
 done ;;
esac

这里是为版本2编写的方式:

AC_CHECK_FUNCS(syslog)
if test $ac_cv_func_syslog = no; then
 # syslog is not in the default libraries. See if it's in some other.
 for lib in bsd socket inet; do
  AC_CHECK_LIB($lib, syslog, [AC_DEFINE(HAVE_SYSLOG)
   LIBS="$LIBS $lib"; break])
 done
fi

如果你通过在引号的后边添加反斜线以处理AC_DEFINE_UNQUOTED中的bug,你需要删除它们
。它现在以可以预期的方式工作,并且不需要特别地处理引号(处理反斜线)。参见设定输
出变量。

所有由Autoconf宏设置的布尔shell变量现在用`yes'来表示真值。虽然为了向后兼容,有些
宏使用空字符串表示假,大部分宏使用`no'来表示假。如果你依赖于shell变量用诸如1或者
`t'来表示真,你就需要改变你的测试。

改变了的宏的编写
在定义你自己的宏时,你现在应该使用AC_DEFUN而不是define。 AC_DEFUN自动调用
AC_PROVIDE并且确保通过AC_REQUIRE调用该宏不会被其他宏所打断,从而防止在屏幕上出现
嵌套的`checking...'消息。继续按照老办法行事没有实际上的伤害,但它缺乏便利和吸引
力。参见宏定义。

你可能把与Autoconf一同发行的宏作为如何解决问题的指南。看看它们的新版本将是一个好
主意,因为风格已经有些改进并且它们利用了一些新的特征。

如果你利用未公开的(undocumented)Autoconf内部元素(宏、变量、变换(diversions)
)作了微妙的工作,就要检查你是否需要修改些什么以适应已经发生的变化。可能你甚至能
够用版本2中公开(officially)支持的技术来代替你的拼装(kludging)。但也可能不能


为了加快你自行编写的特征测试,为它们添加缓存。看看你所有的测试是否足够一般化,从
而具有足够的用途以把它们封装到你可以共享的宏中去。

Autoconf的历史
你可能会困惑,最初为什么要编写Autoconf?它是如何演变到今天的形式的?(为什么它看
起来就像大猩猩的吐沫?)如果你不困惑,那么本章就不包含对你有用的信息,你也可能会
跳过它。如果你困惑,那就让它明白些...

起源(Genesis)
在1991年六月,我为自由软件基金会维护了许多GNU工具。由于它们被移植到更多的平台并
且增加了更多的程序,用户必须在`Makefile'中选择的`-D'选项的数目(大约20个)变得难
以承受。尤其是我-- 我不得不在许多不同的系统上对每个新的发布版本进行测试。所以我
编写了一个简单的shell脚本为fileutils包猜测一些正确的设置,并且把它作为fileutils
2.0的一部分进行发布。这个configure能够胜任工作,因此,我在下个月中,手工对其进行
了修改以用于其他几个GNU工具包,从而创建了相似的configure脚本。 Brian Berliner也
修改了我的脚本以用与它的CVS修订控制系统。

那个夏天以后,我得知Richard Stallman和Richard Pixley正在开发用于GNU编译器工具的
类似脚本;所以我对我的 configure进行了修改以支持它们的进化的界面:把名为
`Makefile.in'的文件当作模板;添加`+srcdir',作为许多选项的第一个选项;并创建
`config.status'文件。

出发(Exodus)
由于我从用户那里获得了反馈,我组合了许多改进,使用Emacs进行搜索和替换、剪切(
cut)和粘贴(paste),在每个脚本中进行类似的修改。随着我修改更多的GNU工具包以使
用configure脚本,完全用手工更新它们就不可能了。Rich Murphey,GNU图形工具的维护者
,在给我发送的邮件中说configure脚本很好,并问我是否有一个可以生成它们的工具可以
发给他。没有,我想,但我将会有!所以我开始考虑如何生成它们。这样,从手工编写
configure脚本的苦力向功能强大而易于使用的Autoconf前进的旅程开始了。

Cygnus configure,它大约也在那个时候被开发,是表驱动的;这意味着用少量的大体上不
可猜测的特征来处理离散数量的系统类型(例如目标文件格式的细节)。Brian Fox为Bash
开发的自动配置系统采用了类似的方法。为了统一用法,我好像必须绝望地试图为每个操作
系统的变种的特征维护一个及时更新的数据库。更容易和更可靠的办法是不检查大多数特征
--特别是在那些人们已经在本地深入地研究或者安装了买主提供的补丁的杂合的系统。

我考虑到使用与Cygnus configure相似的结构,就是提供一个单独的configure脚本,在运
行时读入`configure.in'的片断。但是我不想让每个包都发布所有的特征测试,所以我选择
了使用预处理器从每个`configure.in'中创建不同的configure。这个方法还提供了更多的
控制和便利。

我简要地察看了被Larry Wall、Harlan Stenn和Raphael Manfredi采用的Metaconfig包,但
我为了几个原因而不采用它。这种方式生成的Configure脚本是交互式的,我认为太不方便
了;我不喜欢它测试某些特征的方式(例如库函数);我不知道它是否还有人维护,并且我
所见到的Configure脚本在许多现代系统(例如System V R4和NeXT)中都不能工作;设置在
支持某个特征或者不支持该特征时所进行的动作也不是很方便;我发现它难于学习;并且对
于我的需要,它太大、太复杂了(我没有意识到Autoconf最终将变得多么大)。

我考虑过使用Perl来生成我的风格的configure脚本,但显然m4更加适合于简单的文本替换
工作:由于输出是隐含的,它的工作比较少。还有,每个人都已经拥有它了。(一开始,我
并不依赖于 GNU对m4的扩展。)我在Maryland大学的一些朋友最近用一些程序,包括tvtwm
,制作了m4的前端,并且我也有兴趣试试一种新语言。

上路(Leviticus)
因为我的configure在没有与用户进行交互的条件下自动地确定了系统的能力,我决定把生
成它们的程序称作Autoconfig。但附加了版本号之后,这个名字对于老式的UNIX文件系统来
说就太长了,所以我把它缩短成Autoconf。

在1991年秋天,我召集了一群期望获得移植性的家伙(alpha测试者)以给我提供反馈从而
使我可以压缩(encapsulate)我用m4宏写的脚本并且继续添加特征、改进检查中采用的技
术。测试者中的杰出人物有Pinard,他提出了创建一个`autoconf'来运行m4并且检查找不到
的宏调用的想法;还有Richard Pixley,他建议通过运行编译器而不是在文件系统中寻找引
入文件和符号,以获得更精确的结果;还有Kerl Berry,他使得Autoconf可以配置 Tex并且
把宏索引添加到文档中;还有Ian Taylor,他增加了对创建C头文件的支持以代替在
`Makefile'中添加 `-D'选项的方法,以便他可以把Autoconf用于他的UUCP包。alpha测试者
愉快地、一次又一次地随着 Autoconf不同发布版本中的Autoconf名称和宏调用惯例的改变
而调整他们的文件。他们都贡献了许多特定的检查、绝妙的想法,以及对bug的修正。

发展(Numbers)
在1992年七月,在alpha测试之后一个月,我发布了Autoconf 1.0,并且修改了许多GNU包以
使用它。我对它带来的正面作用感到很吃惊。很多人,包括那些编写并不属于GNU工程的软
件(例如TCL、FSP和Kerberos V5)的人们,开始使用它,以至于我无法跟踪他们了。随着
很多使用configure脚本的人报告他们所遇到的问题,Autoconf继续快速地得到改进,

Autoconf成为考验m4实现的酷刑般的测试。由于Autoconf定义的宏的长度,UNIX m4开始失
败(dump core),同时也发现了GNU m4中的一些bug。最终,我们意识到我们需要使用一些
只有 GNU m4才提供的特征。特别的,4.3BSD m4含有一组增强了的内置宏;System V版本更
好一些,但仍然不能提供我们所需要的所有东西。

随着Autoconf得到人们越来越多的重视,对Autoconf进行了更多的开发(并且有了我不能预
见的用途)。Karl Berry添加了对X11的检查。david zuhn贡献了对C++的支持。Pinard使
Autoconf能够诊断非法的参数。Jim Blandy勇敢地用它配置了GNU Emacs,并且为某些未来
的改进打下了基础。Roland McGrath用它配置了GNU C库,编写了autoheader 脚本以自动创
建C头文件模板,并且为configure添加了一个`--verbose'选项。 Noah Friedman添加了
`--macrodir'选项和环境变量AC_MACRODIR。(他还提出了术语 autoconfiscate,用来表示
“调整软件包以使用Autoconf”。)Roland和Noah改进了AC_DEFINE 中的引用保护并且修正
了许多bug,特别是在1993年二月到六月间我们对处理移植性问题感到厌倦的时候。

现状(Deuteronomy)
在积累了一个关于希望添加的主要特征的长长的列表,并且在几年之中各式各样的人们提供
的补丁残留了古怪的效果之后。在1994年四月,处理对Cygnus的支持时,我开始对
Autoconf进行一次主要的修订。我添加了大部分Cygnus configure 有,而Autoconf缺少的
特征,主要是在david zuhn和Ken Raeburn的帮助下改编Cygnus configure的相关部分。这
些特征包括对使用`config.sub'、`config.guess'、`--host'和 `--target'的支持;创建
对文件的连接;以及在子目录中运行configure脚本。添加这些特征使得Ken可以放弃GNU
as,Rob Savoye可以放弃DejaGNU,而改用Autoconf。

作为对其他人的要求的回应,我添加了更多的特征。许多人要求configure脚本能够在不同
的运行中共享检查的结果,这是因为它们实在太慢了(尤其是像Cygnus那样在配置一个大的
源代码树的时候)。 Mike Haertel建议增加与位置有关的初始化脚本。发布必须在MS-DOS
中解包(unpack)的软件的人们要求提供一种覆盖那些诸如`config.h.in'那样的、含有两
个点的文件名中的`.in'扩展名的方法。 Jim Avera通过AC_DEFINE和AC_SUBST中的引用扩展
了对程序的检测;他的洞察力带来了重要的改进。Richard Stallman要求把编译器的输出送
到`config.log'中,而不是送到`/dev/null'中,以帮助人们调试Emacs configure脚本。

由于我对程序质量的不满,我进行了一些其他的修改。我减少了用于显示检查结果的消息的
二义性,总是打印结果。我识别宏的名字并且消除编码风格的不一致性。我添加了一些我所
开发的附加工具以助于修改源代码包以使用Autoconf。在Pinard的帮助下,我创建了不会在
彼此的消息中导致冲突的宏。(这个特征暴露了他草率地修正的、GNU m4 中的一些性能瓶
颈!)我重新组织了人们需要解决的问题的文档。并且我开始了一组测试(testsuite),
这是因为经验已经表明:在我们修改Autoconf的时候,它有明显的回归倾向。

一些alpha测试者再次给出了难以估量的反馈,特别是 Pinard、Jim Meyering、Karl
Berry、Rob Savoye、Ken Raeburn和Mark Eichin。

最后,2.0版本准备好了。而且我们也很高兴。(我们又有闲暇时间了。我想。哇,很好。

--
※ 来源:.零起点 BBS Zero.cn-bbs.org.[FROM: 220.172.236.*]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店