【Linux】自动化构建-Make/Makefile

前言

上文我们讲到了Linux中的编译器gcc/g++【Linux】编译器gcc/g++及其库的详细介绍-CSDN博客

本来我们将一个对于编译来说很重要的工具:make/makfile

1.背景

在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile可以来定义那些文件先编译,那些文件后编译,那些文件需要重新编译。甚至是一些更为复制的功能

makefile带来是好处就是"一键化编译",只需要一个make命令就可以实现。这极大的提高了开发的效率

会不会写makefile从侧面很大程度的反应了一个人是否具有完成大型工程项目的能力

2.简单认识什么是make/makefile

make是一个命令工具,用于解释makefile中指令的工具

make是一个指令,makefile是一个文件,需要我们自己建立。两个搭配使用就可以实现我们的自动化编译

3.make/makefile的基本使用

3.1简单一键化编译

创建makefile,并使用vim写入内容(m大小写都可以)

复制代码
hyc@hcss-ecs-4ce7:~$ touch makefile
hyc@hcss-ecs-4ce7:~$ vim makefile

makefile的基本结构为:依赖关系+依赖方法

(注:写入依赖方法前,要先点击TAB键。一定要TAB键不要4个空格,这是写书格式!!)

退出并保存,执行make指令,自动化执行编译

复制代码
hyc@hcss-ecs-4ce7:~$ make
gcc test.c -o test

hyc@hcss-ecs-4ce7:~$ ./test
hi,Yuzuriha

hyc@hcss-ecs-4ce7:~$ ls
makefile  test  test.c

3.2简单一键化清理

再次打开makefile,写入清除命令

注:

先忽略.PHONY:clear不看,clear的格式其实和上面的格式都是:依赖关系+依赖方法。只不过clear并没有依赖什么文件,就不写依赖文件

退出并保存,执行make clear,完成一键清除

复制代码
hyc@hcss-ecs-4ce7:~$ ls
makefile  test  test.c

hyc@hcss-ecs-4ce7:~$ make clear
rm test

hyc@hcss-ecs-4ce7:~$ ls
makefile  test.c

大家看到这里可能一头雾水,但是没关系我们来一个一个看

3.2.1为什么这个我们要使用make clear才能达到效果,而前面只需要执行make就可以了呢?

我们可以把这个两个指令交换一下位置,看看效果

我们可以看到此时我们执行make指令时,实现的效果就是清除效果

复制代码
hyc@hcss-ecs-4ce7:~$ ls
makefile  test  test.c
hyc@hcss-ecs-4ce7:~$ make
rm test
hyc@hcss-ecs-4ce7:~$ ls
makefile  test.c
总结:

执行make指令时,会从上到下扫描makefile文件,并且默认执行第一个扫描到的方法。如果想要执行其他方法,可以make + 目标名,显示的调用

3.2.2 .PHONY是什么东西?

.PHONY + 目标名用于声明伪目标

伪目标不是实际存在的目标,而是用于执行特定的命令(如清理)

.PHONT的主要功能是保证对应的依赖关系和依赖方法总是被执行

要理解什么叫总是被执行?我们可以先理解什么叫不总是被执行。我们可以看到当我们多次执行make指令时,第一次正常执行,而后面的都不再执行了。这就叫不总是被执行。

而换做clear,则可以正常执行多次

同样的,当我们使用 .PHNOY修饰test时,也可以反复的执行编译语句

总结:

.PHONY是定义伪目标,其功能是让其对应的依赖关系和依赖方法总是被执行但一般情况下编译都是不要.PHNOY修饰的,因为代码没有经过修改是不需要反复编译的。反复编译会极大的浪费资源。

补充:make是如何判断源文件是否被修改?

1.文件的acm时间

make正是通过两个文件的Modify时间来判断出源文件是否被修改的。

如果可执行文件的时间晚于源文件时间,这代表没有被修改。反之,这代表源文件被修改了想要重新编译。

ACM时间小知识:

Access时间并不是我们想象的我们访问一次就更新一次时间,因为整个系统最频繁的操作就是访问文件,如果每访问一次文件就统计一次时间这会带来巨大的开销。因此,Access时间是会等用户访问到一定次数才会更新。

Modify时间修改,Change时间往往也会一起修改。因为Modify是记录文件内容修改的时间,但是文件内容有修改其体积大小往往会修改,而体积是属于文件属性这一块的,所以Change时间也会修改。

4.make/makefile深入理解

4.1make的推导规则

现在makefile中为一下内容:

执行make指令我们可以看见,执行的指令顺序和我们写入makefile中的顺序是不一样的

因为makefile的推导规则是满足类似栈结构的:myproc由myproc.o文件推导,而myproc.o当先并不存在,要由myproc.s文件推导。那就先把推导myproc的指令入栈,先推导myproc.o文件。以此类推,直到前置条件完成后,通过出栈依次执行后面的指令

4.2makefile的升级之路

4.2.1makefile可以使用变量

makefile可以像我们的编程语言一样使用自定义变量,来指代文件、指令、选项等等。

**:表示这个变量所指代的内容**,比如:(BIN)就表示myproc这个文件

4.2.2makefile中的特殊变量

@:表示目标文件,既(BIN)

\^:表示依赖文件,既(SRC)

特殊符号可以帮助我们简化makefile的书写

4.2.3makefile中一段依赖关系中可以存在多个依赖方法

一段依赖关系中可以存在多个依赖方法,比如这里我们想直观的看到我们做了什么操作,就可以利用echo来输出信息

效果如下:

我们这里看到了我们自己写是echo指令回显了,我们如果想要指令不回显只看效果,可以使用@符号

这样指令就不会回显了

4.2.4makefile处理多文件编译

对于多文件的编译,我们上一篇文章讲到过,我们一般都是先将所有文件编译为.o文件,最后在将所有的.o文件连接

%是makefile下的通配符。%.c:%.o表示将当前路径下的所有.o/.c文件全部展开,比如有100个.c文件,这里就会展开一百个依赖关系,并执行一百个依赖方法

效果如下:

4.2.5makefile最终版本

上面我们说到,如果有多文件的编译makefile的处理方式。确实在依赖方法的书写上,这个便捷多了。但是我们没有考虑到这一切都是建立在使用变量上的,而我们的变量则需要将多个文件表示出来。

如果我们想要编译多个文件,就需要在变量里写多个文件

3个文件还能接受,可对于项目工程来说有上百个文件怎么办?我们不可能一个一个写上去

解决这一问题有两个方法

方法一:

OBJ=(SRC:.c=.o) :语法格式,将.c文件替换为同名.o文件 SRC=(shell ls *.c):使用命令行指令,一键获取.c文件

方法二:

SRC=$(wildcard *.c) :wildcard为makefile的函数,其作用就是获取所有.c文件

至此这就是makefile的最终形态

相关推荐
来鸟 鸣间7 分钟前
vscode 连接远程服务器
服务器·ide·vscode
伤不起bb25 分钟前
Kafka 消息队列
linux·运维·分布式·kafka
Hello.Reader36 分钟前
Git 安装全攻略Linux、macOS、Windows 与源码编译
linux·git·macos
龙仔72539 分钟前
华为云CentOS配置在线yum源,连接公网后,逐步复制粘贴,看好自己对应的版本即可,【新手必看】
linux·centos·华为云
tiging40 分钟前
centos实现SSH远程登录
linux·centos·ssh
Wooden-Flute1 小时前
五、查询处理和查询优化
服务器·数据库·oracle
明月清了个风1 小时前
数据结构与算法学习笔记(Acwing 提高课)----动态规划·树形DP
笔记·学习·动态规划·树形dp
好多知识都想学2 小时前
Linux 文件处理器 sed 和 awk 详细讲解
linux·运维·ubuntu
Johny_Zhao2 小时前
阿里云数据库Inventory Hint技术分析
linux·mysql·信息安全·云计算·系统运维
FBI HackerHarry浩2 小时前
云计算 Linux Rocky day05【rpm、yum、history、date、du、zip、ln】
linux·运维·云计算·腾讯云