当前位置: 首页 > news >正文

【Linux系统】从零掌握make与Makefile:高效自动化构建项目的工具

在这里插入图片描述
各位读者大佬好,我是落羽!一个坚持不断学习进步的学生。
如果您觉得我的文章还不错,欢迎多多互三分享交流,一起学习进步!

也欢迎关注我的blog主页: 落羽的落羽

文章目录

  • 一、make与Makefile是什么
  • 二、使用方法
    • 1. 基本使用方法
    • 2. .PHONY
    • 3. Makefile的扩展语法

一、make与Makefile是什么

一个大型工程中的源文件数不胜数,想象你在开发一个C项目,有上百个源文件,你要把他们全部编译好链接,难道要写上百条gcc命令吗?如果之后修改了一个源文件,还要把所有的源文件重新编译吗?这未免也太麻烦了吧!

于是make与Makefile出手了:

  • make:是一个命令,是一个在Linux系统中常用的自动化构建工具。
  • Makefile:是一个名为Makefile的文本文件,规定make如何构建和管理项目。

二、使用方法

1. 基本使用方法

首先,肯定必须要有写好的源文件吧,为了编译成可执行程序,这里先以一个test.c为例:
在这里插入图片描述

然后,第一步,要创建出Makefile这个文件:touch Makefile
用vim打开Makefile,写如下内容:

test.exe:test.cgcc test.c -o test.exe

其中test.exe test.c称为依赖关系,冒号前是目标文件,冒号后是依赖文件列表(可以为空,表示不需要依赖任何文件)
第二行gcc test.c -o test.exe称为依赖方法,依赖方法可以是任何shell命令,依赖方法可以有很多行,但是必须都以Tab键开头。

写好之后,保存退出Makefile文件,随后在系统中直接执行make命令:

在这里插入图片描述

可以看到,系统就会自动执行Makefile文件中的gcc test.c -o test.exe命令,生成test.exe可执行程序,而且能正常运行。

2. .PHONY

上述语句中,test.exe称为目标文件。
Makefile的语法中,还有一种.PHONY用法,它可以声明一个“伪目标”,伪目标可以自己起名。
伪目标不是一个真实存在的文件,语句.PHONY:伪目标名定义一个伪目标,随后几行也要写出他的依赖关系和依赖方法。

举个栗子,一个项目需要被清理(删除),那我们就可以在Makefile中写下:

.PHONY:clean  #定义clean伪目标
clean:  #依赖关系,没有依赖文件rm -rf test.exe  #依赖方法

保存退出Makefile,随后执行make clean

在这里插入图片描述

其实,在上面生成test.exe的栗子中,我们也可以显示写成make test.exe,效果也是相同的。
使用make命令,后面可以跟“目标名”,然后就会解析他的依赖关系和依赖方法。不加目标名只执行make,make默认只会执行Makefile中的开头第一个依赖关系,只会形成一条完整的推导链。一般我们习惯将项目清理写在后面,make默认执行项目生成。

其实从本质来说,.PHONY定义的伪目标,特性是“总是被执行的”,这个怎么理解呢?
假设现在Makefile中写成这样:

在这里插入图片描述

如果连续执行make,发现第二次make执行失败了,显示说test.exe已是最新

在这里插入图片描述

如果我将test.c的内容修改一下,再一次执行make,却发现又能执行成功了,并且test.exe也随着test.c的内容更新而变化了:
在这里插入图片描述

但是在.PHONY定义的另一种情况下,连续执行make test1.exe,却发现可以一直执行,不会显示程序已至最新:

在这里插入图片描述

我们先来谈论make是怎么判断test.exe是最新的?是通过文件的修改时间判断的:
stat命令能显示文件的详细属性
在这里插入图片描述

其中有三个时间:Access是文件最近一次被访问的时间、Modify是文件最新内容变更的时间、Change是文件最新属性变更的时间。make的规则是,如果目标文件的修改时间晚于或等于所有依赖文件的修改时间,则认为目标文件是最新的,不需要重新构建。反之,如果任何一个依赖文件的修改时间晚于目标文件,则认为目标是过期的,需要重新执行Makefile中的命令来生成它。这个修改时间就是Modify时间。
哦!这下我们就明白一开始的问题了,.PHONY的特性是“总是被执行的”,也就是说:PHONY让make忽略源文件和可执行文件的Modify时间对比,这样命令就可以反复被执行

除了文件内容被修改会改变Modify时间,我们也可以用命令touch 文件手动更新一下这个时间。

小细节:一般Modify时间改变同时,Change时间也会改变。因为内容改变了,文件大小也会改变,文件大小也是文件属性。

3. Makefile的扩展语法

Makefile的内置语法功能十分丰富,我们也需要学习了解一些。

之前我们执行Makefile命令时,发现他还会将命令内容回显一次再执行:
在这里插入图片描述
想要阻止回显,在相应Makefile前加@即可
在这里插入图片描述
在这里插入图片描述

Makefile中也可以定义变量,变量名=内容名,这一个用法有点像C语言中的宏定义。变量就像一个命名的容器,里面存储了一个文本字符串。当你使用这个变量时,make会用容器里的文本字符串来替换它。使用变量要$(变量)
举个栗子:

BIN=test.exe  #定义变量BIN
SRC=test.c  #定义变量SRC
.PHONY:test
test:@echo $(BIN)  #使用变量@echo $(SRC)  #使用变量

在这里插入图片描述
有了变量的用法,大型项目中就可以方便修改变量内容了,不用一个个修改
Makefile中几乎所有内容都能用变量替代,甚至gcc、选项、一条命令等都可以。

在依赖关系中,可以用$@代表目标文件名,可以用$^代表依赖文件列表
在这里插入图片描述

在这里插入图片描述

最后回到一开始的问题,假如我有上百个源文件,想要把它们全部编译起来形成一个程序,在Makefile中难道也要一句句写gcc命令吗?肯定不是这样的。
为了举例,我创建了一百个源文件,假设要把它们编成一个可执行文件
在这里插入图片描述wildcard函数,可以获取当前目录下的所有.c文件,我们可以写SRC=$(wildcard *.c)让SRC代表所有.c文件,以及OBJ=$(SRC:.c=.o)代表SRC的所有.c文件替换为.o同名文件。
然后在依赖关系中,%.o:%.o代表展开当前目录下所有.c和.o文件,且名字一一对应。
依赖方法中,$<代表对于展开的.c文件,一个个交给gcc进行编译。
整个语句为:

BIN=test.exe
SRC=$(wildcard *.c) 
OBJ=$(SRC:.c=.o)$(BIN):$(OBJ)gcc $^ -o $@
%.o:%.cgcc $< -c 

写好以后执行make,就会发现系统会将所有源文件先转换为.o文件,再链接成test.exe文件
在这里插入图片描述

虽然说我们可以不命令生成.o中间文件,但有.o文件的好处是,如果之后修改了其中一个源文件,再执行make时,只会重新编译修改了的源文件,因为其他.o和.c文件的Modify时间没有变化,系统检查后直接回忽略。这样大大减少了整个项目的重写编译时间!

本篇完,感谢阅读!

http://www.dtcms.com/a/524074.html

相关文章:

  • ML:Supervised/Unsupervised
  • 开发网站多少钱北京 工业网站建设公司排名
  • 【后端开发面试题】
  • 【coze】基础概念与使用
  • Java 语法糖详解(含底层原理)
  • 企业网站介绍越南做企业网站
  • 免费建设电影网站宁波优化推广找哪家
  • JAVA1024 类 object类 包装类 享元模式 ;类继承 :interface ;构造方法
  • 树与二叉树的奥秘全解析
  • 《Python 正则表达式完全指南:从入门到精通》(AI版)
  • 【linux】vim快速清空整个文件
  • 基于单片机的故障检测自动保护智能防夹自动门设计及LCD状态显示系统
  • 2025妈妈杯大数据竞赛B题mathorcup:物流理赔风险识别及服务升级数学建模数模教学大学生辅导思路代码助攻
  • 对监控理解
  • 体育数据传输:HTTP API与WebSocket的核心差异
  • 货代如何做亚马逊和速卖通网站dedecms三合一网站源码
  • 燃烧学课程网站建设业之峰装饰官网
  • 做料理网站关键词怎么设置上海专业的网站建设
  • 英文 PDF 文档翻译成中文的优质应用
  • css实现拼图,响应不同屏幕宽度
  • html css js网页制作成品——HTML+CSS度年华电视剧网页设计(5页)附源码
  • 告别内网限制!用StirlingPDF+cpolar打造可远程访问的PDF工具站
  • cms代码做网站高端网站设计教程
  • Tailwind CSS实战:构建仿ChatGPT聊天页面(失败了)
  • DeerFlow多智能体项目分析-依赖LangGraph实现条件路由和中断机制的源码解析
  • 【JUnit实战3_10】第六章:关于测试的质量(上)
  • 容器编排大王Kubernetes——helm包管理工具(8)
  • 南皮县网站建设php网站开发接口开发
  • 【AOA定位与UKF例程】到达角度(AOA)定位后,使用无迹卡尔曼滤波(UKF)对轨迹滤波,MATLAB例程可下载
  • 拒绝笨重,一款轻量、极致简洁的开源CI/CD工具 - Arbess