< 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 进度条进阶版------可实际使用

相关推荐
蝎子莱莱爱打怪1 小时前
小孩儿才做选择!Hermes 和OpenClaw 我都要!
人工智能·后端·github
直奔標竿2 小时前
SpringAI + RAG + MCP + Agent 零基础全栈实战(完结篇)| 27课完整汇总,Java开发者AI转型必看
java·开发语言·人工智能·spring boot·后端·spring
JZC_xiaozhong2 小时前
跨系统审批自动化怎么做?从采购到销售合同的完整方案
大数据·运维·自动化·流程自动化·数据集成与应用集成·业务流程管理·异构数据集成
枫叶林FYL2 小时前
项目八 云资源成本优化与治理平台
后端·python·自然语言处理·flask
嵌入式×边缘AI:打怪升级日志2 小时前
嵌入式Linux开发:开源组件、第三方库与许可证详解
linux
计算机安禾2 小时前
【Linux从入门到精通】第34篇:搭建FTP与Samba——跨平台文件共享解决方案
linux·运维·服务器
乌恩大侠2 小时前
【AI-RAN】在空ubuntu服务器安装环境和生成TV,高达430G文件
服务器·人工智能·ubuntu·fpga开发·o-ru
日取其半万世不竭2 小时前
用 Netdata 实时监控服务器,比 Prometheus + Grafana 轻量得多
linux·服务器·网络·系统架构·负载均衡·zabbix·grafana
SamDeepThinking2 小时前
第1篇-开篇词:几亿用户规模下,我们是怎么做C端高并发商品系统的
java·后端·架构