编译软件的流程(configure, make和autotools等之间的关系)

如今在各个主流系统平台上安装软件已经是一件非常省心和方便的事。熟悉的Windows平台不说,Mac上有Homebrew, Homebrew Cask等,各种Linux的发行版也有自己的软件仓库。不过爱鼓捣的人时常还是会遇到需要从源码编译安装软件的情况,例如前一阵PHP7刚发布的时候,想要尝鲜就不得不自己编译了。

对我这样基本只会写脚本的语言的人来说,编译是一件很陌生的事。我花了两天时间查了点资料,了解了一下源码的编译相关知识。

下面的内容都是假设在Linux系统下,不过大体的流程是通用的,而且也并没有许多需要实际操作的内容。






如果你去下载某个软件的源码,网站上的“安装指南”可能会简单告诉你如何编译安装,类似这样:

./configure --prefix=/path/to/dir/ #有些可能没有指定--prefix参数
make
make install

现在就从这三行命令开始。

第一行命令的意思是运行当前目录下的configure文件。它是一个脚本,用来在安装前对系统进行检查,确认系统是否具备了编译软件所需的各种条件。以C语言程序为例,configure脚本会确认系统内是否有编译软件所需的编译器,以及所需的各种头文件和库等。

有些源码包内可能没有直接包含configure脚本,但是包含了buildconf脚本(文件名也可能为autogen.sh),它的作用是做一些编译前的准备工作。详见:http://buildconf.brlcad.org/

第二行命令调用了make程序对目录下面的源码进行编译。

但是输入了make命令后又发生了什么?它又怎么知道如何把源码编译成可以运行的软件?

我Google了一些资料,有的讲得不错,但是总觉得没有讲透。后来我查阅了make命令的man page,感觉比Google上解释的更加详细到位。

先讲下什么是make,引用一句来自维基百科的话:

make是一个工具程序(Utility software),经由读取叫做“makefile”的文件,自动化建构软件。

程序的源码里有各种相互包含和连接,因此我们用一个被称为makefile的文件告诉make源码间的相互联系和其它一些必需内容。makefile可以通过make命令的-f参数来指定。默认情况下,如果没有具体指定,make命令会依次尝试 一些默认文件名, 常见的有makefile和Makefile(推荐)等。

光编译了源码不不够,编译生成的二制进程序还和源码呆在同一个文件夹内,我们需要将它们放到具体的目录内才能正确地运行。至于放到哪个目录也是通过makefile中的指令来确定的。

Makefile又是怎么来的呢?如果你曾经打开过makefile就会发现它非常复杂,几乎不会是手写的。事实也是如此,makefile是用configure脚本后自动生成的。源码包内一般会有一个Makefile.in文件,它是生成makefile的模版。configure脚本会检查你的系统,然后用收集到的信息结合Makefile.in模板来生成最终的makefile文件

不过Makefile.in这个模板又是哪里来的呢?是否所有的源码编译时都用同一套Makefile模板来生成makefile?前面提到的configure脚本呢?它又从哪里来?每个源码包内的configure都一样吗?

其实,需要通过上面讲的流程进行编译的源码都采用了一套叫做autotools的工具包来处理源码管理中的一些繁琐步骤。Autotools包含了autoscan, autoconf, automake等工具。

程序员完成了程序的源码后,如果用autotools进行发布前的准备工作,首先会在项目的目录下运行autoscan程序,它会检查目录下面的源码后生成一个configure.scan文件(这是configure脚本的爷爷),然后我们需要对configure.scan进行一些手动的更改(像生成的makefile的文件名之类都可以在这一步更改),然后将其另存为configure.ac(这是configure脚本的爸爸)。如果项目不大,configure.ac文件可能都不会超过20行。最后,用到前文提到的autotools中的autoconf来把configure.ac转换成最终的configure脚本(这是儿子)。

接下来讲Makefile.in。前面已经讲到,Makefile(这是儿子)往往会又长又复杂,需要用configure脚本结合Makefile.in(这是Makefile的爸爸)来自动生成。但事实上,Makefile.in这个模版也常常会又长又复杂,手写的话也不是省心的事。所以我们会用autotools中的automake来生成Makefile.in,真正需要程序员手写的是一个叫Makefile.am(这是Makefile的爷爷)的文件,这个文件里用特定的语法指明了要生成什么目标,由什么源文件生成,要安装到哪个目录等。

概括一下make和automake之间关系:

make是一个工具程序(Utility software),经由读取叫做“makefile”的文件,自动化建构软件;

Automake是一种编程工具,可以产生供make程式使用的makefile。

最后就是将源码打包准备发布了。autotools简化了这项工作,只要运行如下命令,它就能把源码和必要的configure, Makefile等打包成用于发布的软件包了:

make dist

标签: Linux, 编程

添加新评论