autotools 构建套件

GNU Autotools是一组适用于Unix C/C++工程的构建工具,它的历史最早可以追溯到1988年,最初由Richard Stallman和David MacKenzie在GNU项目框架下开发,目的是为GNU软件项目提供一个跨平台的自动化构建系统。现在的Autotools通常指3个GNU工具包:Autoconf、Automake和Libtool。

对于一个最简单的GNU软件,编译安装的步骤通常是我们所熟知的./configure && make && make install,三条命令分别实现了配置、编译和具体的可执行文件安装,这个过程需要用到configure脚本和Makefile文件。Autotools能够自动生成configure和Makefile脚本,从而简化工程构建脚本的配置和编写。

时至今日对比一些现代化的构建工具,Autotools是非常繁琐、混乱和复杂的,不过由于历史原因,目前大量开源项目依然使用Autotools构建,因此我们有必要了解其基本使用方法。

Autotools的历史

远古时代

在最早期我们要构建一个Linux/Unix下的C/C++项目,我们通常需要手写一个Makefile构建脚本,其中包含了编译、安装等构建目标。然而随着Unix版本越来越多,情况逐渐变得复杂,不同操作系统的库文件、头文件等位置可能不同,使用的编译器、参数等也可能不同,我们手写的一份Makefile在不同平台下就可能构建失败,此时我们通常使用一个configure脚本来解决这个问题。

在早期configure脚本也是纯手写的,这个脚本能够自动判断不同的操作系统等环境,它会基于一个Makefile.in模板通过一系列的配置和模板替换操作,最终生成一个符合当前操作系统和编译器要求的Makefile。

Autoconf时代

随着项目的规模越来越大,支持的平台越来越多,configure脚本也变得越来越庞大,脚本逻辑也变得越来越复杂,尤其是GNU的相关规范存在很多例如-prefix指定安装路径这种规定,纯手写是很难保证这些构建脚本遵循规范、功能完整而且不出Bug的,于是在1991年人们开发了Autoconf。

Autoconf工具用于自动生成configure脚本,它能够自动在configure脚本中实现GNU Build System规范要求的功能,我们只需简单配置一个configure.ac文件,Autoconf工具会读取这个文件并进行后续操作,而不必手写完整的configure脚本。实际上这一步还会涉及aclocal工具,它能够生成一个aclocal.m4文件,这个文件包含了Autoconf工具自定义的宏,它们可以用于检测系统特性、库和头文件等信息,并在生成configure脚本时使用。生成的configure脚本会在执行时做一系列检查和设置,最终通过替换模板文件Makefile.in来生成最终的Makefile。

此外,现在configure.ac文件实际上也可以不用手写,Autoconf还包含了autoscan工具,它可以自动扫描我们的项目生成configure.scan文件,我们在其基础之上修改后就可以作为configure.ac使用,非常的方便。

Autoconf还包含了一个autoheader工具,它能够自动生成一个config.h.in文件,我们只需要在configure.ac中定义这些宏,最终它就可以在configure脚本执行时被转换成头文件config.h并被编译到可执行文件中。

Automake时代

虽然Autoconf解决了configure脚本的复杂性,然而在大型项目中手写Makefile.in模板依然是困难的,于是在1994年人们开发了Automake。

Automake工具用于自动生成Makefile.in模板文件,它需要一个Makefile.am配置文件来描述源代码文件中的依赖关系,Automake能够自动根据配置扫描项目并生成正确的Makefile.in模板。此外Automake是和Autoconf配合使用的,它扩展了一些自定义宏,为了和Autoconf整合也会涉及到aclocal工具,在Autoconf调用aclocal时Automake会将这些自定义宏加入aclocal.m4文件来扩展Autoconf的功能。

Libtool时代

随着Linux、Unix之间的差异越来越大,在不同的操作系统和编译环境下,动态库的命名规则、链接方式以及编译参数等可能会有所不同,这再次给跨平台开发和移植带来了挑战,于是1996年出现了Libtool。

Libtool提供了统一的接口和规范,可以在不同的系统上生成符合标准的动态库,同时隐藏了底层系统差异,简化了开发和维护工作。不过如果只面向Linux平台开发,并且你的项目不涉及到跨平台编译和移植性问题,那么你可以不太关心Libtool,本篇笔记对Libtool不过多涉及。

Autotools工具链

我们理清Autotools的历史脉络后,就可以理解Autotools相关的各种命令行工具和中间文件了,下图展示了这些内容。

Autotools使用例子

这里我们以一个简单的C语言工程为例介绍Autotools的使用,我们的工程包含以下源代码文件。

|_ myfunc.h
|_ bark.c
|_ meow.c
|_ main.c

安装Autotools

假设我们已经安装好了GCC编译器、make等工具,此时我们还需要额外安装Autools工具中的autoconfautomake

apt install autoconf automake

编写相关配置

我们首先需要创建Makefile.am配置文件。

bin_PROGRAMS = main
main_SOURCES = myfunc.h main.c bark.c meow.c

然后我们使用autoscan生成configure.scan,修改其中的内容,并将其重命名为configure.ac

AC_PREREQ([2.71])
AC_INIT([main], [1.0], [gacfox2021@gmail.com])
AM_INIT_AUTOMAKE([foreign -Werror])
AC_CONFIG_SRCDIR([main.c])
AC_CONFIG_HEADERS([config.h])

AC_PROG_CC

AC_CONFIG_FILES([Makefile])
AC_OUTPUT

代码中,AC_PREREQ指定了Autoconf的最低版本;AC_INIT指定了软件包的名字、版本和bug维护地址;AM_INIT_AUTOMAKE用于初始化Automake工具,foreign参数告诉Automake该包不遵循GNU标准目录结构,-Werror参数将所有的编译警告转换为错误;AC_CONFIG_SRCDIR指定了包含源代码的主要源文件,它用于定位确认源码目录的有效性,我们这里源代码都在同一个目录下因此填写其中一个源代码文件即可;AC_CONFIG_HEADERS指定了配置头文件名为config.hAC_PROG_CC用于检查C编译器是否可用,并设置变量CC为所找到的C编译器;AC_CONFIG_FILES宏指定了由Autoconf生成的文件列表,在这里它指定了生成的Makefile;AC_OUTPUT指示Autoconf生成所有配置文件,通常这个宏会在configure.ac文件的末尾,它会根据之前的配置信息生成最终的配置文件。

然后我们执行Autotools工具,该命令会自动执行了autoconfaclocal等工具,最终生成configure脚本和Makefile.in文件。

autoreconf --install

执行configure脚本和make

最后,我们执行configure脚本,该脚本会生成最终的Makefile,最后我们调用make工具编译工程。

./configure && make

此时一个工程就构建完成了。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap