autoconf可以帮我们生成configure脚本,替换Makefile中的变量,本文讲解其简单的使用方法。
假设我们有如下代码helloworld.c:
#include <stdio.h>
int main() {
printf("Hello, world!\n");
}
Makefile如下:
version = 1.0
name = helloworld
helloworld: helloworld.c
$(CC) -o $@ helloworld.c
便形成了一个完整的,非常简单的使用make编译的c项目。那么用autoconf的情况下面如何写呢?首先我们要将Makefile重新命令为Makefile.in,内容如下:
version = @PACKAGE_VERSION@
name = @PACKAGE_NAME@
helloworld: helloworld.c
$(CC) -o $@ helloworld.c
注意到Makefile.in实际上相当于Makefile的一个模版,里面的@PACKAGE_VERSION@和@PACKAGE_NAME@相当于参量,将会被autoconf定义的参量替换。
autoconf需要一个文件做为输入,叫作configure.ac。创建这个文件,内容如下:
AC_INIT([helloworld], [1.0])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
上面第一行AC_INIT定义了PACKAGE_NAME和PACKAGE_VERSION,第二行告诉autoconf要生成的配置文件名为Makefile,注意autoconf会自动查找 配置文件名+.in 这样的文件做为输入模版,并替换里面的参量。因此Makefile对应的模版文件就是我们手写的Makefile.in。
第三行告诉autoconf按以上配置输出相关配置文件。下面执行autoconf:
autoreconf
autoreconf实际是一串命令的集合,比执行autoconf要简单。执行完成后,生成了configure文件:
% ls
configure
configure文件将用于生成config.status文件。执行configure:
% ./configure
configure: creating ./config.status
config.status: creating Makefile
生成了config.status。注意到,实际上是config.status负责创建Makefile。看看生成的Makefile内容:
version = 1.0
name = helloworld
helloworld: helloworld.c
$(CC) -o $@ helloworld.c
我们再过一遍流程:
1. configure.ac是autoconf的命令输入文件
2. 在configure.ac中,我们定义Makefile为待生成的配置文件,因此我们需要有Makefile.in做为模版,里面有要替换的变量
3. 执行autoreconf生成configure
4. configure生成config.status
5. config.status通过Makefile.in生成Makefile
从上面的流程看出什么没?可以发现其实是config.status这个文件负责将Makefile.in转成Makefile。因此,上面的流程执行过一次以后,如果想修改Makefile,只需要修改Makefile.in就可以了,而1-4步可以不必再重复,除非configure.ac需要做出改动。
因此我们可以在Makefile.in中加入用于更新Makefile自身和config.status的rule:
version = @PACKAGE_VERSION@
name = @PACKAGE_NAME@
helloworld: helloworld.c
$(CC) -o $@ helloworld.c
Makefile: Makefile.in config.status
./config.status $@
config.status: configure
./config.status --recheck
这样,当1-5执行过一次后,以后想更新Makefile,只需要修改完Makefile.in后,执行:
% make Makefile
./config.status Makefile
config.status: creating Makefile
make: `Makefile' is up to date.
是不是很酷?我将上面的代码放在了github里面,可以clone出来玩玩看:
git clone git://github.com/liweinan/try-make.git
代码位于try02目录。