Makefile学习笔记 1个规则
1 2 hello: hello.c gcc -o hello hello.c
基本原则:
若想生成目标 ,检查规则 中的依赖条件 是否存在,如不存在,则寻找是否有规则 用来生成该依赖条件
检查规则中的目标 是否需要更新,必须先检查它的所有依赖 ,依赖 中有任意一个被更新,则目标 才能更新
分析各个目标和依赖之间的关系
根据依赖关系自底向上执行命令
根据依赖条件 和目标 的修改时间来判断目标 是否需要更新
如果目标不依赖任何条件,则执行对应命令,以示更新
make工具检查makefile文件,默认将其中第1条规则的目标作为终极目标 除非用 ALL 命令指定终极目标 make生成终极目标 就自动退出了
1 2 3 4 5 6 7 8 9 10 11 ALL: main hello.o: hello.c gcc -c hello.c -o hello.o add.o: add.c gcc -c add.c -o add.o sub.o: sub.c gcc -c sub.c -o sub.o div.o: div.c gcc -c div.c -o div.o main: hello.o add.o sub.o div.o gcc hello.o add.o sub.o div.o -o main
2个函数 $(wildcard *.c)
匹配当前工作目录下所有.c文件。将文件名组成列表,赋值给变量 src
$(patsubst %.c, %.o,$(src)) 1 obj = $(patsubst %.c, %.o,$(src) )
将变量参数3 中包含参数1 的部分替换为参数2 ,并赋值给变量 obj
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 src = $(wildcard *.c) obj = $(patsubst %.c, %.o, $(src) ) ALL: main main: $(obj) gcc hello.o add.o sub.o div.o -o main hello.o: hello.c gcc -c hello.c -o hello.o add.o: add.c gcc -c add.c -o add.o sub.o: sub.c gcc -c sub.c -o sub.o div.o: div.c gcc -c div.c -o div.o
clean 1 2 clean: (没有依赖) -rm -rf $(obj) main
3个自动变量
自动变量
作用
$@
在规则的命令中,表示规则中的目标
$<
在规则的命令中,表示规则中的第一个依赖条件
$^
在规则的命令中,表示规则中的所有依赖条件,组成一个列表,用空格隔开,删除重复项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 src = $(wildcard *.c) obj = $(patsubst %.c, %.o, $(src) ) ALL: main main: $(obj) gcc $^ -o $@ hello.o: hello.c gcc -c $< -o $@ add.o: add.c gcc -c $< -o $@ sub.o: sub.c gcc -c $< -o $@ div.o: div.c gcc -c $< -o $@ clean: -rm -rf $(obj) main
模式规则 将上面一组相似的规则定义了一个模式
1 2 %.o: %.c gcc -c $< -o $@
1 2 3 4 5 6 7 8 9 10 11 12 13 src = $(wildcard *.c) obj = $(patsubst %.c, %.o, $(src) ) ALL: main main: $(obj) gcc $^ -o $@ %.o: %.c gcc -c $< -o $@ clean: -rm -rf $(obj) main
1 2 3 4 5 6 7 > make gcc -c hello.c -o hello.o gcc -c add.c -o add.o gcc -c div.c -o div.o gcc -c sub.c -o sub.o gcc hello.o add.o div.o sub.o -o main >
这样可以随意的添加或删除一些源文件而不需要去动makefile
静态模式规则 给一个变量指定了一个模式规则
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 src = $(wildcard *.c) obj = $(patsubst %.c, %.o, $(src) ) ALL: main main: $(obj) gcc $^ -o $@ $(obj) : %.o: %.c gcc -c $< -o $@ %.o: %.c gcc -c $< -o $@ clean: -rm -rf $(obj) main
伪目标 不管目标文件是否是最新的,都再去执行一次目标 的规则
1 2 3 .PHONY : cleanclean: -rm -rf $(obj) main
其它 还可以用变量去定义一些在命令中会用到的参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 src = $(wildcard *.c) obj = $(patsubst %.c, %.o, $(src) ) FLAGS = -Wall -g ALL: main main: $(obj) gcc $^ -o $@ $(FLAGS) $(obj) : %.o: %.c gcc -c $< -o $@ $(FLAGS) clean: -rm -rf $(obj) main
小测试 小测试的项目结构
1 2 3 4 5 6 7 8 9 10 11 12 maketest ├── include │ └── head.h ├── Makefile ├── obj └── src ├── add.c ├── div.c ├── main.c └── sub.c 3 directories, 6 files
Makefile文件内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 src = $(wildcard ./src/*.c) obj = $(patsubst ./src/%.c, ./obj/%.o, $(src) ) INCLUDE_PATH = ./include ALL: main main: $(obj) # 链接阶段就不需要include了 gcc $^ -o $@ $(obj) : ./obj/%.o: ./src/%.c gcc -c $< -I $(INCLUDE_PATH) -o $@ .PHONY : cleanclean: -rm -rf $(obj) main
main.c文件内容
1 2 3 4 5 6 7 8 9 #include "head.h" int main () { int a = 10 , b = 2 ; printf ("%d+%d=%d\n" , a, b, add(a, b)); printf ("%d-%d=%d\n" , a, b, sub(a, b)); printf ("%d/%d=%d\n" , a, b, div(a, b)); return 0 ; }
head.h文件内容
1 2 3 4 5 6 7 8 9 10 #ifndef _HEAD_H_ #define _HEAD_H_ #include <stdio.h> int add (int , int ) ;int sub (int , int ) ;int div (int , int ) ;#endif
执行
1 2 3 4 5 6 > make gcc -c src/main.c -I ./include -o obj/main.o gcc -c src/add.c -I ./include -o obj/add.o gcc -c src/div.c -I ./include -o obj/div.o gcc -c src/sub.c -I ./include -o obj/sub.o gcc obj/main.o obj/add.o obj/div.o obj/sub.o -o main
最终执行项目结构图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 maketest ├── include │ └── head.h ├── main ├── Makefile ├── obj │ ├── add.o │ ├── div.o │ ├── main.o │ └── sub.o └── src ├── add.c ├── div.c ├── main.c └── sub.c 3 directories, 11 files