在Windows下有诸如vs这样儿“强大”的工具来组织与管理工程,文件层次组织,代码编写,包括选项的设置,编译,链接,都可以在一个窗口中完成(其实背后也是有一个make工具)。Linux下,Unix的哲学,多个不同功能的小工具,组合到一起组成强大的功能,一些小小的文件,我们可以gcc –XXFlags XXOO.c –o XXOO,这样儿来做,但是要是几十个文件,几百个文件呢?还去挨个的输入命令编译?这就是是马上要介绍的make工具,使用make工具,只需要一个命令,就可以构建你的工程。当然,代价就是编写Makefile,make工具就是靠解释Makefile文件来对整个工程进行编译和链接。
这里先给出一个简单的示例,只为说明用法,简单写了几个文件如下:
utils.c,utils.h,display.c,display.h,main.c内容如下(非常简单)
1 |
|
如果按最平常的方式,怎么做呢?你肯定想到,先编译utils,display和main为目标文件,再链接三个目标文件,生成main。至少三个命令,有人说了,也不多,那再想,如果我改动了utils文件,那就要再编译utils,再链接main。所以,该Makefile上场了:
1 | makefile for sample |
这就算是一个小小的Makefile了,慢慢看一下它。
- 首先,#号开头,Makefile的注释,作用从行首到行尾,如果想换行,需要加上\转义换行。
- 接下来有三个名称然后跟冒号,这三个名称(或者叫文件名)叫做目标,就是要生成的东西,无论是生成的中间文件,还是最终文件,都叫做目标,通常放在第一个位置的都是最终要生成的目标,如本例是main。
- 之后冒号后跟了几个空格分隔的名称(文件名),这叫做依赖,看名字就是知道,意思就是目标文件要生成,那么就依赖这几个文件,也就是生成这个目标的必要文件,没有先后顺序。
- 然后,每个目标和依赖的下一行都有一行命令,这个命令就是上面的依赖,通过下面的命令生成目标,需要注意的是,命令需要以Tab开头,不然make不会识别,如果Makefile某个部分过长,可以通过\来转到下一行继续。
根据上面几个部分的具体规则,就可以在本目录下通过make命令构建出最终目标了,默认是生成第一个目标文件,想只生成其中的某个目标,可以使用make obj类似的命令,如本例,如只想生成utils.o文件,则可以用make utils.o命令。每次的构建生成,make工具都会检测每个对应的文件是否是最新生成的,如果某个文件不是最新生的,那么make将重新构建对应的目标,如果某个目标的依赖是这个重新构建的目标,那么同样儿的,这个目标也会被重建。make的工作方式就是解释Makefile,以现第一个目标,然后去寻找它的依赖,如果依赖存在,就寻找下一个依赖,如果这个依赖不存在,就去找对应的依赖的作为目标的构建规则,直到生成这个依赖,有点儿像C语言里面的递归。层层下去,然后最终文件都齐全了,生成最终目标。
再看这个小Makefile的最后三行,.PHONY:XXX指示其冒号后的这个目标是伪目标,也就是防止在make XXX的时候,当前目录下正好有一个叫做XXX的文件,那么make就会现错误或者停止工作了。声明这个伪目标,make XXX的时候,就不会出现上述状况了,而这个例子中clean下面的命令,就是清除生成的文件(包括是中间文件和最终目标,像一般IDE里的清理生成,清理解决方案之类的。),make clean之后,生成的是中间和最终文件就全被删除了,再次make,就是重新构建了。
感兴趣的也可以自己组织一个小“工程”,练习一下Makefile的初级使用。