Autotools 基础
在使用 ebuild 时,了解 GNU autotools(automake、autoconf 等)会很有帮助。
- 如果构建系统不被简单地视为一个可怕的黑盒,那么查找和纠正构建问题通常会更容易。
- Autotools 输入文件可以帮助确定软件包的构建时依赖项。
- 如果理解了构建系统文件之间的关系,那么在错误的时间修补错误文件从而意外破坏某些东西的风险就会大大降低。
主要的 Autotools 组件
Autotools 是一个相关软件包的集合,当一起使用时,可以消除创建可移植软件过程中的大部分困难。这些工具连同一些相对简单的上游提供的输入文件一起,用于创建软件包的构建系统。

主要 Autotools 组件如何协同工作的一个基本概述。
在简单的设置中
- autoconf程序从- configure.in或- configure.ac(参见下面的注释)生成- configure脚本。
- automake程序从- Makefile.am生成- Makefile.in。
- configure脚本运行以从- Makefile.in文件生成一个或多个- Makefile文件。
- make程序使用- Makefile编译程序。
configure.in 名称曾经是标准的。但是,GNU 文档现在推荐使用 configure.ac,因为它更直观地表明在处理它时应该使用哪个程序。这两个文件执行相同的目的并具有相同的格式——唯一的区别是名称。您可能会看到 Autotools 在各种阶段函数中使用。 src_prepare 函数是在配置和编译之前操作源代码的最合适的地方。特别是,在 src_configure 之前调用 src_prepare,后者通常期望 configure 脚本存在。
autoreconf 工具据说根据需要运行 autoconf(以及 automake、autoheader、aclocal、autopoint 和 libtoolize)。有时它能正常工作。一些软件包附带一个名为 autogen.sh 的 shell 脚本,它执行相同的功能(这与 autogen 无关)。autotools.eclass 包含用于独立工具的帮助器函数,以及它们对应的名称,例如 eautoconf 和 eautomake。
configure 和 make 之间修改任何生成的文件。这会导致 Autotools 尝试聪明地重新创建文件,进而导致您的更改被删除。在某些情况下,这还会导致 ./configure 参数被静默丢弃,从而导致依赖关系错误。通常最好的方法是使用 .ac / .in 文件。简单的 Autotools 打补丁示例
以下代码片段说明了在修补 Makefile.am 或 configure.ac 后继续进行的正确方法。
EAPI=8
WANT_AUTOCONF=2.5
WANT_AUTOMAKE=1.9
inherit autotools
IUSE="nls"
BDEPEND="nls? ( sys-devel/gettext )"
src_prepare() {
	default
	# Remove problematic LDFLAGS declaration
	sed -i -e '/^LDFLAGS/d' src/Makefile.am || die
	# Rerun autotools
	eautoreconf
}
src_configure() {
	econf $(use_enable nls)
}
configure.ac 文件
configure.ac 文件用于创建 ./configure 脚本。它由一系列宏组成,这些宏由 autoconf 处理和扩展。这些宏可以检查软件包和库,处理 --enable 和 --with 开关,并生成各种文件。
configure.ac 的基本格式
configure.ac 文件是一个基本的文本文件。缩进和空格在很大程度上无关紧要。注释由字符串 dnl 表示(dnl 实际上是一个丢弃输入其余部分的宏——它代表“丢弃新行”)。
如果上一句话让你感到不安,你可能应该停止阅读此页面。情况会变得更糟。
一个典型的文件可能以类似以下内容开头
dnl Process this file with autoconf
AC_INIT(appname, 0.1)
AC_PREREQ(2.5)
AC_CONFIG_SRCDIR(src/main.c)
AC_CONFIG_AUX_DIR(config)
AM_INIT_AUTOMAKE(1.8)
如果存在,AC_PREREQ 行会告诉您需要哪个 autoconf 版本。这很有用,因为不同版本的 autoconf 之间不兼容。在上面的示例中,我们需要 =autoconf-2.5*,并且在调用 autoconf 时,我们应该 export WANT_AUTOCONF="2.5"(或使用 autoconf-2.59 脚本)。
AM_INIT_AUTOMAKE 行告诉我们我们需要哪个 automake 版本。同样,automake-1.7 脚本几乎不可能与 automake-1.8 正常工作。在环境中设置 WANT_AUTOMAKE="1.8" 可以使未版本化的 automake 调用运行正确的版本。
WANT_ 变量是 Gentoo 的一个特性,最初来自 Mandrake。其他发行版可能会以不同的方式处理这些事情。通常,一些标准检查将紧随其后
dnl Check for toolchain and install components
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_RANLIB
对于非标准应用程序,您也可能会看到手动检查
dnl Check for sed
AC_CHECK_PROGS(regex_cmd, sed)
if test x$regex_cmd = "x" ; then
    AC_MSG_ERROR([sed is required to build the data files.])
fi
您也可能会看到编译器特性的检查
dnl Check that our compiler can do const and inline
AC_C_CONST
AC_C_INLINE
库和头文件检查
dnl Check for standard headers:
AC_HEADER_STDC
AC_HEADER_DIRENT
AC_CHECK_HEADERS([stdlib.h stdio.h libintl.h locale.h])
dnl Check for libraries:
AC_CHECK_LIB(ssl, SSL_free)
以及函数检查
dnl Check for functions:
AC_CHECK_FUNCS([setlocale strtol])
通常这些都会混在一起,没有任何有用的注释。在某些情况下,许多进行的检查对于相关的应用程序甚至不是必需的——大多数 Autotools 代码都是复制/粘贴而不是从头编写的,并且 autoscan(一个帮助编写 configure.ac 的工具)有时会过于急切地添加检查。
文件将以一些输出函数结束
AM_CONFIG_HEADER(config.h)
AC_OUTPUT(Makefile src/Makefile nls/Makefile man/Makefile tests/Makefile)
这些用于使 ./configure 脚本生成相关文件。
启用和禁用检查
到目前为止,我们只看到了“硬”依赖关系。许多软件包对各种额外功能(图形工具包、添加功能的库、解释器、特性等)提供可选支持。如果我们幸运的话,这可以通过 --enable-foo 和 --disable-foo 开关传递给 ./configure 来处理,这些开关是从 autoconf 规则生成的。
一个简单的 --enable / --disable 函数可能看起来像下面这样
AC_MSG_CHECKING(--enable-cscope argument)
AC_ARG_ENABLE(cscope,
    [  --enable-cscope         Include cscope interface.],
    [enable_cscope=$enableval],
    [enable_cscope="no"])
AC_MSG_RESULT($enable_cscope)
if test "$enable_cscope" = "yes"; then
  AC_DEFINE(FEAT_CSCOPE)
fi
有时会根据某个选项是否启用包含更复杂的检查。还有一些预定义的宏,包括 AC_ARG_ENABLE。因此,使用 AC_ARG_ENABLE 对 configure.ac 进行 grep 可能不会给出完整的列表。更好的方法是使用 ./configure --help 并检查输出。
./configure 提供 --enable 或 --disable 开关时,使用第三个参数,而当未传递此类开关时,使用第四个参数。一个常见的误解是第三个是启用,第四个是禁用——事实并非如此。您可能会遇到处理错误的软件包。检查软件包是否正确使用此宏的一种简单方法是安装可选依赖项,然后尝试所有 ./configure。 ./configure --enable-foo 和 ./configure --disable-foo。如果第二次和第三次运行给出相同的结果,则说明某些地方出了问题。如果第一次运行的结果与第二次和第三次不同,则很有可能误解了 AC_ARG_ENABLE 参数。
带和不带检查
一个简单的 --with / --without 检查可能如下所示
AC_MSG_CHECKING([whether to enable foo])
AC_ARG_WITH(foo,
    [  --with-foo           enable foo support],
    with_foo=$withval,
    with_foo=yes)
AC_MSG_RESULT($with_foo)
同样,第三个参数用于“指定”,第四个参数用于“未指定”,并且有一些标准宏包含 with 选项。
自动检查
可以编写绕过手动启用/禁用约定的 autoconf 规则(或者只是忽略用户请求的内容)。如果您的软件包执行此操作,则必须对其进行修复以避免依赖项问题。
最常见的形式是软件包简单地使用 AC_CHECK_LIB 来决定是否启用某个功能。如果您发现某个软件包执行此操作,则必须更改其行为。
configure.ac 的引用规则
在后台,autoconf 大量使用 m4 宏处理器来完成工作。 m4 的引号字符由 autoconf 设置为 [ 和 ],分别表示开始和结束引号。使用 " 或 ' 可能会产生意外的结果。
要包含一个文字左方括号,最简单的方法是使用特殊字符串 @<:@。对于右方括号,使用 @:>@。
例如
AC_MSG_RESULT(the first)
AC_MSG_RESULT([the second])
AC_MSG_RESULT("the third")
AC_MSG_RESULT(@<:@the fourth@:>@)
AC_MSG_RESULT([@<:@the fifth@:>@])
给出
    the first
    the second
    "the third"
    [the fourth]
    [the fifth]
如有疑问,通常最安全的方法是使用 [ ] 引用宏参数,而不是不加引用。
Makefile.am 文件
Makefile.am 文件由 automake 处理以创建 Makefile.in, Makefile.in 又由 configure 处理以创建 Makefile, Makefile 又由 make 用于构建软件。
基本格式类似于 Makefile。但是,您会看到设置了各种“特殊”变量,而不是手动编写每个规则。
一个非常简单的例子
bin_PROGRAMS = myapp
myapp_SOURCES = myapp_commandline.c myapp.c
所有标准的 GNU 规则都将生成,因此 make。 make clean。 make distclean。 make dist 等等都将在这里工作。
您也可能会看到一些标准的 Makefile 结构出现在没有标准的 automake 方法来处理某些任务时。例如
CLEANFILES = glep31check.1
man_MANS = glep31check.1
EXTRA_DIST = glep31check.in
%.1 : %.in
    @regex_cmd@ -e "s,\@VERSION\@,$(VERSION),g" $? > $@
这里, @regex_cmd@ 变量将被替换为 configure 在创建 Makefile 时检测到的任何内容(在本例中为 sed)。这通过 configure.ac 中的宏 AC_SUBST(VARNAME) 处理。
Makefile 变量
有时,行为不良的 Makefile.am 文件会覆盖用户变量,例如 CFLAGS。不允许这样做——请参阅不筛选变量。在这些情况下,应该使用单独的特殊变量——例如,为了设置 CFLAGS, Makefile.am 应该使用 AM_CFLAGS,以便不会忽略用户首选项。
因此,如果 Makefile.am 包含,比如说
CFLAGS="-Wall"
您应该使用 sed 或 patch 将其修改为
AM_CFLAGS="-Wall"
如果您这样做,请记住手动运行 autoconf 然后 automake。
config.h.in 文件
config.h.in 文件由 autoheader 生成。通常您不必担心这个问题,但偶尔您可能需要在构建过程中手动运行 autoheader,如果上游没有提供预生成的版本。
aclocal 和 m4 文件
在 configure.ac 或 configure.in 文件中,您不仅可以调用 autoconf 和 automake 定义的默认宏,还可以调用由特定软件包(如库和程序)定义的其他函数,以正确的方式检查其功能。
这些函数(通常)在 m4 文件中定义,这些文件由软件包放置在 /usr/share/aclocal 目录中。当您需要重新生成 autotools 文件时,可能会出现问题,因为 configure.ac 文件使用的函数可以在用户系统上未安装的 m4 宏文件中定义。例如,对于某些需要库并由 USE 标志禁用的可选功能就是这种情况。如果 m4 文件未安装在用户系统上,则 autoconf 步骤将失败。
为了解决这个问题,大多数软件包只是将其 configure.ac 所需的 m4 宏文件放在源软件包中的 m4 子目录中。不幸的是,即使存在,并非所有 m4 目录都是完整的。
在这些情况下,您需要找出 m4 文件,通常由依赖项安装在 /usr/share/aclocal 中,并确保 src_unpack 阶段使 autotools 可以使用这些文件并调用 aclocal 来重新创建 aclocal.m4 文件,该文件在创建配置脚本时由 autoconf 使用。
通常缺少的不仅仅是一个 m4 文件,因此您可能希望将它们打包成一个 tarball,并将其添加到 SRC_URI 中。在确保 tarball 提取到 ${WORKDIR} 中的某个位置(例如,在 gentoo-m4 目录中)后,通常有两种处理这些宏文件的一般方法,一种用于带有不完整 m4 目录的软件包,另一种用于不带 m4 目录的软件包。
在第一种情况下,您通常希望执行以下操作
WANT_AUTOCONF="2.5"
inherit autotools
src_prepare() {
	default
	einfo "Regenerating autotools files..."
	cp "${WORKDIR}/gentoo-m4" "${S}/m4" || die "m4 copy failed"
	eaclocal -I "${S}/m4"
	eautoconf
}
等等。在第二种情况下,您可以通过这种方式简化它
WANT_AUTOCONF="2.5"
inherit autotools
src_prepare() {
	default
	einfo "Regenerating autotools files..."
	eaclocal -I "${WORKDIR}/gentoo-m4"
	eautoconf
}
无需复制文件。
当分发版中缺少所需的 m4 文件时,最好始终通知上游,要求他们在源 tarball 中添加所有所需的文件,以避免如果宏发生更改则版本冲突。