Contents
  1. 1. configure
  2. 2. Build
  3. 3. make install
  4. 4. 脚本从何而来
  5. 5. Hello World
  6. 6. 创建configure脚本
  7. 7. 创建Makefile
  8. 8. 汇总
  9. 9. 发布程序
  10. 10. 总结

接触过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, 维护者为abc@124.com:

1
AC_INIT([helloworld], [0.1], [abc@124.com])

我们将使用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], [abc@124.com])
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定义了一系列的目录,包括bindirlibdirpkglibdir,还可以定义自己的目录。

如果想安装一些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
Contents
  1. 1. configure
  2. 2. Build
  3. 3. make install
  4. 4. 脚本从何而来
  5. 5. Hello World
  6. 6. 创建configure脚本
  7. 7. 创建Makefile
  8. 8. 汇总
  9. 9. 发布程序
  10. 10. 总结