带你快速理解Makefile文件

————————————————————————
小编写在前面的话:
Makefile总是让人一头雾水,这次来做个了结吧!

为什么写

一句话小结Makefile作用:去繁存简,挑新编译
减去繁琐的编译指令,写完Makefile后,只需要用命令行工具(windows用cmd)进入到Makefile的同级目录,输入make即可开始编译。如果依赖中有一个文件更新了,则重新执行这条命令,大大缩短编译时间。

如何看懂

Makefile的结构大体分为两个模块:赋值、执行语句:

1.赋值

Makefile中有很多赋值语句,有”=”的就是赋值家族的一员。我们从c语言的逻辑入手,Makefile的赋值和c逻辑类似,就是:目标=参数。把A赋值给B,则A为参数,B为目标。
要注意以下几种不同赋值符号的含义:

符号含义
=基本赋值
:=覆盖之前的赋值
?=如果没有被赋值过则赋值
+=增加等号后面的赋值

不同在于,在c中赋值语句无外乎就是A=B,但是Makefile中可以将赋值和其他功能函数写成一句,大大减少了代码量。下面举两个栗子感受一下:

栗子1:赋值+宏定义
Makefile中的宏定义相当于在头文件中定义全局变量#define xxx,有几种写法都可以达到宏定义的目的:

MakefileC语言
-D A=B#define A B
-D FLAG=true#define FLAG true
-D FLAG#define FLAG 1

结合上赋值语句,如CFLAGS += -D A,意思就是将A定义成一个宏,然后将这个宏赋值给CFLAGS。

栗子2:赋值+函数
为了在赋值的时候使用一些特别的功能,比如提取文件名、字符串模式替换等,会使用到Makefile函数:

函数名作用
shell返回在shell环境中的执行结果
wildcard获取匹配模式的文件名
patsubst模式替换函数
strip去掉空格

函数的具体使用方法可以在使用的时候查一查,在这里就不一一展开描述了。
比如cont1 := $(shell cat cont2) 就是将cont2的内容赋值给cont1(cat是shell命令)。

现在出现了一个奇怪的符号$,不仅如此,Makefile中你可能还会看到很多不明含义的符号@,*,^,<等等,莫慌,我们将在第二个大块“执行语句”内提及。

2.执行语句

首先抓住关键,执行语句的标志是”:”,大概的结构是:

target… : prerequisites …
command

讲话太多,不如实际解析一段代码:

.PHONY: clean
clean:
rm dir

其中clean是要生成的目标,rm dir是目标clean所需的代码。.PHONY声明了clean这个目标是个伪目标。所谓伪目标,就是在make的时候不会执行代码rm dir,而是在make clean的时候才会执行。
在Makefile里还可以执行shell脚本,如 LDIR=$(shell pwd) ,此时只是赋值,shell是函数名,pwd是参数,赋值给变量LDIR,当Makefile执行LDIR变量的时候(@eho LDIR),shell脚本才会被执行。

.PHONY指定了一个编译伪目标,一个Makefile可能会有多个伪目标,如果设置all为第一个目标,如:

.PHONY:all
all: 
...
.PHONY:del
...
.PHONY:clean
...

则执行make就代表make all。也可以用make xxx来单独编译其中一个目标。

Makefile是从第一行开始执行的,当遇到嵌套依赖的时候,先执行最底层的依赖。比如A依赖B,B依赖C,那么在运行到要执行A的时候,会先执行C,再执行B,最后执行A。
听起来是不是不难,之所以有的同学觉得比较难理解,是因为搞不清语句中一些特殊符号的含义。
现在我们就来总结一下使用比较多的符号:

符号含义
@Makefile会将所执行的命令在屏幕上回显出来,如果在命令前加了@表示运行时不回显此命令。
$展开定义的目标
$@表示目标
$^表示展开所有的依赖
$<表示展开第一个依赖
$?表示比目标还要新的依赖文件列表

有了以上这些,我想看大部分的Makefile总不至于一头雾水啦。

如何写

能看懂Makefile之后,我们就可以仿写一些自己的Makefile。在这里,写Makefile还有一些规矩要说。

  1. Makefile中执行命令如果另起一行,必须以[tab]键开头。如果命令紧跟在依赖的冒号后面就不用。用小括号()将$后面的东东包起来。
  2. 当一条命令的返回码为成功,make会执行下一条命令,如果失败,make会中止执行。又似乎后我们并不希望它中止,就会在Makefile的命令行前加一个”-”号,意思是此命令不管成不成功都往下执行。
  3. 如果你的工程好大,也许会用到嵌套Makefile,就是在子目录中还有Makefile指定了该子目录下文件的编译规则,那么在总Makefile中还要执行子目录的make,如
Subsystem:
$(MAKE)-C 子目录名

————————————————————
小编写在结尾的话:
遇到难题不要放弃呀,如果你也在做类似的事情,欢迎给小编发私信交流!若上文小编有理解不对的地方,也欢迎指正!

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值