前言
这篇学习笔记是根据陈浩写的《跟我一起写Makefile》系列文章总结出的内容,这个系列文章对Makefile的讲解深入浅出,对于新人十分友好。推荐大家在有时间的情况下,通读全文。
在写文章到一半的时候,惊闻陈浩老师离世,中文互联网永远失去了一位充满理想的技术人,写这篇文章也是感谢陈浩老师为我们贡献了如此之多的好博文,您永远都是我的榜样。希望中国的程序员不要那么的苦逼,不是每天996,而是真正的在探索技术,利用技术来提升自己的生产力。
这是第一次感受到程序员身体健康的重要性,也希望广大程序员朋友积极锻炼身体,身体才是革命的本钱。
Makefile思维导图
一些有用的例子
将所有.c文件编译为目标foo
1 | objects := $(patsubst %.c,%.o,$(wildcard *.c)) |
其中$(wildcard *.c)
找到所有的.c
文件,通过$(patsubst %.c,%.o,$(wildcard *.c))
将所有.c
文件替换为.o
文件当做object变量的值。最后的依赖规则中成为foo目标的依赖项,其中的.o
会被自动推导为对应.c
文件的编译生成内容。
生成多个目标文件
1 | all : prog1 prog2 prog3 |
all依赖3个prog,这样就能全部执行对应的生成命令,最后得到3个目标文件。
清理不同类型文件
1 | .PHONY : cleanall cleanobj cleandiff |
定义了3个伪目标,这样能通过make cleanall
清除所有目标,make cleanobj
清除.o
文件,make cleandiff
清除.diff
文件。
将多个存在生成规律的目标整合成一条规则
1 | bigoutput littleoutput : text.g |
$@
表示目标的集合,会依次从中取出目标用于执行命令,之后又使用$(subst output,,$@)
将output替换成空。
利用静态模式规则实现批量依赖规则
1 | files = foo.elc bar.o lose.o |
$(filter %.o,$(files))
从files变量中筛选出.o
文件,这些.o
文件全部匹配上.c
文件。对应的执行规则$<
在模式匹配中会表示一组依赖文件集,和$@
组合在一起刚好是对所有符合的.c
文件生成对应.o
文件。
自动更新Makefile中的依赖关系
1 | %.d: %.c |
将所有的.d
文件依赖于.c
文件,当我们的c文件更新时会自动更新.d
依赖文件。首先会删除原有的依赖文件,之后则是生成新的依赖文件。$$$$
意为一个随机编号,生成的文件名会拼接上这个随机符号,这里的名称可能是name.d.12345
。第三行的sed是将其中的依赖关系加入xxx.d
文件,第四行则是删除临时文件。如果我们要使用这个依赖关系,可以直接用include批量引入。
嵌套执行Makefile
1 | subsystem: |
由一个主Makefile开始,去执行子目录中的Makefile,这样的结构能有效减少Makefile的复杂度。
使用MAKELEVEL对不同的调用层作区分
1 | ifeq (0,${MAKELEVEL}) |
系统变量MAKELEVEL
记录了当前的Makefile的调用层数,嵌套调用的时候这个变量数值会增加。
利用VPATH搜索路径指定依赖文件的搜索路径
1 | override CFLAGS += $(patsubst %,-I%,$(subst :, ,$(VPATH))) |
如果$(VPATH)
的值为src:../headers
,那么上面的语句将会返回-Isrc -I../headers
。