【Linux】自动化构建--make/Makefile
目录
- 前言
- 一、认识make/Makefile
- 1. make/Makefile的使用
- 2. make指令和Makefile的依赖关系和依赖方法
- 二、Makefile基本语法
- 1. Makefile推导过程
- 2. 项目清理
- 3. .PHONY如何做到总是被执行的
- 4. stat指令的ACM时间
- 三、Makefile语法细节
前言
【Linux】Linux编译器–gcc详情点击查看,今天继续介绍【Linux】自动化构建–make/Makefile
make是⼀条命令,makefile是⼀个文件,两个搭配使用,完成项目自动化构建
一、认识make/Makefile
1. make/Makefile的使用
- 使用touch指令创建文件Makefile
- vim打开Makefile写入内容
- 输入make指令(make会在当前目录下找名字叫“Makefile”或“makefile”的文件)
2. make指令和Makefile的依赖关系和依赖方法
- 依赖关系:test.exe可执行文件的形成依赖test.c文件
- 依赖方法:形成test.exe可执行文件需要怎样的操作才能让test.c文件生成可执行文件,这个时候就有了依赖方法
- 依赖方法的代码前面的空格必须使用Tab空格
注意:依赖关系和依赖方法必须是合理的
二、Makefile基本语法
1. Makefile推导过程
- 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并
报错,对于所定义的命令的错误,或是编译不成功,make根本不理
2. 项目清理
- ⼀般clean的目标文件,我们将它设置为伪目标,用
.PHONY
修饰,.PHONY
是Makefile内部的类似于关键字,它的作用是声明一个符号(clean、clear等),这个clean是一个目标文件,所以它也得有对应的依赖关系和依赖方法依赖关系必须存在,但依赖关系列表可以为空
依赖方法可以是任何shell命令
- clean目标只是利用make的自动推导能力来让其执行rm命令,在构建工程的视角看起来就是清理项目,其本质就是删除不需要的临时文件
为什么清理clean,要用make clean,编译成可执行文件test.exe直接make或者make test.exe都行?
- make命令后面跟
目标名
执行该目标名的依赖方法- make默认只会推导一条完整的推导链路
- make默认只会推导第一个依赖关系对应的推导链,如果我们将clean的依赖关系和依赖列表放在文件前面,那么clean直接make就会执行,形成可执行文件test.exe就必须要make test.exe才可以,但是我们一般将clean放在后面
.PHONY
是用来修饰目标文件是一个伪目标,伪目标的本质是:总是被执行的。为什么make/make test.exe只能执行一次,第二次执行就像下面图片展示(告诉我test.exe是最新的)的那样不让反复执行了,但是make clean就能反复执行?
- 当我们将test.exe文件用
.PHONY
修饰时,我们发现make/make test.exe就像clean一样能被反复连续执行了,这就是.PHONY
的本质:总是被执行的
.exe不用
.PHONY
修饰,本质加速编译的效率
- 如果在一个项目中有很100多个.c文件,我们只改了其中一个.c文件,如果使用
.PHONY
修饰,那么每修改一点代码,这100多个.c文件都需要重新编译链接,这样效率就会很低,默认情况下如果原文件没有修改过,直接使用原编译的.exe可执行文件就可以了gcc怎么判断是否是老代码?
- 我们的test.c文件的创建时间是比他的可执行文件test.exe创建时间要早的(如果源文件的修改时间比可执行文件的时间早,那么说明该文件在生成可执行文件后没有修改过,不需要重新编译,反之说明修改过,需要重新编译)
3. .PHONY如何做到总是被执行的
上面我们已经说过通过比较源文件和可执行文件的修改时间(
Modify时间
)来确定是否需要重新编译,我们可以通过stat 文件名
查看文件的时间信息
从上面可以看出源文件修改时间比可执行文件时间早,因此后面我们无法再次编译,那么我们有什么办法能再次编译呢?
- 修改代码
- 使用
touch
指令,能够更改文件的时间
从图片结果可以看出源文件修改时间从16:12:12--->20:09:14
,再次make允许编译
总结:.PHONY能做到总是被执行的原因是:让gcc或者对应的指令忽略Modify时间对比新旧
(有些指令不关心时间)
4. stat指令的ACM时间
文件 = 文件内容 + 文件属性
Modify:对文件内容做更改的时间
Change:对文件属性做更改的时间
- 下面结果中我们可以看到,使用vim修改了文件内容,但是Modify和Change时间都被修改了,为什么?
因为更改文件内容,会影响文件大小,且文件的Modify也是文件属性
Access:表示文件最近被访问的时间(查文件内容或属性都叫做访问文件:
cat && stat
,access更偏向于访问文件内容),但是我们发现我们使用cat指令访问文件后Access时间有的时候会更改,有的时候不会更改,为什么?
- 因为文件内容和文件属性如果更改了都必须在磁盘上刷新(如果不在磁盘上刷新,此时电脑关机,那么更改的文件将没有了)
- 文件查看的比重比文件修改的比重大(修改文件内容也得打开文件后才能修改)
- 如果每次查看都更新Access时间,那么文件属性就会被更改---->刷新到磁盘---->会增加访问磁盘的次数(磁盘是外设,效率低)---->OS整体效率降低
访问文件内容,特定次数后才会更新一次时间
三、Makefile语法细节
- 回显问题
执行make指令,我们发现Makefile中的指令也会回显出来,怎么让回显不显示呢?Makefile中在指令前面加入@
- Makefile的规范写法
$@ 和 $^
:@ 和 ^是变量, $@对应目标文件, $ ^对应的是目标文件的依赖文件列表
%.o:%.c
:%的作用将该目录下的.o和.c文件展开
$<
:将冒号左边的文件一个一个的拿过来
- {x…xx}:现在我们创建100个.c文件,使用指令
touch test{1..100}.c
,使用rm test{1..100}.c
删除这100个文件
现在怎么编译这100个文件呢?
将这100个文件编译成.o文件后,再统一链接成可执行文件
我们还可以进一步的替换gcc、echo、rm,这样只需要修改文件头部的内容就可以通用