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






































