文章

项目自动化构建工具-make/Makefile

项目自动化构建工具-make/Makefile

概述

  • make:一个常见的自动化构建工具,用于根据依赖关系自动编译、链接及执行其他任务。
  • Makefilemake 所读取和执行的脚本文件,定义了目标、依赖及命令。

作用:通过声明式规则管理源文件、目标文件及其依赖关系,避免手动重复编译,提高效率。

make和makefile的关系

  1. make 是可执行程序,运行时会在当前目录寻找名为 MakefilemakefileGNUmakefile 的文件。
  2. Makefile 中定义了:

    • 目标(target)
    • 依赖(dependencies)
    • 构建命令(recipes)

执行 make 时:

  • 若不指定目标,默认执行第一个目标。
  • 若指定目标,如 make clean,则执行对应规则。

隐式规则

如果当前目录下没有makefile,例如以下的文件结构:

1
2
3
4
.
└── main.c

0 directories, 1 file

这时候如果输入命令

1
make main

即使没有makefile文件,make也会按照默认规则去尝试自动构建文件

尝试隐式规则:GNU make 有一套内建规则,例如:

如果目标是 main,并且有一个 main.c 文件,那就自动用 cc -o main main.c 编译。

make自动认为你想用下面的规则构建目标:

1
2
main: main.c
    $(CC) $(CFLAGS) -o main main.c

Makefile基本结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 变量定义
CC      = gcc
CFLAGS  = -Wall -O2

# 默认目标
all: app

# 目标与依赖
app: main.o utils.o
	$(CC) $(CFLAGS) -o $@ $^

# 单个文件编译
%.o: %.c
	$(CC) $(CFLAGS) -c $<

# 清理
.PHONY: clean
clean:
	rm -f *.o app

缩进使用tab制表符缩进,如果用空格缩进会报错

GNU make 是按照 UNIX 传统设计的,它用 Tab 来明确表示“命令行”。如果你用了空格,它会认为这是其他语法,比如变量或目标定义,不符合格式就会报错。

  • 变量:用来简化命令,如 $(CC)$(CFLAGS)
  • 自动化变量:
    • $@:目标文件名
    • $<:第一个依赖文件
    • $^:所有依赖文件列表
  • 模式规则(Pattern rule):%.o: %.c 适用于所有 .c -> .o 的编译。
  • 伪目标(.PHONY):声明 clean 不对应实际文件,防止同名文件冲突。伪目标总是被执行。
  • make通过检测目标和依赖的Modify时间,来判断是否执行指令,.PHONY则不需要对比时间

.PHONY声明的目标,总是会执行,否则会对比文件的时间状态

例如

1
2
3
4
5
6
main: main.c
	gcc main.c -o main

.PHONY: clean
clean:
	rm -f main
1
2
3
4
5
6
7
8
9
10
11
TARGETS := ex1 ex2

all: $(TARGETS)

%: %.c
	gcc -o $@ $<

clean:
	rm -f $(TARGETS)

.PHONY: all clean

makefile原理

  1. 建立依赖关系,谁依赖:于谁,比如说main依赖main.c
  2. 新起一行,必须以tab开头,如gcc main.c -o main

常用命令

命令含义
make执行默认目标(通常是第一个)
make all执行 all 目标
make clean执行清理操作
make -n模拟运行,不实际执行命令
make -B强制重建所有目标
make -j[N]并行执行,多核加速(N 为线程数,省略时使用所有可用核心)

高级特性

  1. 条件判断

    1
    2
    3
    
     ifeq ($(DEBUG),1)
     CFLAGS += -g
     endif
    
  2. 函数:如 $(shell ...)$(wildcard ...)
  3. 包含其他 Makefile:

    1
    
     include common.mk
    
  4. 文件依赖自动生成:配合 gcc -MMD 生成 .d 文件。
本文由作者按照 CC BY 4.0 进行授权