通过将一个 Makefile 从最原始的状态一步步简化,来展现多种常见的 Makefile 语法和技巧。
最初始的形态:
1main: main.o submodule.o utils.o
2 gcc main.o submodule.o util.o -o main
3
4main.o: main.c submodule.h utils.h
5 gcc -g -c main.c -o main.o
6
7submodule.o: submodule.c submodule.h utils.h
8 gcc -g -c submodule.c -o submodule.o
9
10utils.o: utils.c utils.h
11 gcc -g -c utils.c -o utils.o
12
13.PHONY: clean
14clean:
15 rm main main.o submodule.o utils.o
引入变量:
1OBJS=main.o submodule.o utils.o
2CC=gcc
3CFLAGS=-g
4
5main: $(OBJS)
6 $(CC) $(OBJS) -o main
7
8main.o: main.c submodule.h utils.h
9 $(CC) $(CFLAGS) -c main.c -o main.o
10
11submodule.o: submodule.c submodule.h utils.h
12 $(CC) $(CFLAGS) -c submodule.c -o submodule.o
13
14utils.o: utils.c utils.h
15 $(CC) $(CFLAGS) -c utils.c -o utils.o
16
17.PHONY: clean
18clean:
19 rm main $(OBJS)
引入 Static Pattern Rules
和 Automatic Variables
($<
和 $@
):
1OBJS=main.o submodule.o
2DEPS=submodule.h utils.h
3CC=gcc
4CFLAGS=-g
5
6main: $(OBJS) utils.o
7 $(CC) $(OBJS) -o $@
8
9$(OBJS): %.o: %.c $(DEPS)
10 $(CC) -c $(CFLAGS) $< -o $@
11
12utils.o: utils.c utils.h
13 $(CC) $(CFLAGS) -c utils.c -o utils.o
14
15.PHONY: clean
16clean:
17 rm main $(OBJS)
或者引入 Implicit Rules ,同时使用了单一规则多目标 和单一目标多规则 的语法:
1OBJS=main.o submodule.o utils.o
2CC=gcc
3CFLAGS=-g
4
5main: $(OBJS)
6 $(CC) $(OBJS) -o $@
7
8main.o submodule.o: submodule.h
9
10$(OBJS): utils.h
11
12.PHONY: clean
13clean:
14 rm main $(OBJS)
另外,一个常有的情况是:我们想把编译出来的二进制文件放到一个特殊的目录下,或者把源文件和头文件分目录存放。这里使用了 Substitution References ,以及 info 和 shell 函数:
1OBJS=main.o submodule.o utils.o
2CC=gcc
3CFLAGS=-g
4BIN_DIR=./bin
5_TARGETS = main
6TARGETS = $(_TARGETS:%=$(BIN_DIR)/%)
7
8$(info $(shell mkdir -p $(BIN_DIR)))
9
10$(TARGETS): $(OBJS)
11 $(CC) $(OBJS) -o $@
12
13main.o submodule.o: submodule.h
14
15$(OBJS): utils.h
16
17.PHONY: clean
18clean:
19 rm main $(OBJS)
最后介绍一个好用的参数:make -n
“dry-run”, just print what it’s gonna do but not actually do it. Really helpful for debugging.
参考资料:
- Makefile Tutorial By Example — The first tutorial I read.
- GNU Make Manual
, with:
- TOC, with one web page per section
- The whole GNU make manual in one Web page — Useful especially to search for unfamiliar keywords & built-in variables.
- 关于目录的处理:
- Create directories using make file — StackOverflow
- Types of Prerequisites — GNU Make Manual