【Linux】make/Makefile——项目自动化构建工具

🌈 个人主页:Zfox_

🔥 系列专栏:C++从入门到精通

目录

  • [一: 🔥 make / Makefile背景介绍](#一: 🔥 make / Makefile背景介绍)
    • [🥝 make是什么?](#🥝 make是什么?)
    • [🥝 Makefile是干什么的?](#🥝 Makefile是干什么的?)
  • [二: 🔥 Makefile的显式规则](#二: 🔥 Makefile的显式规则)
    • [🥝 2.1 .PHONY的作用](#🥝 2.1 .PHONY的作用)
  • [三: 🔥 依赖关系与依赖方法](#三: 🔥 依赖关系与依赖方法)
    • [🥝 概念理清](#🥝 概念理清)
  • [四: 🔥 Makefile小知识📚](#四: 🔥 Makefile小知识📚)
    • [🥝 通配符](#🥝 通配符)
  • [五: 🔥 Makefile取消回显](#五: 🔥 Makefile取消回显)
  • [六: 🔥 共勉](#六: 🔥 共勉)

一: 🔥 make / Makefile背景介绍

💢 首先我们来介绍一下什么是 make/Makefile,以及它们之间的关系。

🥝 make是什么?

  • make 是一个命令工具,是一个解释 makefile 中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi 的 make,Visual C++的nmake,Linux下GNU的make。可见,Makefile都成为了一种在工程方面的编译方法。

🥝 Makefile是干什么的?

  • Makefile 是一个 文件。它是一个工程文件的编译规则,它记录了原始码如何编译的详细信息、描述了整个工程的编译链接等规则。
  • Makefile 带来的好处就是------"自动化编译"。一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率🚀。

🎯 先来看一下 Makefile 的【语法】:

cpp 复制代码
target(目标文件):文件1 文件2(依赖文件列表)		//依赖关系
 
<Tab>gcc -o 欲建立的执行文件 目标文件1 目标文件2		///依赖方法
	 command
	 ...
	 ...
  • target就是我们想要建立的信息,一般称作 目标文件。而后面的依赖文件列表就是具有相关性的 object files,也就是目标文件所依赖的文件(可以是一个或多个,也可以没有)。

🎯 然后看一下 Makefile 的【规则】:

  • 目标文件与依赖文件列表文件之间要使用冒号隔开 目标文件:依赖文件列表
  • target可以是一个目标文件、执行文件,甚至可以是一个标签【后面会提到的伪目标】。
  • 依赖方法前面必须加 Tab空格键
  • 依赖方法以gcc为例,也可以是其他的shell指令【command】。

💢 【总结一下】:make 是一条命令makefile 是一个文件,两个搭配使用,完成项目自动化构建。


二: 🔥 Makefile的显式规则

💢 首先,在Makefile中,#代表着注释,这个是不会被编译进去的。

大家注意,在Makefile里,有一个很反人类的规定,指令前必须打一个 [Tab] 键,按四下空格会报错。

💢 越是接近目标文件的命令,就越是要写在前面。因为程序是按照递归的方式进行依赖文件查找的,看到第一行有一个没见过的依赖文件,就往下一行进行查找,以此类推。

但是有些同学反映,不按照这个顺序来写好像也不会报错,我觉得这可能是和版本有关系,不过保险起见,我建议大家还是按照规范来写Makefile。

举个例子:

cpp 复制代码
hello:hello.o
	gcc hello.o -o hello
	
hello.o:hello.s
	gcc -c hello.s -o hello.o
	
hello.S:hello.i
	gcc -S hello.i -o hello.s
	
hello.i:hello.c
	gcc -E hello.c -o hello.i
  • 假设当前文件夹中有 hello.cMakefile 两个文件,当我们在终端输入make指令的时候,就会自动编译出hello.o,hello.s,hello.i 以及hello可执行文件。

  • 可是,我们又不想要这些不相关的文件,想对这些文件做一些操作,我们把这样的操作叫做伪目标,标志位.PHONY:

在上述代码的最后面加上:

cpp 复制代码
.PHONY:
clear:
	rm hello.o hello.S hello.i

.PHONY:这是固定格式,不能变的,但是下面的clear是自己取的名字,你随便取什么名字都可以,但是clear比较直观。

这样,当我们执行make clear指令后,将只剩下hello.c 和 hello可执行文件。

🥝 2.1 .PHONY的作用

我们发现当我们重复make的时候,只有第一次make是有效的,那是因为gcc指令会自动去比较 ./process 和 process.c 等代码文件被修改的时间如果代码没有被修改,也就没有必要重复执行命令了,提高了效率。


💢 加上标志位.PHONY:的命令就可以被重复执行了。

  • PHONY 配置项的目标clean并不是其他文件生成的实际文件,使make命令会自动绕过隐含规则搜索过程,也就是说执行命令make clean会自动忽略名为"clean"文件的存在 ,因此声明.PHONY配置项会改善性能,并且不需要担心实际同名文件存在与否😮
  • 【通俗一点说】:.PHONY 修饰的目标clean并不是某个依赖项生成的实际文件,因此make命令不再去搜寻当前文件夹下是否有clean文件,这样少去做一些事,自然会改善性能,并且不用担心当前文件夹下是否有同名的文件。

💢 再来个复杂一点的例子:

cpp 复制代码
# 目标文件:test
# 现有文件:program1.c program1.h program2.c program2.h main.c main.h

test:program1.o program2.o main.o
	gcc program1.o program2.o main.o -o test

program1.o:program1.c
	gcc -c program1.c -o program1.o

program2.o:program2.c
	gcc -c program2.c -o program2.o

main.o:main.c
	gcc -c main.c -o main.o

.PHONY:
clean_all:
	rm program1.o program2.o main.o

然后回到命令行,我们来执行一下这个make指令,它就是自动在当前源文件的所在路径下搜寻Makefile,并解释里面命令。之后若是我们需要去编译任何文件,只需要在Makefile里面做一个添加即可,怎么样,是不是很方便。

到这里,Makefile就学会了,就可以用来做事情了,就是这么简单。

后面的内容无所谓你看不看了,放学了...

三: 🔥 依赖关系与依赖方法

通过小小的demo,想必你已经感受到了【自动化构建工具】的强大,我们来仔细看看Makefile中的指令为何要如此书写✍

🥝 概念理清

  • 对于 process:process.c ,冒号左侧是目标文件,右侧是它的依赖文件,所以就可以说它们之间存在一种 【依赖关系】只有 process.c 存在才可以有 process。
  • 那要如何通过 process.c去生成 process 呢❓ 此时就需要使用到下面的这句 gcc指令 gcc -o process process.c 👉它叫做 【依赖方法】

四: 🔥 Makefile小知识📚

符号 含义
= 替换
%.o 任意的.o文件

如果我们写TAR = test,就表示下面的代码中,我们可以用TAR代表test文件

🥝 通配符

符号 含义
$^ 所有依赖文件
$@ 所有目标文件
$< 所有依赖文件的第一个文件

即这个 $@ 和 $^,前者表示:左侧被编译的所有内容,即【目标文件】,后者表示:之后所有内容,即【依赖文件】。

此时,当我们再去make的时候,就可以发现这个特殊符号自动替换成了:两侧的【目标文件】和【依赖文件】。

五: 🔥 Makefile取消回显

写了这么多【make】,你是否感觉每次都会出现回显很麻烦呢?能不能像我们在敲普通指令的时候一样,直接给出结果呢?

  • 这里我们就可以在执行的命令行前加上这个**@**
  • 此时当我们在【make 】和【make clean 】的时候就不会产生任何回显了,可以达到一样的效果。

六: 🔥 共勉

以上就是我对 【Linux】makefile自动化编译 的理解,觉得这篇博客对你有帮助的,可以点赞收藏关注支持一波~😉

相关推荐
十二测试录几秒前
Jmeter自学【8】- 使用JMeter模拟设备通过MQTT发送数据
经验分享·测试工具·jmeter·程序人生·自动化
Tester_孙大壮2 小时前
了解智能运维
运维
林农2 小时前
C05S14-MySQL高级语句
linux·mysql·云计算
Wanliang Li3 小时前
Linux电源管理——CPU Hotplug 流程
linux·嵌入式硬件·嵌入式·armv8·电源管理·cpuhotplug
fnd_LN3 小时前
Linux文件目录 --- mkdir命令,创建目录,多级目录,设置目录权限
linux·运维·服务器
会飞的土拨鼠呀3 小时前
Flannel是什么,如何安装Flannel
运维·云原生·kubernetes
木与子不厌3 小时前
微服务自定义过滤器
运维·数据库·微服务
达帮主3 小时前
7.C语言 宏(Macro) 宏定义,宏函数
linux·c语言·算法
行思理3 小时前
Linux 下SVN新手操作手册
linux·运维·svn
初学者丶一起加油3 小时前
C语言基础:指针(数组指针与指针数组)
linux·c语言·开发语言·数据结构·c++·算法·visual studio