Autoconf学习——编写configure脚本

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'时产生的),保存测试产生的结果 (seeCache 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 ---'



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


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


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文件中注释的起始符号是“#”。



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


autoscan程序能够帮助你为一个软件包创建/维护一个configure.ac文件。autoscan根据作为一个命令行参数指定的目录作为根位置(如果没有指定则是当前工作目录)扫描检查整个目录树中的文件。它为了通用可
移植性问题搜查源文件,并创建一个configure.scan文件,该文件是configure.ac文件的前身,并且为了完整性检查存在的configure.ac文件。
在你要将configure.scan文件重命名为configure.ac之前,需要仔细检查一下该文件,譬如宏调用的顺序有问题。如果你想要包含一个配置头文件,那么可以使用AC_CONFIG_HEADERS宏()
。你可能不得不改变或者添加#if指令到你的程序中与Autoconf一起工作()。   
当autoscan在一个包的源代码文件中找到特殊的呼号时它使用几个数据文件(与Autoconf安装在一起)来决定输出哪个宏。这几个文件都有同样的格式:每一行由一个符号,一个或多个空格,对应该符号要输出的宏。
autoscan接受下面的选项:

ifnames能够帮助你编写某一个软件包的configure.ac文件。它打印标识符——该软件包已经在C预处理条件中使用。如果一个包已经被设置为可移植的,ifnames能够帮助你指出它需要检查的配置。
ifnames接受下列选项:
因为一些工具如automake已经被更新,或者一些源文件如configure.ac已经被更新,或者只是为了重新安装GNU Build系统,都需要重新安装各个组件。


你可能感兴趣的:(configure.ac)