Makefile 自动化编译过程,让构建项目变得简单。
每次修改代码都要输入长长的编译命令:
# ❌ 每次都输入
gcc -Wall -g src/main.c src/snake.c src/food.c src/ui.c src/input.c src/score.c src/utils.c -o snake_game -lncurses
Makefile 的好处:
make 即可make clean# 变量定义
CC = gcc
CFLAGS = -Wall -g -Isrc
LDFLAGS = -lncurses
# 目标文件列表
OBJS = obj/main.o obj/snake.o obj/food.o obj/ui.o obj/input.o obj/score.o obj/utils.o
# 最终目标
snake_game: $(OBJS)
$(CC) $(OBJS) -o snake_game $(LDFLAGS)
# 编译规则
obj/%.o: src/%.c
$(CC) $(CFLAGS) -c $< -o $@
# 清理
clean:
rm -rf obj/*.o snake_game
# 声明伪目标
.PHONY: clean
# 定义变量
CC = gcc
CFLAGS = -Wall -g
# 使用变量
program: main.c
$(CC) $(CFLAGS) main.c -o program
# 格式
target: dependencies
command
# 示例
snake_game: main.o snake.o
gcc main.o snake.o -o snake_game
| 变量 | 含义 |
|---|---|
$@ |
目标文件名 |
$< |
第一个依赖文件 |
$^ |
所有依赖文件 |
obj/main.o: src/main.c
$(CC) -c $< -o $@
# 编译器和标志
CC = gcc
CFLAGS = -Wall -Wextra -std=c99 -Isrc -O2
LDFLAGS = -lncurses
# 目录
SRC_DIR = src
OBJ_DIR = obj
# 源文件和目标文件
SRCS = $(wildcard $(SRC_DIR)/*.c)
OBJS = $(SRCS:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
# 目标可执行文件
TARGET = snake_game
# 默认目标
all: $(TARGET)
# 链接
$(TARGET): $(OBJS)
@echo "链接 $(TARGET)..."
$(CC) $(OBJS) -o $@ $(LDFLAGS)
# 编译
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
@echo "编译 $<..."
$(CC) $(CFLAGS) -c $< -o $@
# 创建 obj 目录
$(OBJ_DIR):
mkdir -p $(OBJ_DIR)
# 清理
clean:
@echo "清理..."
rm -rf $(OBJ_DIR) $(TARGET)
# 重新编译
rebuild: clean all
# 运行
run: $(TARGET)
./$(TARGET)
# 调试版本
debug: CFLAGS += -g -DDEBUG
debug: clean all
# 帮助
help:
@echo "可用目标:"
@echo " all - 编译项目(默认)"
@echo " clean - 清理编译产物"
@echo " rebuild - 重新编译"
@echo " run - 编译并运行"
@echo " debug - 编译调试版本"
@echo " help - 显示帮助"
.PHONY: all clean rebuild run debug help
# 编译项目
make
# 清理
make clean
# 重新编译
make rebuild
# 编译并运行
make run
# 编译调试版本
make debug
# 查看帮助
make help
执行 make
↓
检查目标 snake_game
↓
检查依赖 obj/*.o
↓
如果 .o 文件不存在或 .c 文件更新
↓
执行编译命令
↓
所有 .o 文件准备好
↓
执行链接命令
↓
生成 snake_game
Make 的聪明之处在于只编译修改过的文件:
# 第一次编译
$ make
编译 src/main.c...
编译 src/snake.c...
编译 src/food.c...
链接 snake_game...
# 只修改了 snake.c
$ make
编译 src/snake.c... # 只编译这个!
链接 snake_game...
# 没有修改
$ make
make: 'snake_game' is up to date.
# 显示执行的命令(不实际执行)
make -n
# 显示详细过程
make -d
# 只显示错误
make -s
# ❌ 错误:使用空格
target:
command # 空格!
# ✅ 正确:使用 Tab
target:
command # Tab!
# ❌ 可能编译顺序错误
snake_game: main.o
gcc main.o -o snake_game
# ✅ 正确
snake_game: main.o snake.o
gcc main.o snake.o -o snake_game
为你的贪吃蛇项目创建 Makefile
all - 默认编译clean - 清理run - 运行debug - 调试版本下一课:游戏循环