源文件增多后,手工重复输入编译与链接命令既繁琐又易遗漏已修改的文件。Makefile 描述目标与依赖关系,由 make 按规则执行命令,并支持仅重建发生变更的部分(增量编译)。
Makefile 的作用
Makefile 供 make 读取,每条规则说明如何从依赖文件生成目标文件。Linux 环境常预装 make;其他平台可安装 GNU Make 等实现。
规则结构
target: dependencies
command- target:要生成的文件(如
main.o、可执行文件main)。 - dependencies:生成 target 所需的输入文件。
- command:执行的 shell 命令;必须以 Tab 字符缩进,不能用空格代替。
可用变量简化重复,以 $() 引用:
CC = gcc
$(CC) -o main main.o多文件工程示例
假设存在 main.c、multiply.c、factorial.c 及头文件 function.h:
/* function.h */
#ifndef FUNCTION_H
#define FUNCTION_H
int multiply(int, int);
int factorial(int);
void print(void);
#endif/* multiply.c */
#include "function.h"
int multiply(int a, int b) { return a * b; }/* factorial.c */
#include "function.h"
int factorial(int n) {
if (n == 1)
return 1;
return n * factorial(n - 1);
}/* main.c */
#include <stdio.h>
#include "function.h"
int main(void) {
printf("%d\n", multiply(2, 3));
printf("%d\n", factorial(5));
print();
return 0;
}手工编译步骤示例:
gcc -c main.c
gcc -c multiply.c
gcc -c factorial.c
gcc -o main main.o multiply.o factorial.o
./main对应的 Makefile 示例:
# 编译器
CC = gcc
# 编译选项:开全警告、带调试信息
CFLAGS = -Wall -g
# 目标可执行文件
TARGET = main
# 源文件
SRCS = main.c multiply.c factorial.c
# 把 .c 换成 .o
OBJS = $(SRCS:.c=.o)
# 默认目标:编译并运行
all: $(TARGET) run
# 链接:把 .o 合成可执行文件
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS)
# 通用规则:任何 .o 由同名 .c 编译而来
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
# 运行
run: $(TARGET)
./$(TARGET)
# 清理生成的文件
clean:
del $(TARGET).exe $(OBJS)在项目目录执行:
make若仅修改 multiply.c,再次执行 make 时通常只重新编译 multiply.o 并重新链接,其余目标文件可复用。清理产物:
make clean使用要点
- Tab 缩进:命令行必须以 Tab 开头。
- 自动变量:
$@表示当前目标,$<表示首个依赖,$^表示全部依赖。 - 默认目标:文件中第一条规则在无参数执行
make时被构建。 - 目录组织:头文件、源文件与生成物分目录存放,便于维护较大工程。
本节介绍了 Makefile 的基本结构与增量编译思路。下一节说明 printf / scanf 格式说明符的用法与排版修饰。