configure、 make、 make install 背后的原理

整个过程分为三步:

1. 配置 configure

configure脚本是一个由Autoconf工具生成的用于配置软件的脚本,用于在源代码安装之前,根据系统环境自动检测和配置软件包的编译和安装参数。configure脚本的主要作用是根据系统环境的不同,生成适合该系统的Makefile文件,确保软件包能够正确地编译和安装。Unix 程序一般是用 C 语言写的,所以我们通常需要一个 C 编译器去构建它们。在这个例子中 configure 要做的就是确保系统中有 C 编译器,并确定它的名字和路径。

configure脚本通常包含一些用于检测系统特性、依赖性和用户配置选项的命令,例如:

检查系统的操作系统类型、版本和架构
检查编译器类型、版本和特性
检查系统库和头文件的位置
自定义的软件包安装路径和其他选项

通过执行configure脚本,软件包可以根据系统环境进行自动化配置,并生成一个Makefile文件,使得软件包可以被正确地编译和安装到指定位置。

configure命令语法和选项取决于具体的软件包。一般来说,configure命令的基本语法如下:

./configure [options]
./configure是执行configure命令的命令行,[options]表示配置命令的选项,常见选项:

–prefix=DIR:指定软件安装的目录,默认是/usr/local。
–with-:指定依赖的其他软件包。
–without-:指定不需要的软件包。
–enable-feature:启用特定的功能。
–disable-feature:禁用特定的功能。
–help:显示帮助信息。
注意:configure命令的选项和语法在不同的软件包中会有所不同,它不是固定的形式。

2. 构建 make

当 configure 配置完毕后,可以使用 make 命令执行构建。这个过程会执行在 Makefile 文件中定义的一系列任务将软件源代码编译成可执行文件。

你下载的源码包一般没有一个最终的 Makefile 文件,一般是一个模版文件 Makefile.in 文件,然后 configure 根据系统的参数生成一个定制化的 Makefile 文件。

3. 安装 make install

现在软件已经被构建好并且可以执行,接下来要做的就是将可执行文件复制到最终的路径。make install 命令就是将可执行文件、第三方依赖包和文档复制到正确的路径。

这通常意味着,可执行文件被复制到某个 PATH 包含的路径,程序的调用文档被复制到某个 MANPATH 包含的路径,还有程序依赖的文件也会被存放在合适的路径。

因为安装这一步也是被定义在 Makefile 中,所以程序安装的路径可以通过 configure 命令的参数指定,或者 configure 通过系统参数决定。

如果要将可执行文件安装在系统路径,执行这步需要赋予相应的权限,一般是通过 sudo。

这些脚本是怎么产生的

安装过程简单说就是 configure 脚本根据系统信息将 Makefile.in 模版文件转换为 Makefile文件,但是 configure 和 Makefile.in 文件是怎么产生的呢?

如果你曾经试着打开 configure 或者 Makefile.in 文件,你会发现超长而且复杂的 shell 脚本语言。有时候这些脚本代码比它们要安装的程序源代码还要长。

如果想手动创建一个这样的 configure 脚本文件是非常可怕的,好消息是这些脚本是通过代码生成的。

通过这种方式构建的软件通常是通过一个叫做 autotools 的工具集打包的。这个工具集包含 autoconf 、automake 等工具,所有的这些工具使得维护软件生命周期变得很容易。最终用户不需要了解这些工具,但却可以让软件在不同的 Unix 系统上的安装步骤变得简单。

举个例子 Hello world

我们以一个 Hello world 的简单 C 程序为例,来看看如何使用 autotools 打包。

下面是程序源码,源代码文件命名:main.c

1
2
3
4
5
6
include <stdio.h>

int main(int argc, char* argv[]) {
printf("Hello world\n");
return 0;
}

创建 configure 脚本

我们不直接写 configure 脚本文件,而是通过创建一个描述文件 configure.ac 来描述 configure 需要做的事情。configure.ac 使用 m4sh 写,m4sh 是 m4 宏命令和 shell 脚本的组合。

第一个用到的宏命令是 AC_INIT,这个命令会初始化 autoconf 并配置一些关于软件的基本信息。下面这行代码表示,软件名是 helloworld,版本是 0.1,维护作者是 abcde@gmail.com

AC_INIT([helloworld], [0.1], [abcde@gmail.com])

因为这个项目需要用到 automake,所以我们要用下面这个命令来初始化它:

AM_INIT_AUTOMAKE

接下来,我们需要告诉 autoconf configure 脚本需要的依赖。在这个例子中,configure 需要的只是 C 编译器,我们可以用下面这个宏命令来设置:

AC_PROG_CC

如果我们需要别的依赖,可以使用别的 m4 宏命令来设置;例如 AC_PATH_PROG 表示在 PATH 上搜索一个特定的程序。

此时我们已经列出了所有的依赖,我们可以使用它们。前面有提到, configure 脚本会根据系统的信息和 Makefile.in 文件生成 Makefile 文件。

下面这个宏命令 AC_CONFIG_FILES 表示让 autoconf 配置 configure 脚本找到 Makefile.in 文件,并将文件内的占位符用对应的值替换,例如将 @PACKAGE_VERSION@ 替换成 0.1,然后将结果写在 Makefile 文件中。

AC_CONFIG_FILES([Makefile])

最后,当我们把所有配置信息都告诉 autoconf 后,可以使用 AC_OUTPUT 命令去输出脚本:

AC_OUTPUT

下面这段代码是 configure.ac 中的所有代码,相比几百行行的 configure 脚本文件,这些代码好懂多了

1
2
3
4
5
AC_INIT([helloworld], [0.1], [george@thoughtbot.com])
AM_INIT_AUTOMAKE
AC_PROG_CC
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

还差一点我们就可以发布软件了,configure 脚本需要一个 Makefile.in 文件,将系统相关信息填充进去后,生成最终的 Makefile 文件。

创建 Makefile 文件

查看 Makefile.in 脚本发现它的代码又长又复杂,手写不太可能。不过可以先写一个 Makefile.am 脚本,然后通过 automake 工具生成 Makefile.in 脚本。Makefile.am 脚本相比 Makefile.in 简单一些,接下来看看如何去写。

首先需要告诉 automake 项目的结构,因为这里的例子不是标准的 GNU 项目的结构,所以结构声明为 foreign:

AUTOMAKE_OPTIONS = foreign

接下来告诉 automake 需要 Makefile 构建的软件名字:

bin_PROGRAMS = helloworld

上面这行代码其实包含了很多信息,这多亏了 automake 的命名规则。

PROGRAMS 称为「primary 主要」字段,它告诉了 automakehelloworld 文件的属性。例如这里的 PROGRAMS 表示这个文件需要编译,而属性是 SCRIPTS 或 DATA 的文件则不需要编译。

这里的 bin 前缀则是在告诉 automake 后面的文件需要安装在 bindir 变量所指示的路径下。类似 bindir 这样变量还有 libdir 和 pkglibdir,这些都是 autotools 定义的变量,也可以创建自定义的变量。

如果项目中包含 Ruby 脚本,可以定义 rubydir 变量,用来记录安装 Ruby 脚本的地方:

rubydir = ${datadir}/ruby

ruby_DATA = my_script.rb my_other_script.rb

安装路径前可以再一些前缀来让 automake 做一些别的操作。

因为定义了 「PROGRAMS 程序」,所以需要告诉 automake 它的源文件。下面这行代码里,前缀 helloworld 表示编译的软件名字,而不是要安装的的路径。

helloworld_SOURCES = main.c

下面这段是 Makefile.am 脚本的完整代码,和 configure.ac 一起编译 helloworld 软件。相比它生成的 Makefile.in 脚本代码少了很多:

AUTOMAKE_OPTIONS = foreign

bin_PROGRAMS = helloworld

helloworld_SOURCES = main.c

生成文件

现在已经写好了所有需要的脚本,使用 autotools 就可以生成 configure 和 Makefile.in 脚本。

首先需要为 autotools 准备 m4 脚本环境:

aclocal

接下来使用 autoconf 将 configure.ac 生成 configure 脚本,用 automake 将 Makefile.am 生成为 Makefile.in 脚本:

autoconf

automake –add-missing

发布软件

最终使用软件的用户不需要关心使用 autotools 的部分,所以我们只需要把 configure 和 Makefile.in 脚本发布出去就可以了,不需要前面写的脚本。

autotools 也可以帮我们发布软件。Makefile 里有各种各样的命令,包括构建一个可以发布的软件包:

./configure

make dist

还可以测试软件包能否在各种版本系统上安装:

make distcheck

总结

现在终于知道这段安装命令的来历和工作原理了!

下面分别展示下软件发布和安装的命令:

发布:

1
2
3
4
5
aclocal # 设置m4 环境
autoconf # 生成 configure 脚本
automake --add-missing # 生成 Makefile.in 脚本
./configure # 生成 Makefile 脚本
make distcheck # 使用 Makefile 构建一个发布软件并测试

安装:

1
2
3
./configure # 生成 Makefile 脚本
make # 构建软件
make install # 使用 Makefile 安装软件
作者

Amazing Coder

发布于

2020-08-21

更新于

2020-08-21

许可协议

评论