makefile的重要性不用我多说了,翻一翻各种招聘软件上的职位描述就可以发现,如果你会编写makefile来编译大型项目,那么绝对是一个加分项。
今天我们来一步一步从一个low到爆的makefile简化成一个花里胡哨(fei chang jian dan)的makefile。
首先打开linux环境,我们新建几个文件
touch main.c tool1.c tool2.c tool1.h tool2.h
我们的目标就是把这几个文件编译成一个可执行程序test,首先先给里面写个简单的打印函数。
tool1.c
#include <stdio.h>
#include "tool1.h"
void mytool1(void)
{
printf("my tool 1 print\n");
}
同理,tool2.c我们打印 “my tool 2 print\n”,然后我们在main函数里调用mytool1和mytool2。
#include "tool1.h"
#include "tool2.h"
int main(int argc,char *argv[])
{
mytool1();
mytool2();
return 1;
}
这样的编译依赖就形成了一个树结构,main.o依赖于tool1.o、tool2.o,这个简单的依赖关系再加深多层就能够构建一个复杂的大型项目。
接下来我们来编写makefile编译这个工程。
直捣黄龙-确定目标
我们的目标是生成一个可执行文件test,这个test的生成依赖于tool1.o tool2.o main.o
按照makefile的语法开始编写。
target:依赖文件.o
test:tool1.o tool2.o main.o
各个击破-编译各个c文件
确定好依赖文件后,我们就要开始编译单个的c文件了。
main.o:main.c
gcc -c -g -Wall main.c -o main.o
tool1.o:tool1.c
gcc -c -g -Wall tool1.c -o tool1.o
tool2.o:tool2.c
gcc -c -g -Wall tool2.c -o tool2.o
这部分已经开始让人厌烦了,我们现在还只有3个文件,要是大型项目几百上千个文件的话岂不是要把手写断了,惹不起惹不起...我还是想点办法,简化一下。
makefile是包含了自动推导特性的,也就是说,如果我们有一个a.o的目标,makefile是会默认为这个目标文件的源文件名也是a,所以上面的代码的依赖关系可以简化为下面这样。
%.o:%.c gcc -c -g -Wall $^ -o $@
这下清爽多了,妈妈再也不用担心文件太多啦。解释一下上述代码中的$^表示上一行中的依赖源文件,$@表示上一行中的目标文件。
到这里其实编译就已经结束了,已经生成了我们需要的可执行文件。
打扫战场-删除中间文件
删除中间文件就比较简单了,一行代码搞定,这里我们一般只删除中间文件.o 和最终的目标文件test
rm *.o test -rf