编译之路

作者: | 更新日期:

为了编译,我们越走越远。

本文首发于公众号:天空的代码世界,微信号:tiankonguse

大家好,这里是tiankonguse的公众号(tiankonguse-code)。
tiankonguse曾是一名ACMer,现在是鹅厂视频部门的后台开发。
这里主要记录算法,数学,计算机技术等好玩的东西。

这篇文章从公众号tiankonguse-code自动同步过来。
如果转载请加上署名:公众号tiankonguse-code,并附上公众号二维码,谢谢。

零、背景

c++语言需要使用g++编译,这个没什么可说的。
但是项目大了,平台多了,文件多了后,我们在编译的路上越走越远,比如makefile、configure、autoconf、automake等等。
下面就来慢慢介绍这些东西。

一、编译

大家平常如果仅仅写一个cpp文件时,往往是一条命令就编译出可执行程序了。
但是学习编译原理课程的时候,龙书告诉我们这一条命令其实包含四个步骤:预处理,编译,汇编,链接。

预处理阶段将源代码中的包含的头文件编译进来,其中宏也会展开。
编译阶段时会先检查代码的规范性、是否有语法错误等,然后把代码翻译成汇编语言代码。
汇编阶段是把”.s”汇编代码转成二进制中间目标文件。
链接阶段将二进制中间目标文件链接成最终可执行文件或者库文件。

这里有人可能会有疑问:为什么会有链接阶段,汇编阶段直接生产可执行文件不就行了吗?
这是因为汇编阶段是将每个cpp文件分别转化为二进制中间目标文件,链接阶段是将所有中间文件打包为可执行程序。

一、makefile

上个小节提到汇编是将每个cpp转化为目标文件,链接起到打包的作用。

这也引入一个问题:假设我们一个程序写了很多cpp文件,就不能方便的使用一个命令来直接生产可执行程序了。
我们需要先分别在汇编阶段生产中间目标文件,最后再链接为可执行程序。

这就需要很多条命令才能编译。
考虑到程序文件分布在多个目录,库文件也在不同的目录,这些事情人工来做显然变得特别复杂。

所以这些事情需要脚本化。
这个脚本就是makefile

又由于这些makefile脚本常常做的事情都差不多,于是makefile脚本规定了一些语法,用来更简洁的编写脚本。
于是makefile也可以成为一种脚本语言了吧。

二、configure

我们有了makefile就可以方便的编译程序了。

可是随着开源的兴起,大家会发现我们的程序在其他人那里不能编译了。
原来由于平台系统的差异,我们系统上存在的库在另一个人那可能没有。

于是我们需要一个工具来检查需要的库在当前系统是否存在,于是configure这个脚本程序就出来了。
当然configure的功能不仅仅检查库存在,还有很多其他的功能,这里只是用来举例方便大家理解。

三、autoconf

上面提到configure用于检查库是否存在。
但是我们一个程序会使用很多库,尤其是系统自带的库。

如果手动去编写这个configure,那工作量将是分成巨大的,而且几乎不可能的。
因为库其实还存在一个依赖问题,一个系统库依赖另一个系统库,我们是不知道的。

所以这里只能使用工具来自动生成configure了,这个工具就是autoconf了。
当然,autoconf这个工具的数据是GNU m4文件。
GNU m4这个文件也需要工具生成,那就是aclocal

四、aclocal

aclocal作用是根据已经安装的宏、用户定义宏、acinclude.m4文件中的宏 将configure.ac文件所需要的宏集中定义到文件aclocal.m4中。
aclocal是一个perl 脚本程序,它的定义是:“aclocal - create aclocal.m4 by scanning configure.ac”

是的,你们有猜错。
aclocal有一个输入文件,叫做configure.ac
这个configure.ac也是使用工具生成的,那就是autoscan

五、autoscan

好吧,目前是2017,至少现在为止,autoscan是尽头了。

autoscan扫描源代码以搜寻普通的可移植性问题,比如检查编译器,库,头文件等,生成文件configure.scan, 它是configure.ac的一个雏形。

六、automake

其实讲configure的时候,有一点没有说。
对于大项目,一般还需要Makefile.in文件。
我们执行configure的时候,会将Makefile.in转化为Makefile

那么问题来了:Makefile.in怎么生成的呢?
你没有猜错,就是automake

automake根据Makefile.amconfig.h.inconfigure.ac三类文件生成Makefile.in
Makefile.am是我们自己写的,config.h.in需要使用工具生成,这个工具的名字叫做autoheader

七、autoheader

autoheader根据configure.ac中的某些宏,比如cpp宏定义,运行m4,生成config.h.in

八、总结

好了,到现在为止我知道大家都分不清谁是谁了。
但是看看下面的图,大家应该就清楚了。

本来我们只是为了编译一个小项目,现在为了跨平台,却越搞越复杂了。

对了现在开通了公众号和小密圈。
博客记录所有内容。
技术含量最高的文章放在公众号发布。
比较好玩的算法放在小密圈发布。
欢迎大家加入看各种算法的思路。

长按图片关注公众号,阅读不一样的技术文章。

本文首发于公众号:天空的代码世界,微信号:tiankonguse
如果你想留言,可以在微信里面关注公众号进行留言。

关注公众号,接收最新消息

tiankonguse +
穿越