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

🌈 个人主页:Zfox_
🔥 系列专栏:C++从入门到精通

一: 🔥 make / Makefile背景介绍

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

🥝 make是什么?

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

🥝 Makefile是干什么的?

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

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

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。

举个例子:

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:

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

.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文件,这样少去做一些事,自然会改善性能,并且不用担心当前文件夹下是否有同名的文件。

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

# 目标文件: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自动化编译 的理解,觉得这篇博客对你有帮助的,可以点赞收藏关注支持一波~😉
在这里插入图片描述

评论 134
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值