您是否曾经下载过一个流行的软件项目的源代码,该项目需要您键入几乎是仪式性的 ./configure; make && make install 命令序列来构建和安装它?如果是这样,您就使用过 GNU Autotools。如果您曾经研究过此类项目随附的一些文件,您可能也会对这种构建系统表面上的复杂性感到震惊。
好消息!GNU Autotools 的设置比您想象的要简单得多,而且正是 GNU Autotools 本身为您生成了那些 1000 行的配置文件。是的,您可以编写 20 或 30 行安装代码,并免费获得其他 4000 行。
Autotools 工作原理
如果您是 Linux 新用户,正在寻找有关如何安装应用程序的信息,则无需阅读本文!如果您想研究软件是如何构建的,欢迎阅读本文,但如果您只是安装一个新应用程序,请阅读我关于 在 Linux 上安装应用程序 的文章。
对于开发人员来说,Autotools 是一种快速简便的方法来管理和打包源代码,以便用户可以编译和安装软件。Autotools 也得到了主要打包格式(如 DEB 和 RPM)的良好支持,因此软件存储库的维护者可以轻松地准备使用 Autotools 构建的项目。
Autotools 分阶段工作
- 首先,在 ./configure 步骤中,Autotools 扫描主机系统(正在运行它的计算机)以发现默认设置。默认设置包括支持库的位置,以及新软件应放置在系统上的位置。
- 接下来,在 make 步骤中,Autotools 构建应用程序,通常通过将人类可读的源代码转换为机器语言。
- 最后,在 make install 步骤中,Autotools 将其构建的文件复制到计算机上相应的位置(在 configure 阶段检测到)。
只要您使用 Autotools,这个过程看起来很简单,而且确实如此。
Autotools 的优势
GNU Autotools 是一款大型且重要的软件,我们大多数人都认为它是理所当然的。与 GCC(GNU 编译器套件) 一起,Autotools 是允许构建自由软件并将其安装到正在运行的系统的支架。如果您运行的是 POSIX 系统,那么毫不夸张地说,您计算机上大多数操作系统都作为可运行软件存在,这要归功于这些项目。
在您的个人项目不太可能是操作系统的情况下,您可能会认为 Autotools 对于您的需求来说是多余的。但是,尽管 Autotools 声名狼藉,但它仍然有很多小功能可能对您有利,即使您的项目是一个相对简单的应用程序或一系列脚本。
可移植性
首先,Autotools 的设计就考虑了可移植性。虽然它不能使您的项目跨所有 POSIX 平台工作(这取决于您,作为编码人员),但 Autotools 可以确保您标记为安装的文件被安装到已知平台上最合理的位置。并且由于 Autotools,高级用户可以轻松自定义和覆盖任何非最佳值,根据他们自己的系统。
使用 Autotools,您只需要知道哪些文件需要安装到哪个通用位置。它会处理其他一切。不再有在任何未经测试的操作系统上都会崩溃的自定义安装脚本。
打包
Autotools 也得到了良好的支持。将带有 Autotools 的项目交给发行版打包者,无论他们打包的是 RPM、DEB、TGZ 还是其他任何东西,他们的工作都很简单。打包工具了解 Autotools,因此可能不需要任何补丁、黑客攻击或调整。在许多情况下,将 Autotools 项目合并到管道中甚至可以自动化。
如何使用 Autotools
要使用 Autotools,您必须首先安装 Autotools。您的发行版可能会提供一个旨在帮助开发人员构建项目的软件包,或者它可能会为每个组件提供单独的软件包,因此您可能需要在您的平台上进行一些研究,以发现您需要安装哪些软件包。
Autotools 的主要组件是
- automake
- autoconf
- make
虽然您可能需要安装项目所需的编译器(例如 GCC),但 Autotools 可以与不需要编译的脚本或二进制资产完美配合。事实上,Autotools 对于此类项目可能很有用,因为它提供了 make uninstall 脚本,以便于删除。
安装完所有组件后,就该查看项目文件的结构了。
Autotools 项目结构
GNU Autotools 有非常具体的期望,如果您经常下载和构建源代码,那么其中大多数期望可能都很熟悉。首先,源代码本身预计位于名为 src 的子目录中。
您的项目不必遵循所有这些期望,但如果您将文件放在非标准位置(从 Autotools 的角度来看),那么您稍后必须在 Makefile 中对此进行调整。
此外,还需要以下文件
- NEWS
- README
- AUTHORS
- ChangeLog
您不必积极使用这些文件,它们可以是单片文档(如 README.md)的符号链接,其中包含所有这些信息,但它们必须存在。
Autotools 配置
在您的项目根目录中创建一个名为 configure.ac 的文件。此文件供 autoconf 用于创建用户在构建之前运行的 configure shell 脚本。该文件必须至少包含 AC_INIT 和 AC_OUTPUT M4 宏。您无需了解有关 M4 语言的任何知识即可使用这些宏;它们已经为您编写好了,并且所有与 Autotools 相关的宏都在文档中定义。
在您喜欢的文本编辑器中打开该文件。AC_INIT 宏可能包含软件包名称、版本、用于错误报告的电子邮件地址、项目 URL 以及可选的源 TAR 文件名称。
AC_OUTPUT 宏要简单得多,不接受任何参数。
AC_INIT([penguin], [2019.3.6], [seth@example.com])
AC_OUTPUT
如果您此时运行 autoconf,则会从您的 configure.ac 文件生成一个 configure 脚本,并且它会成功运行。但这就是它所做的全部,因为到目前为止您所做的只是定义您的项目元数据并调用要创建的配置脚本。
您必须在 configure.ac 文件中调用的下一个宏是用于创建 Makefile 的函数。Makefile 告诉 make 命令要做什么(通常是如何编译和链接程序)。
用于创建 Makefile 的宏是 AM_INIT_AUTOMAKE,它不接受任何参数,以及 AC_CONFIG_FILES,它接受您要调用的输出文件的名称。
最后,您必须添加一个宏来考虑您的项目所需的编译器。您使用的宏显然取决于您的项目。如果您的项目是用 C++ 编写的,则相应的宏是 AC_PROG_CXX,而用 C 编写的项目则需要 AC_PROG_CC,依此类推,如 Autoconf 文档的 构建程序和库 部分中所述。
例如,我可以为我的 C++ 程序添加以下内容
AC_INIT([penguin], [2019.3.6], [seth@example.com])
AC_OUTPUT
AM_INIT_AUTOMAKE
AC_CONFIG_FILES([Makefile])
AC_PROG_CXX
保存文件。现在可以继续处理 Makefile 了。
Autotools Makefile 生成
Makefile 手动 编写 并不困难,但 Autotools 可以为您编写一个,并且它生成的 Makefile 将使用在 ./configure
步骤中检测到的配置选项,并且它将包含比您想到的或想要自己编写的更多选项。但是,Autotools 无法检测到您的项目构建所需的一切,因此您必须在 Makefile.am 文件中添加一些详细信息,automake 在构造 Makefile 时会使用该文件。
Makefile.am 使用与 Makefile 相同的语法,因此如果您曾经从头开始编写 Makefile,那么此过程将是熟悉且简单的。通常,Makefile.am 文件只需要几个变量定义来指示要构建哪些文件以及要安装在何处。
以 _PROGRAMS 结尾的变量标识要构建的代码(这通常被认为是主要目标;这是 Makefile 存在的主要原因)。Automake 识别其他主要目标,例如 _SCRIPTS、_DATA、_LIBRARIES 以及构成软件项目的其他常见部分。
如果您的应用程序实际上是在构建过程中编译的,那么您可以使用 bin_PROGRAMS 变量将其标识为二进制程序,然后使用程序名称作为变量前缀来引用构建它所需的源代码的任何部分(这些部分可能是一个或多个要编译和链接在一起的文件)
bin_PROGRAMS = penguin
penguin_SOURCES = penguin.cpp
bin_PROGRAMS 的目标安装到 bindir 中,bindir 在编译期间是用户可配置的。
如果您的应用程序实际上没有编译,那么您的项目根本不需要 bin_PROGRAMS 变量。例如,如果您的项目是用 Bash、Perl 或类似的解释型语言编写的脚本,则改为定义 _SCRIPTS 变量
bin_SCRIPTS = bin/penguin
Automake 希望源文件位于名为 src 的目录中,因此如果您的项目为其布局使用了替代目录结构,则您必须告诉 Automake 接受来自外部来源的代码
AUTOMAKE_OPTIONS = foreign subdir-objects
最后,您可以在 Makefile.am 中创建任何自定义 Makefile 规则,它们将逐字复制到生成的 Makefile 中。例如,如果您知道需要在安装继续之前替换源代码中的临时值,则可以为此过程制定自定义规则
all-am: penguin
touch bin/penguin.sh
penguin: bin/penguin.sh
@sed "s|__datadir__|@datadir@|" $< >bin/$@
一个特别有用的技巧是扩展现有的 clean 目标,至少在开发期间是这样。make clean 命令通常删除所有生成的构建文件,但 Automake 基础结构除外。它被设计成这样,因为大多数用户很少希望 make clean 破坏使构建代码变得容易的文件。
但是,在开发过程中,您可能需要一种可靠的方法,使您的项目返回到相对不受 Autotools 影响的状态。在这种情况下,您可能需要添加以下内容
clean-local:
@rm config.status configure config.log
@rm Makefile
@rm -r autom4te.cache/
@rm aclocal.m4
@rm compile install-sh missing Makefile.in
这里有很多灵活性,如果您还不熟悉 Makefile,那么可能很难知道您的 Makefile.am 需要什么。最基本的要求是主要目标,无论是二进制程序还是脚本,以及源代码位置的指示(无论是通过 _SOURCES 变量,还是通过使用 AUTOMAKE_OPTIONS 告诉 Automake 在哪里查找源代码)。
定义这些变量和设置后,您可以尝试生成构建脚本,如下一节所示,并针对任何缺失的内容进行调整。
Autotools 构建脚本生成
您已经构建了基础结构,现在是时候让 Autotools 发挥其最佳作用:自动化您的项目工具。开发人员(您)与 Autotools 的交互方式与构建您的代码的用户不同。
构建者通常使用这个众所周知的序列
$ ./configure
$ make
$ sudo make install
但是,为了使该咒语起作用,作为开发人员,您必须引导构建基础结构。首先,运行 autoreconf 以生成用户在运行 make 之前调用的 configure 脚本。使用 –install 选项引入辅助文件,例如指向 depcomp 的符号链接、一个用于在编译过程中生成依赖项的脚本以及 compile 脚本的副本(编译器的包装器,用于考虑语法差异等等)。
$ autoreconf --install
configure.ac:3: installing './compile'
configure.ac:2: installing './install-sh'
configure.ac:2: installing './missing'
有了这个开发构建环境,您就可以为源代码分发创建一个包
$ make dist
dist 目标是您从 Autotools “免费”获得的规则。
它是内置到从您简陋的 Makefile.am 配置生成的 Makefile 中的功能。此目标生成一个 tar.gz 存档,其中包含您的所有源代码和所有必需的 Autotools 基础结构,以便下载软件包的人员可以构建项目。
此时,您应该仔细检查存档的内容,以确保它包含您打算交付给用户的所有内容。当然,您还应该尝试自己从中构建
$ tar --extract --file penguin-0.0.1.tar.gz
$ cd penguin-0.0.1
$ ./configure
$ make
$ DESTDIR=/tmp/penguin-test-build make install
如果您的构建成功,您会找到由 DESTDIR 指定的已编译应用程序的本地副本(在本例中为 /tmp/penguin-test-build)。
$ /tmp/example-test-build/usr/local/bin/example
hello world from GNU Autotools
是时候使用 Autotools 了
Autotools 是一个很棒的脚本集合,用于可预测和自动化的发布过程。如果您习惯使用 Python 或 Bash 构建器,那么这个工具集对您来说可能是新的,但为了它为您的项目提供的结构和适应性,它很可能值得学习。
Autotools 不仅适用于代码。Autotools 可用于构建 Docbook 项目,保持媒体有序(我将 Autotools 用于我的音乐发行)、文档项目以及任何其他可以从可自定义安装目标中受益的项目。
2 条评论