添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

接触过Linux开发的人都知道从源代码安装需要执行类似以下的步骤:

1
2
3
./configure
make
make install

目前为止我执行上述命令已经很多次了,但是并不知道它背后的逻辑。在跟进一个还在开发中的项目的时候,上要述步骤并不能完美执行,需要针对作一些修改,是时候挖掘这些咒语背后的操作了。

configure

configure 脚本负责在特定的系统上执行build的准备工作。这确认后续的build和install的依赖关系已经满足,找出使用这些依赖需要知道的所有信息。

Linux程序通常是用C编写的,所以我们需要C编译器,configure脚本通常会检查系统有合适的C编译器,它在哪里以及如何调用。

Build

一旦configure完成,我们就可以执行 make 命令来build软件。它执行一系列在Makefile中定义的操作来编译写好的源代码。

通常下载的源文件tarball中不包含Makefile,取而代之的是一个模板文件 Makefile.in ,configure脚本产生一个针对你的系统定制的Makefile文件。

make install

现在软件已经build成可执行文件了,它们可以被复制到最终的目录。 make install 命令会将build成型的 程序 文件和 文件以及 文档 复制到合适的目录。

通常二进制文件会被COPY到 PATH 的某个目录,manual文件会被复制到 MANPATH ,其它依赖文件会被保存到合适的地方。

make install 的操作也会定义在 Makefile 中,所以软件的安装目录可以通过configure的参数来修改,或者由configure脚本自动从你的系统中发现。

取决于软件安装的目录,你可能需要高级的权限来完成操作,这种情况下一般加上 sudo 就可以了。

脚本从何而来

所有的操作都定义在configure脚本中,它检查你的系统,从模板文件 Makefile.in 生成 Makefile ,那么这个脚本从何而来呢?

如果你打开过任何一个configure文件,或者与之关联的Makefile.in,你会发现它包含成百上千的shell命令,有时甚至比程序源代码还长。

即使从一个现成的configure脚本开始修改,手动编写的难度也是很大的,但是不用担心,它们不用手动编写。

使用这种方式安装的程序通常使用叫做 autotools 的工具包来管理,工具包包括 autoconf , automake 和很多其它工具,它们一起使得软件维护大为简化。最终用户见不到这些工具,但是它们消除了在不同系统上频繁配置安装过程的麻烦。

Hello World

下面以一个简单的hello world程序为例来演示如何使用 autotools .

程序源代码如下:

1
2
3
4
5
6
7
8
#include <stdio.h>
int
main(int argc, char* argv[])
{
printf("Hello world\n");
return 0;
}

创建configure脚本

我们不手工编写configure脚本,而是使用m4sh来编写configure.ac文件来定义configure中的操作。m4sh是m4 macro和shell的结合。

第一个调用的m4 marco是 AC_INIT ,它会初始化 autoconf 并设置一些关于 我们要打包的程序的基本信息。程序名为hellworld,版本为0.1, 维护者为[email protected]:

1
AC_INIT([helloworld], [0.1], [[email protected]])

我们将使用 automake 工具,所以调用AM_INIT_AUTOMAKE macro:

1
AM_INIT_AUTOMAKE

接下来定义依赖关系,程序依赖C编译器,所以

1
AC_PROG_CC

如果还有其它的依赖,我们可以使用其它marco来发现,例如 AC_PATH_PROG 可以在用户PATH下查找程序。

依赖关系完成以后,接下就要使用这些信息生成Makefile了。

使用 AC_CONFIG_FILES 告诉autoconf脚本需要找到Makefile.in,替换变量(如@PACKAGE_VERSION@)为某值(如0.1),将结果写入Makefile。

1
AC_CONFIG_FILES([Makefile])

当一切定义完之后,使用 AC_OUTPUT 来输出脚本。

1
AC_OUTPUT

以下是全部的内容:

1
2
3
4
5
AC_INIT([helloworld], [0.1], [[email protected]])
AM_INIT_AUTOMAKE
AC_PROG_CC
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

至此已经接近完成了,马上就可以发现软件包了,但是我们还没有创建Makefile.in文件。

创建Makefile

类似Makefile,Makefile.in也会很长,所以我们写一个 Makefile.am 文件给automake来创建模板文件。

首先设置一些选项来告诉automake关于项目的结构信息。由于我们没有遵照GNU规范,所以它是一个 foreign 类型的工程

1
AUTOMAKE_OPTIONS = foreign

工程名为helloworld

1
bin_PROGRAMS = helloworld

这一行中包含了许多信息,多亏了automake的 uniform naming scheme

PROGRAMS的前缀称为 primary ,告诉automake工程有哪些properties。例如PROGRAMS需要build,但数据和脚本不需要。

bin 前缀告诉automake此处列出的文件应该安装到变量 bindir 指定的目录,autotools定义了一系列的目录,包括 bindir libdir pkglibdir ,还可以定义自己的目录。

如果想安装一些RUBY脚本作为程序的一部分,可以定义 rubydir 并告诉automake安装ruby脚本到此。

1
2
rubydir = $(datadir)/ruby
ruby_DATA = my_script.rb my_other_script.rb

额外的前缀可以加在安装目录前来定义automake的具体行为。

因为我们定义了一个 PROGRAM ,需要告诉automake源文件位置,前缀为程序名。

1
helloworld_SOURCES = main.c

以下是Makefile.am的全文,它比Makefile或者Makefile.in要短很多。

1
2
3
AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = helloworld
helloworld_SOURCES = main.c

汇总

现在可以生成自己的configure和makefile.in了。首先需要生成autotools使用的m4环境变量。

1
aclocal

现在可以运行autoconf来将configure.ac转换为configure文件,automake则生成Makefile.in

1
2
autoconf
automake --add-missing

发布程序

最终用户只需configure和Makefile.in而不需要autotools生成以上文件的相关文件,所幸autotools也包含发布功能。Makefile包含所有有趣的目标,例如build一个包含发布工程所需的所有文件的tarball。

1
2
./configure
make dist

甚至可以测试该tarball在不同条件下的可安装性

1
make distcheck

总结

现在我们知道那些咒语的奥秘了
在维护者这里

1
2
3
4
5
aclocal # Set up an m4 environment
autoconf # Generate configure from configure.ac
automake --add-missing # Generate Makefile.in from Makefile.am
./configure # Generate Makefile from Makefile.in
make distcheck # Use Makefile to build and test a tarball to distribute

在使用者那里

1
2
3
./configure # Generate Makefile from Makefile.in
make # Use Makefile to build the program
make install # Use Makefile to install the program