Linux 学习笔记(九):自动化构建神器 Make 与 Makefile

一、 为什么需要 Makefile?

上一节学了 GCC 编译,但如果一个项目有几十个源文件,且每次只改了一个文件,手动敲 gcc 命令重新编译所有文件是非常低效的。

Makefile 解决了两个大问题:

  1. 把复杂的编译命令封装起来,只需敲一个 make 就能编译整个项目。

  2. 实现"增量编译":它通过对比源文件和目标文件的修改时间,只编译修改过的文件。

二、 Makefile 的编写规则

核心公式是:目标 : 依赖,换行后写 命令。

⚠️ 最大的天坑 :命令前面必须按 Tab 键 ,绝对不能用空格,否则会报错 missing separator。

三、 实战演示

1. 最基础的 Makefile

cpp 复制代码
hello: hello.c
	gcc hello.c -o hello

执行 make,系统会自动调用对应的 gcc 命令。

2. 伪目标 .PHONY

当我们需要执行一些清理动作(如 make clean 删除编译产物)时,为了防止同名的文件干扰,需要声明伪目标。

cpp 复制代码
.PHONY: clean
clean:
	rm -f hello

声明为 .PHONY 后,make clean 总是会被无条件执行。

3. 使用变量优化

为了让 Makefile 更具扩展性,我们可以引入变量:

cpp 复制代码
BIN = hello
SRC = hello.c

$(BIN): $(SRC)
	gcc $(SRC) -o $(BIN)

.PHONY: clean
clean:
	rm -f $(BIN)

总结

make 是一个命令,Makefile 是一个规则文件。它通过比较文件的 Modify 时间(修改时间)来决定是否重新编译,极大地提升了开发效率。

自我实战操作

linux_study/gcc_test 目录里操作。

实战 1:写第一个 Makefile
bash 复制代码
cd ~/linux_study/gcc_test
vim Makefile   # 注意首字母大写,或者全小写 makefile 也行

在 Vim 里(按 i 进入插入模式),输入以下内容:

(注意:第二行的开头必须按一下键盘上的 Tab 键,千万别敲空格!)

cpp 复制代码
hello: hello.c
	gcc hello.c -o hello

按 Esc,输入 :wq 保存退出。

实战 2:使用 make 编译
bash 复制代码
# 1. 删掉之前手动编译的旧文件,确保干净
rm -f hello

# 2. 直接敲 make 命令
make
# 输出:gcc hello.c -o hello (它自动读取了 Makefile 并执行了里面的命令)

# 3. 验证一下程序
./hello
实战 3:体验 Make 的"智能"特性
bash 复制代码
# 1. 再次敲 make
make
# 输出:make: 'hello' is up to date. (它会说 hello 已经是最新的了,不重复编译,省时间!)

# 2. 我们用 touch 修改一下 hello.c 的修改时间
touch hello.c

# 3. 再次 make
make
# 输出:gcc hello.c -o hello (它发现 hello.c 比 hello 新,于是重新编译了!)
实战 4:加入伪目标 clean

重新编辑 Makefile:

bash 复制代码
vim Makefile

改成这样(注意 rm 前面依然是 Tab):

cpp 复制代码
hello: hello.c
	gcc hello.c -o hello

.PHONY: clean
clean:
	rm -f hello

保存退出后,测试一下:

bash 复制代码
make clean   # 会执行 rm -f hello,把程序删掉
ls           # 发现 hello 没了
实战 5:Makefile 进阶语法(变量)

前面的代码写死了 hello.c,如果有多个文件,每次改 Makefile 太麻烦。我们用变量优化(这部分面试提到会加分):

cpp 复制代码
# 定义变量
BIN = hello
SRC = hello.c

$(BIN): $(SRC)
	gcc $(SRC) -o $(BIN)

.PHONY: clean
clean:
	rm -f $(BIN)

(注意:Makefile 里的变量赋值和引用,跟 Shell 脚本略有不同,直接写 变量名 = 值,引用用 $(变量名))

相关推荐
鬼手点金1 小时前
单轮对话:最简单的 API 调用
java·服务器·前端·javascript·react.js·servlet·tomcat
lisanmengmeng1 小时前
监控Kubernetes集群的GPU资源(三)
linux·容器·kubernetes
北塔软件1 小时前
从根因分析到协同执行,如何让AI运维真正落地?
运维·人工智能
蜡笔羊驼1 小时前
ModuleNotFoundError: No module named ‘torchvision.transforms.functional_tensor‘
linux·人工智能·python
箓维1 小时前
线程池&&线程安全与可重入
linux·网络·安全
码农1001号1 小时前
emqx5.8开源版WSS连接
运维·服务器
海宇AI1 小时前
零信任架构实战:基于海宇车辆车五项信息核验构建自动化汽配供应链车型分类与发动机型号适配网关
运维·人工智能·架构·自动化
程序员-Benothing1 小时前
Linux端口与连接排查:ss、lsof、nc、telnet、curl
linux·运维·服务器
看浪的路人1 小时前
第8讲:记忆系统的监控与运维——Prometheus 指标、Grafana 面板与告警体系
运维·grafana·prometheus