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 脚本略有不同,直接写 变量名 = 值,引用用 $(变量名))

相关推荐
kloc1 小时前
聊天室项目入口网关子服务的实现
linux·c++
GeW1 小时前
深圳APEC峰会倒计时:数据库与Linux运维的"隐形考场"
linux
梦到啥说啥2 小时前
Linux网络编程:UDP网络协议
linux·网络协议·udp
无足鸟ICT3 小时前
【RHCA+】ipcrm命令(删除IPC资源)
linux
星恒随风4 小时前
MySQL 从零入门(四):表的增删改查与基础查询详解
linux·服务器·数据库·笔记·mysql
Z21-X5 小时前
云原生运维学习笔记:ECShop全链路容器化部署与Docker底层资源隔离深度剖析
运维·笔记·学习·云原生
陈希1237 小时前
Linux 网络诊断工具实战:ping、curl、tcpdump、mtr、dig 用法详解
linux·网络·tcpdump
进击的荆棘7 小时前
Linux系统——线程同步与互斥之线程池和安全
linux·运维·服务器·安全·单例模式·线程
刘大望7 小时前
不用买开发板:用 QEMU 走通嵌入式 Linux 全流程(三)存储与网络实地验证
linux·qemu·嵌入式linux·alpine
蜗牛一步步往上爬8 小时前
第六章 BMC常用的调试工具
服务器