< 6 > Linux 自动化构建工具:makefile 详解 + 进度条实战小项目

1. 自动化工程构建 make / makefile ------ 前置语法知识讲解

make是一个命令

makefile是一文件------描述的是如何编译当前工程
先看看怎么使用的:

1.1 依赖关系,依赖方法

makefile:依赖关系 和 依赖方法 的集合!
依赖关系:我(code.c) 和 我爸(code),我依赖我爸。我们是依赖关系

依赖方法:我可以找我爸拿生活费,我爸可以让我干事情

有了依赖关系,那还要有依赖方法,事情才能干成。不能只挂名,不干事

1.2 make执行时,会默认只执行第一个目标文件,及其依赖方法

make执行时,会默认执行第一个出现的目标,及其依赖方法
这也就是为什么,刚刚 make 会直接执行gcc命令,因为code 是从上到下 第一个目标,gcc是其依赖方法

如果反过来,那就先执行rm了!

1.3 makefile自动编译推导过程

其实:

  • make 内部维护一个栈,从第一个目标开始解析;
  • 如果目标无法直接生成 ,就把它的生成方法压入栈 ,然后向下查找能生成该依赖的目标
  • 重复这个过程:无法生成 → 压栈 → 继续向下找 ,直到找到最底层能直接生成的文件(如 .c 文件);
  • 找到后,开始弹栈执行所有方法
  • 因为栈是后入先出 ,所以执行顺序和压栈顺序完全相反,从最底层一步步向上生成,最终完成第一个目标

总结:

无法直接生成目标文件,就会 方法压栈 + 向下递推,直到找到能执行的方法+依赖链闭环,再全部弹栈,最终生成目标文件 ,找不到就报错,停止。
依赖关系相对应,逻辑闭环,就会压栈此方法 并 返回弹栈,但是依赖方法执行不了,就会报错中止,后面的方法不再执行。

1.4 构建工程,清理工程

1.5 .PHONY ------ 伪目标

.PHONY :伪目标 也是 目标,也有依赖文件,依赖方法

它的意义是:强制执行依赖方法!总是执行当前依赖方法

最佳实践:clean等,清理工程的方法,都建议用 .PHONY 修饰! 其他都不建议!

1.6 增量编译 / 有效编译 ------ 提高编译效率,不让重复编译

1.7 ACM时间 ------快速定位被修改的文件

之前说过:Access,Modify,Change,3个文件的时间信息。

再次复习一次:

名称 核心含义 触发更新的操作 make 是否关注?
Access 文件被读取 / 打开的时间 访问,打开文件、读取文件内容 ❌ 不关注
Modify 文件内容被改动的时间 写入、追加、覆盖文件内容,内容实质性变化 ✅ 核心判断依据
Change 文件元数据被改动的时间 修改权限、重命名、修改文件大小等文件元信息 时,并且Modify时间变了!Change时间一定改变 ❌ 不直接关注

1.71 文件M时间改变,make必定重新编译

make 会读取 M 时间 : 文件内容被修改,M时间更新。

一旦M时间更新,就代表可能更新编译结果,make就必须重新编译它!

1.72 短时间高频访问,A时间不会每次都改变

读取文件内容指令,几乎是最高频的命令。这意味着A时间会频繁改动。但是它又没有实质性的内容,信息变动,又显得不那么重要!

所以Linux对A时间有更新策略:短时间高频访问,视为一次动作!不会多次改变A时间!

目的是减少多次"几乎无意义"的更新,以提高Linux效率!

2. Makefile 的 实用语法指令

2.1 @ ^ ------ 目标文件 和 依赖文件列表

$@ 代表目标文件

$^ 代表依赖文件列表

2.2 B=A ------ 全局定义变量名,类似于C的宏替换

B=A ------ 全局定义变量名,类似于C的宏替换

等号两边不建议空格,实用例子:

2.3 @ ------ 避免指令语句回显,打乱观察

2.4 $(A) ------ 原文件名可被 echo 打印,用于debug

2.5 $< ------ 将依赖文件列表所有文件,逐个编译

2.6 %.c %.o ------ 展开当前文件所有.c / .o 文件

有了它,才是真正的泛型编程!上面都是对单,这下可以对群!整体自动推导,整体编译!


整体替换:

2.7 (shell ls \*.c) ------ ()表达式可以写入shell指令

2.8 $(Src:.c=.o) ------ 将Src的所有.c文件变为同名.o

2.9 $(wildcard *.c) ------ 函数,自动获取所有 .c 文件

3.0 makefile 最终版本

3. Linux 第一个 系统程序 ------ 进度条

3.1 前置知识:\r\n 与 \n :回车换行 与 换行

我们经常混淆回车,换行,回车换行 这三个概念,以为都** 是换到下一行**,实际上:

名称 转义符 作用(核心含义)
回车 \r 光标回到当前行的开头不换行
换行 \n 光标换到下一行,不回到行首
回车换行 \r\n 回到行首 + 换到下一行,完整换行

C/C++ 的换行,其实是回车换行! 实际上应该是:\r\n

3.2 前置知识:printf存在缓冲区,不会立刻打印内容,fflush立即刷新

编写一段程序:包含:打印内容,休眠3秒


为什么? 难道是先执行sleep,然后执行printf吗?

不是!C/C++程序是严格按照上到下的顺序执行,执行sleep前,printf一定执行完毕!

答案是:已经打印好了,但是缓存在内存缓存区里了!程序结束时,会强制刷新缓存,缓冲区会自动刷新,把缓存中的内容,一次性全打打印到屏幕上
怎么才能立即刷新?

\n 或者 fflush(stdout) :这两个可以立即刷新!

3.3 前置知识3:\r 的作用 ------ 回到行首,作用:覆盖上一次的结果

3.4 进度条纯享版------展示功能

我的问题:

1.没注意宏定义

2.命名不够规范

3.旋转光标,我写了字符数组,不够规范

另外还有头文件、主函数测试用例文件,简单调用声明

3.5 进度条进阶版------可实际使用

相关推荐
j_xxx404_9 小时前
MySQL表操作硬核解析:从 CREATE TABLE 到磁盘文件、ALTER TABLE 与 DDL 风险
运维·服务器·数据库·c++·mysql·adb·ai
ba_pi9 小时前
k8s删除pod
linux·容器·kubernetes
前端程序猿i9 小时前
Nginx 教程:从入门到能上线
运维·nginx
小蜜蜂dry9 小时前
nestjs实战-权限二:角色模块
前端·后端·nestjs
默默且听风9 小时前
Ubuntu 22 环境下 VS Code Codex 插件无法打开的排查与修复记录
后端·ai编程·vibecoding
AskHarries9 小时前
权限模型:Shell、Browser、文件读写的安全边界
服务器·前端·网络
小蜜蜂dry9 小时前
nestjs实战-权限一: 菜单模块
前端·后端·nestjs
木雷坞9 小时前
Qdrant Docker 部署教程:数据卷、API Key 和集合初始化
运维·docker·容器·知识图谱
wuminyu9 小时前
Java锁机制之park和unpark源码剖析
java·linux·c语言·jvm·c++
团象科技10 小时前
外贸站选海外服务器 拆解跨境运营中常被忽略的核心性能细节
运维·服务器