7
1
2016
0

autotools 教程:现在再谈 autoconf

很好的开端……

你应该已经学习了本部教程的 m4 章节,那么恭喜你,这是一个非常好的开端。过去你可能已经多次尝试入门 autoconf 但是不得要领,但是只要你学会了 m4 的基础知识,autoconf 对你来说就是一套预先定制好的 m4 宏而已,你只需学习其用法即可。读完本章,你就会发现 autoconf 是多么简单!

configure.ac 和 autoconf

要使用 autoconf,你需要一个叫做 configure.ac 的文件,当然,搞得这么花哨,其实就是一 m4 文件罢了。因为讲解 autoconf 时不宜引入 automake 之类的乱七八糟的东西,避免影响我们的教授流程,所以这里不会给出一个实际例子。这里你只需要知道,我们的目标程序名字叫做 SalamatPagi,使用 C 语言开发。

我们创建一个非常典型的开源项目文件系统:

mkdir -p SalamatPagi/src
mkdir -p SalamatPagi/lib
mkdir -p SalamatPagi/common
cd SalamatPagi

然后我们创建 configure.ac:

AC_INIT([SalamatPagi], [0.1], [bug-report@address])
AC_PROG_CC

此处,AC_INIT 初始化 autoconf,AC_PROG_CC 引入 C 编译器,AC_OUTPUT 则指示写出 configure。在这个目录下运行 autoconf,就可以得到 configure 文件,与此同时也会生成一个叫做 autom4te.cache 的目录(看到 m4 了吗?)。我们运行 configure 脚本:

checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed

会生成一个 config.log,打开之,可看到 configure 到底做了些什么。

其他编译器

除了 AC_PROG_CC,autoconf 还原生支持 AC_PROG_{CXX,OBJC,OBJCXX,GO} 等。但是注意,Vala 支持是 Automake 提供的,命令叫做 AM_PROG_VALAC。

什么是归 autoconf/configure 管的?

从上面的 configure.ac、configure 的运行输出和 config.log,我们可以清楚地看到:编译器调用、可移植性检测、用于程序内部的常量定义均归 autoconf 管辖范畴。除此之外,一些自定义校验、依赖库是否存在的检验和includedir/libdir定义也是属于 autoconf 的范围的。

现在可移植性问题少了,就代表 configure 可以消失了吗?

事实并非如此,因为 configure 还有另外一个非常重要的用途,即将一些模板文件具体化。直接这么说,可能还有点难以理解,我们就以具体例子来说吧。

创建一个叫做 pathdefs.in 的文件:

According to your settings:
The binaries will be in ${bindir} and the libraries will be in ${libdir}.

然后在 configure.ac 下面添加两行:

AC_CONFIG_FILES([pathdefs])
AC_OUTPUT

AC_CONFIG_FILES 是什么意思呢?也就是在 autoconf 这里注册某个文件(文件名这里不能有 .in,所以你自己创建的模板文件名必须以 .in 结尾),这个文件后来会被具体化。如果有多个文件,则应在 [ ] 中以空格分隔,如 [file1 file2 file3]。

AC_OUTPUT 则会创建一个叫 config.status 的脚本文件,实际上是这个文件在做模板具体化的事情。

在下一章,你将会看到 automake 实际上是将 Makefile.am 文件转化为 Makefile.in,然后交给 configure 处理的。

在当今时代,这可能是 configure 最重要的功能,而第二重要的功能则是提供一系列方便好用的参数以供配置时修改,这一点可以大大方便各种发行版的打包(如果你做过某个发行版的开发者肯定为一些不提供 autotools 的软件头痛过);此外更可以自己添加配置选项。

如何自己添加选项?

让 configure 拥有一个类似 --with-foo 的参数:

AC_ARG_WITH([foo], 
	[AS_HELP_STRING([--with-foo], 
		[get fancy features of foo @<:@default=no@:>@])], 
	[], [with_foo=no])

其实第一个参数是 with-xxx 中的 xxx,而 AS_HELP_STRING 则为我们格式化漂亮的帮助文档。第三个参数是如果给定了该参数的行为,第四个是如果没给定时的行为(也就是默认行为)。这里默认时 with-foo 设为 no。这里的 @<:@ 是转义 [,因为 [ 被用为 quote 了。当我们设置了 --with-foo 参数时,就会在 shell 脚本层面定义一个 with_foo 变量。

但是这有什么用呢?我们还需要对其进行处理。这里需要使用 AS_IF。AS_IF 和 ifelse 的用法差不多,但是其并非对两个字符串进行比较,而是运行一段 shell 脚本,如果脚本返回 0,那么代表验证成功,即执行 true-clause。

AS_IF([test "x$with_foo" = xyes], [echo yes!!!], [echo no!!!])

autoconf 后再运行 configure --with-foo=yes 我们就能看到 yes!!!

与 --with-xxx 类似,我们还能定义 --{enable,disable,without}-xxx,其命名均为AC_ARG_{WITHOUT,ENABLE,DISABLE},故不再赘述。一般来说,enable 的是某个外部库引入的功能,而 with 的是本身程序提供的功能。

这里实际上还有另一种更方便的处理方法,详见 automake 章。

如何使变量对 .in 可见?

默认情况下,configure 里面的变量是作为 shell 的内部变量不对 .in 可见的,如果要让我们的变量对 .in 可见,需要调用 AC_SUBST 命令。这里我们把 pathdefs.in 修改为:

--with-foo=@with_foo@

并在 configure.ac 中添加一行 AC_SUBST([with_foo]),我们就能看到效果了。注意,这里的变量替换用的是 @variable@ 格式。

如何检查程序依赖的库?

AC_CHECK_{LIB,HEADERS,FUNCS} 等如今已经很少用,这里从简,详见文档。

但是现代编程又经常使用 pkg-config,我们看看如何使用之。

PKG_CHECK_MODULES([GTK], [gtk+-3.0 >= 3.0])

注意,这里 >= 和两边应有空格,且重新生成 configure 时应先用 aclocal,因为引入了一个新的 m4 命令 PKG_CHECK_MODULES。使用 PKG_CHECK_MODULES,可以毫无压力地解决LDFLAGS、CFLAGS 等麻烦事,并且还能自动把变量传下去,如这里会创建一个 GTK_CFLAGS 和 GTK_LIBS 以供 Makefile 使用。

谈谈 config.h

我们有时候需要用 config.h 给程序提供一些常变的信息,如版本号。我们当然希望这些信息是集中的,比如说集中在 configure.ac 里面,然后通过 config.h 传递给代码。我们选择把 config.h 放在 common 里面。

在 configure.ac 中添加:

AC_CONFIG_HEADER([common/config.h])

然后创建 common/config.h.in,现在你应该驾轻就熟了吧,和普通的 .in 一样!填进去自
己感兴趣的东西即可。

写在 SCons、CMake 等工具的旁边

上回书说道,m4 可以当作一个相当蹩脚的编程语言来用,但是 m4 的强项并不在于控制程序逻辑,而是把一堆乱七八糟的东西不断展开再展开,所以可以用一些简单的宏生成一堆复杂的代码,也就是 configure 脚本。

而一些更现代化的构建工具,比如说 CMake,它的控制脚本叫做 CMakeLists.txt,其实也是一种编程语言,但是与 autotools 不同,要生成代码,你必须安装好 cmake。而 SCons 则更为激进,它直接使用 Python 作为脚本语言。

你可能会问,为什么那么 autotools 相对这些工具还有什么优势?

  1. 正如之前所说,GNOME 系的库全线支持 autotools,简单方便。
  2. autotools 原生支持 make uninstall,这在 cmake 和 scons 中都是要手动完成的!

多絮叨几句

实际上本章已经介绍了不少 configure.ac 构造技术了,借助搜索引擎和文档,你可以写出更大更复杂的 configure.ac。你可能会疑惑我们怎么没有生成出来一个有效的可执行文件,但是这已经不在 configure 范畴内了!下一章我们会看如何在 automake 的帮助下构
建出来可执行文件。

当然,实际上 autoconf 不单单可用于构建程序,试着想想看 autotools 还能用在哪儿?:-)

Category: 技术 | Tags: autotools-tut | Read Count: 2010

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Powered by Chito | Hosted at is-Programmer | Theme: Aeros 2.0 by TheBuckmaker.com