- 基本语法
makefile用于大型文件编译,原因是它编译时只编译依赖时间戳比目标新的文件,而不必去重新编译整个工程文件。换句话说就是用我们指定的方式去编译文件
基本规则:
![](https://img-blog.csdnimg.cn/img_convert/d136b2594f65194cd44751d78d5630c2.png)
目标是指一个普通文件,也可以是一个标签或者执行文件。
依赖是指生成这个目标需要的文件或目标,以空格隔开依赖
命令是指任意的shell命令,注意一定要以tab键开头
它的基本规则是:当任意一个及以上的依赖文件的时间戳比目标要新,或者目标不存在,就执行下面的命令
来写一个最简单的makefile:
![](https://img-blog.csdnimg.cn/img_convert/912fcdb2fe9f5106d8ae7fdd0741a0dd.png)
![](https://img-blog.csdnimg.cn/img_convert/ebc61444b70ab207a4cd91464373b20e.png)
分析:原来只有a.c与Makefile这两个文件,在编写好Makefile后,执行make,此时没有生成a这个目标文件,它会执行后面的命令。有了a之后再执行make,此时显示目标文件是最新的,因为依赖文件没有更改,时间戳自然比生成的文件落后,所有没有执行命令。利用touch命令更新一下a的时间,此时再执行make,它又会执行命令。
假想目标.PHONY:避免目录下含有与目标相同的文件名引起冲突。
用法就是用.PHONY修饰一下目标即可
all:它只是一个约定俗成,是所有目标的集合,和常规目标用法没啥不同,只是习惯把要生存的多个目标放到这儿来生成,例如,我们要生成两个目标文件,如果一个一个写,它只会执行第一个目标,后面的只能通过make+指定目标才能执行,举例
![](https://img-blog.csdnimg.cn/img_convert/868e548eda92193912e4dd6b39d7c317.png)
执行make,结果只执行第一个
![](https://img-blog.csdnimg.cn/img_convert/cf94267151df57619202ed0c02585516.png)
要执行第二个,就应该
![](https://img-blog.csdnimg.cn/img_convert/7d22b144fb32675471cceeb26c2953b0.png)
而想要生成两个目标就应该这样
![](https://img-blog.csdnimg.cn/img_convert/64fbd81e3f4f6f9a06e97c9f1a13c430.png)
直接make或者make all结果相同,也可以单独执行main1或者main2
![](https://img-blog.csdnimg.cn/img_convert/1dcd827ba426a91d42b400588961efc4.png)
- 变量
大型文件自然不可能像这么简单,我们得学习一下makefile变量
makefile的变量全是字符串形式,不需要定义类型,变量间以空格隔开。
变量:分为立即变量与延时变量
即时变量赋值(立即覆盖原值):
:= 覆盖前面的值,即刻确定
延时变量赋值
= 用到时才确定
?= 如果是第一次定义变量才起效,前面如果已经定义则此时赋值忽略
特殊
+= 附加,它是即时变量还是延时变量取决于前面的定义
举例说明
![](https://img-blog.csdnimg.cn/img_convert/4b16ea768fce9864b42f38f549ac5856.png)
![](https://img-blog.csdnimg.cn/img_convert/4b9324844a62172b7d3e1f5fdc9c75fd.png)
x1为即时变量,在用时c的值还未确定为空,所以打印结果为空
x2为延时变量,执行完时,c的值为100,所以打印结果为100
x3与x2也是延时变量,
![](https://img-blog.csdnimg.cn/img_convert/4e157df0fb0ae71dffdcd06327e8ec91.png)
![](https://img-blog.csdnimg.cn/img_convert/cefd2bd9c9c4433c160cb0535ac4a382.png)
在4,5行皆是对原本值附加d的值,x1是即时变量,附加后也是,附加时d的结果未确定,所以还是为空。而x2是延时变量,追加后也是延时变量,结果值自然可以附加后面d定义的值。
- 常用函数
参数与函数名以空格隔开,参数之间用逗号隔开
函数1.foreach
![](https://img-blog.csdnimg.cn/img_convert/54cfa219fa34e6f2dafa0f2cddda733a.png)
用法:将list的所有值拿出来赋给var,再执行text,
eg:
![](https://img-blog.csdnimg.cn/img_convert/948536f994e42b360c09f39063f0702f.png)
结果:
![](https://img-blog.csdnimg.cn/img_convert/cfff7ae867b91374812d2f1ec1fca96a.png)
函数2.filter与filter-out
![](https://img-blog.csdnimg.cn/img_convert/ebb7eb2a5c82876f9a326af909cc4929.png)
用法:在text中取出符合pattern格式的值
![](https://img-blog.csdnimg.cn/img_convert/d14d2fc17dd7aa85be3479f2dad6326b.png)
用法:取出text中不符合pattern格式的值
eg:
![](https://img-blog.csdnimg.cn/img_convert/0304e9f3aad8e7432a6b7937bbe5ca26.png)
![](https://img-blog.csdnimg.cn/img_convert/acecf081f01bd023cf99cd6c4a4cded9.png)
函数3:wildcard pattern
![](https://img-blog.csdnimg.cn/img_convert/e3cbb834bc089717eab6679f2d003295.png)
用法:pattern定义了文件名的格式,wildcard取出其中存在的文件
eg:
![](https://img-blog.csdnimg.cn/img_convert/10549cda654e18fd63ef5a8923e737f0.png)
![](https://img-blog.csdnimg.cn/img_convert/79acbdaccda390dfd3cd8825fcb126a3.png)
释义:当前目录下含有a.c b.c文件,运用wildcard函数后,它会将将files中真实存在的文件拿出来,也就是a.c和b.c
函数4:patsubst
![](https://img-blog.csdnimg.cn/img_convert/bbd5ca2f09be960087b149f2f6d8c7ee.png)
说明:将var的值全部拿出来,将符合pattern格式的值替换为replacement格式,不符合格式的不做改变
eg:
![](https://img-blog.csdnimg.cn/img_convert/4a818bace5fb2713f556132adb2f1e81.png)
![](https://img-blog.csdnimg.cn/img_convert/6a64c8285d7535f214e1c9b100d7a85d.png)
- 常见符号
*:在系统里匹配的通配符
%:在makefile里匹配的通配符
$@:目标文件
$<:第一个依赖文件
$^:所有的依赖文件
$?:依赖中比目标新的文件
好了,到这儿我们应该编写一些基本的makefile是没有多大的问题了,基础篇到这儿就结束了,所有内容只是我的一些实验和结果总结,如果有错误还请指出,接下来还有一些补充,后面总结完再发