【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自动化编译 的理解,觉得这篇博客对你有帮助的,可以点赞收藏关注支持一波~😉

相关推荐
无敌小茶14 分钟前
Linux学习笔记之环境变量
linux·笔记
Harbor Lau27 分钟前
Linux常用中间件命令大全
linux·运维·中间件
漫谈网络1 小时前
基于 Netmiko 的网络设备自动化操作
运维·自动化·netdevops·netmiko
꧁坚持很酷꧂1 小时前
Linux Ubuntu18.04下安装Qt Craeator 5.12.9(图文详解)
linux·运维·qt
凉、介1 小时前
PCI 总线学习笔记(五)
android·linux·笔记·学习·pcie·pci
电鱼智能的电小鱼2 小时前
EFISH-SBC-RK3588无人机地面基准站项目
linux·网络·嵌入式硬件·机器人·无人机·边缘计算
电鱼智能的电小鱼2 小时前
基于 EFISH-SBC-RK3588 的无人机环境感知与数据采集方案
linux·网络·嵌入式硬件·数码相机·无人机·边缘计算
小诸葛的博客3 小时前
详解Linux中的定时任务管理工具crond
linux·运维·chrome
一默19913 小时前
CentOS 7.9升级OpenSSH到9.9p2
linux·运维·centos
keep intensify3 小时前
Linux常用指令
linux·服务器·php