目录
什么是make/makefile
- make和makefile可以快速自动化地构建目标文件。
- make是一个命令;makefile是一个文件,用来保存依赖关系和依赖方法。
- 执行make命令时,会根据makefile的内容来构建目标文件。
依赖关系与依赖方法的举例说明
月底,你找老爹打电话要生活费时,第一步是说明你和你老爹的关系:你是他儿女,他是你爸爸;第二步是告诉他你要钱。
这其中的第一步就是说明依赖关系,第二步是说明依赖方法,也就是先说明为什么要给帮我再说怎么帮我。
写一个makefile——makefile版本1
创建makefile
就在存放源文件的目录下创建,命名要求是makefile或Makefile。
touch makefile
创建好后就可以vim进去编写依赖关系和依赖方法了,这里以源文件为mytest.c,目标文件为mybin举例。
ls > makefile
如果已经先写好了别的文件,用这条指令创建makefile比较方便,它能把你所写的文件名都复制一份到里面。
#version 1
mybin:mytest.c
gcc -o mybin mytest.c
含义说明
- 第一行“mybin:mytest.c”描述的是依赖关系,表示目标文件mybin要依赖对应源文件mytest.c创建。
- 第二行“gcc -o mybin mytest.c”描述的是依赖方法,表示源文件到目标文件的方法是gcc编译。
语法说明
- 描述依赖关系时,语法规则是:目标文件:依赖文件1 依赖文件2
依赖文件与依赖文件以空格分隔
- 描述依赖方法时,语法规则是: 方法命令
前面要加一个tab键
make命令效果演示
有了makefile我们就可以使用make命令快速编译出mybin了。
一下截图将分为三部分分别说明三个问题:
- 红色框选的内容1,说明有了makefile后,可以使用make命令直接得到目标文件了。
- 橙色框选的内容2,说明在make一次后再次make会得到目标文件mybin已经是最新版本,而不再执行make命令的提示。
- 绿色款选的内容3,说明了“rm mybin”将目标文件删除后,可以在次make目标文件了。
make命令效果引申出的问题
由此,我们引申出下面三个问题:
- 多次执行make时的提示是如何知道我的目标文件已经是最新的了?
- 再次make要将目标文件mybin删除,而mybin其实属于一个临时文件,当工程较大时,临时文件很多,有什么办法可以快速删除吗?
- 有没有办法强行多次执行make?
怎么知道我的目标文件是最新的?
先说结论,怎么知道最新:对比两个文件的Modify时间(文件最近修改时间)。
当目标文件依赖多个源文件时,一个源文件的修改就需要重新构建目标文件。
文件的三个时间
下面的命令可以查看一个文件的三个时间。
stat filename
- Access:文件访问时间(不是每次都更新,提高系统整体效率)
- Modify:文件内容修改
- Change:文件属性修改(一般Modify修改Change也修改,内容修改大小修改)
快速清理临时文件——makefile版本2
#version 2
mybin:mytest.c
gcc -o mybin mytest.c
clean:
rm -f mybin
这里我们添加了一组依赖关系和依赖方法,奇怪的是,这组的依赖关系只有目标文件而没有依赖文件,由于没有明确的依赖关系,它可以多次重复执行,因为没有最近修改时间和它对比。
依赖方法是清理掉临时文件mybin。
执行第二组依赖关系与依赖方法要用下面的命令:
make clean
这与两组依赖关系和依赖方法的顺序有关,谁放第一个就可以直接“make”执行,否则都需要“make 目标文件”执行。
强制生成目标文件——makefile版本3
#version 3
.PHONY:mybin
mybin:mytest.c
gcc -o mybin mytest.c
clean:
rm -f mybin
“.PHONY:mybin”可以让mybin成为伪目标,总是被执行,这样就可以一直make编译了。
常用版本——makefile版本4
目标文件在源文件不更改时不重新生成的设计是很好的,不会浪费资源,所以一般不去修改这个,常常.PHONY:的关键字语法都是给clean这组依赖关系和依赖方法用的。
#version 4
mybin:mytest.c
gcc -o mybin mytest.c
.PHONY:clean
clean:
rm -f mybin
其他makefile语法(补充)
$@替代目标文件,$^替代源文件
mybin:mytest.c
gcc -o $@ $^
#$@代表目标文件
#$^代表依赖文件
makefile里的“宏定义”
cc=gcc
flag=-o
mybin:mytest.c
$(cc) $(flag) $@ $^
#cc代替了gcc
#flag代替了-o
.c文件编译全过程的makefile(补充)
mybin:mytest.o
gcc -o mybin mytest.o
mytest.o:mytest.s
gcc -c -o mytest.o mytest.s
mytest.s:mytest.i
gcc -S -o mytest.s mytest.i
mytest.i:mytest.c
gcc -E -o mytest.i mytest.c
clean:
rm -f mybin mytest.o mytest.s mytest.i