Makefile中,目标 之后是冒号或双冒号,冒号和双冒号后面跟的都是依赖文件。
执行make 后面跟的是目标名(例如 clean),是指定目标执行clean。
例1:
1 funny: # 目标后面跟的是依赖列表,判断如果依赖列表存在就判断时间戳是否要更新编译,
不存在就执行下面的shell命令。
2 echo “just for fun”
例2:
1 image:a.o b.o x.o # 将所有目标文件链接成image
2 gcc a.o b.o x.o -o image
3
4 a.o:a.c
5 gcc a.c -o a.o -c
6 b.o:b.c
7 gcc b.c -o b.o -c
8 x.o:x.c
9 gcc x.c -o x.o -c
例3:
1 A = apple
2 B = I love China
3 C = $(A) tree #使用变量
4
5 all:
6 @echo $(A) # echo 前面的 @ 代表命令本身不打印出来
7 @echo $(B)
8 @echo $(C)
vincent@ubuntu:~$ make
apple
I love China
apple tree
例4:
1 OBJ = a.o b.o x.o #代替所有目标文件
2
3 image:$(OBJ)
4 gcc $(OBJ) -o image
5
6 a.o:a.c
7 gcc a.c -o a.o -c
8 b.o:b.c
9 gcc b.c -o b.o -c
10 x.o:x.c
11 gcc x.c -o x.o -c
例5:
1 OBJ = a.o b.o x.o
2 CC = arm-Linux-gnu-gcc #C编译器默认 “ CC ” 是 “ cc ”,这里可以赋值为 arm-Linux-gnu-gcc
3
4 image:$(OBJ)
5 $(CC) $(OBJ) -o image
6
7 a.o:a.c
8 $(CC) a.c -o a.o -c
9 b.o:b.c
10 $(CC) b.c -o b.o -c
11 x.o:x.c
12 $(CC) x.c -o x.o -c
例6:
1 OBJ = a.o b.o x.o y.o
2
3 image:$(OBJ)
4 $(CC) $^ -o $@ # “ @ ” 表示所在规则,目标的完整名称
5 # “ ^ ” 表示所在规则的依赖列表,同一文件不可重复
6 a.o:a.c
7 $(CC) $^ -o $@ -c
8 b.o:b.c
9 $(CC) $^ -o $@ -c
10 x.o:x.c
11 $(CC) $^ -o $@ -c
12 y.o:y.c
13 $(CC) $^ -o $@ -c
例6:
1 A = I love $(B) // = 是递归方式,全局搜索
2 B = China
1 B = China
2 A := I love $(B) //直接定义方式,只会对前面的语句进行搜寻(不包含自己所在的那一行)
1 A = apple
2 A ?= I love China //条件方式,没有定义 A 才赋值
1 define commands
2 echo “thank you!” //多命令行定义方法
3 echo “you are welcome.”
4 endef
1 A = apple
2 A += tree //追加方式 值就是apple tree。
例7:修改变量值 方式
1 A = srt.c string.c tcl.c // " % " 表示所在规则的成员名
2 B = $(A:%.c=%.o) //将变量A 所有 .c 成员,替换成 .o 结果 srt.o string.o tcl.o
1 A = srt.c string.c tcl.c
2 B = $(patsubst %.c, %.o, $(A)) //同上,patsubst是另外一种替换方式
例8:修改和保护变量值
1 make A="an elephant" //执行make命令时,带变量定义,就会修改makefile中变量A的值。
2 override A = an apple //makefile定义变量时,加上override修饰,就会被保护。不能通过上面方式修改变量值。
例9:
1 export CFLAGS = -Wall -g //导出变量 CFLAGS。 -w 是生成编译警告信息 -g 是生成调试信息。
例10:
1 $(MAKE) -C dir/ //调用位于dir/中的子Makefile
上面问题还需要详细了解。
例11:
VPATH :当Makefile中的目标文件或者依赖文件不在当前路径时,make会在此变量所指定的目录中搜寻,
如果VPATH包含多个备用路径,他们使用空格或者冒号隔开。
1 VPATH = src1/:src2/ //指定文件搜寻除当前路径之外的备用路径。多个路径时,用冒号隔开。
例11.1:
vpath是一个指示符,VPATH是一个变量。
1 vpath %.c = src1/:src2/ //指定本Makefile中.c文件的可能路径
2 vpath %.h = include/ //指定本Makefile中.h文件的可能路径
例12:
1 $(MAKE) -C subdir/ //Makefile中调用子Makefile时,指定子Makefile的路径。
2 $(MAKE) 变量实际代表了当前系统中make软件的全路径。如:/usr/bin/make。
例13:
1 MAKEFLAGS 此变量代表了在执行make时的命令行参数。
2 执行 make -s,Makefile中 MAKEFLAGS的值就是 s。
例14:
1 .PHONY: clean //声明不要对clean使用隐式规则。不能运用隐式规则的目标被称为伪目标。
2 隐式规则,指Makefile执行的时候,例如,如果发现clean,就会去查找clean.c。
例15:
静态规则:用自动变量实现,一次编译好所以的.c文件。
1 image:$(OBJ)
2 $(CC) $(OBJ) -o image //"%"代表其所在规则的静态库文件的一个成员名
3 $(OBJ):%.o:%.c //"@"代表其所在规则的目标的完整名称
4 $(CC) $^ -o $@ -Wall -c //"^"代表其所在规则的依赖列表
例16:
多目标规则:函数$(subst)的用法
1 $(CC) $(subst .o,.c,$@) -o $@ -c //函数$(subst)是将$@中所有.o文件替换成.c文件。
//函数$(subst)等到的就是所有.c文件。
多目标规则应用在以下两种场合:
1 a.o b.o x.o y.o:head.h //只需描述依赖关系,而不需要指定相关 Shell 命令。
一个只描述依赖关系的规则,用来管理工程项目当中一些各自和公共文件会非常方便,
比如工程当中有许多.o 文件,用变量 OBJS 来表达,他们都依赖于 config.h 文件,
而他们又可以各自依赖于其他的头文件:
OBJS = a.o b.o c.o
a.o:a.h
b.o:b.h B.h
c.o:c.h
$(OBJS):config.h
这样做的好处是:我们可以在源文件中增加或者删除了包含的头文件以后不用修改已经存在的
Makefile 的规则,只需要增加或者删除某一个.o 文件依赖的头文件。这种方式很简单也很方便。
对于一个大的工程来说,这样做的好处是显而易见的。在一个大的工程中,对于一个单独目录下的.o
文件的依赖规则建议使用此方式。
2 有多个具有类似构建命令的目标,就是上面的例子那样,将之展开得到:
a.o:a.c b.c x.c y.c
$(CC) a.c -o a.o -c
b.o:a.c b.c x.c y.c
$(CC) b.c -o b.o -c
x.o:a.c b.c x.c y.c
$(CC) x.c -o x.o -c
y.o:a.c b.c x.c y.c
$(CC) y.c -o y.o -c
例17:
双冒号规则:
1 image::b.c //如果“b.c”被修改那么“image”将根据“b.c”被重建
$(CC) a.c -o $@ -L. -lx
例18:
条件判断:
1 ifdef TOOLCHAIN //ifdef 语句用来判断变量 TOOLCHAIN 是否有定义
CC = $(TOOLCHAIN)
else
CC = gcc
endif
2 ifeq ($(CC), gcc) // 用来判断变量 CC 的值是否等于 gcc 注意:ifeq 跟后面一个空格
$(CC) $(OBJ) -o image -lgcc
else
$(CC) $(OBJ) -o image
endif
例19:
函数:
注意到在 Makefile 中书写一个函数的格式:$(function arg1,arg2,arg3, … …) 其中 function
是函数的名字,后面跟一个空格,然后是参数列表,如果有多个参数则用逗号隔开(注意逗号后面最好
不要有空格),整个函数用$( )包裹起来(跟变量一样)。
1 SRC = $(wildcard *.c) //wildcard 函数的作用就是找到参数匹配的文件名。找出所以 .c 文件。
OBJ = $(SRC: %.c=%.o) //上面得出所有.c文件,这里用变量替换操作,得出所有.o文件。
下面列出 Makefile 中常用到的内嵌函数的详细信息,以供查阅:
1 $(subst FROM,TO,TEXT) //将字符串 TEXT 中的字符 FROM 替换为 TO。
A = $(subst AB,EF,ABCD) 结果:EFCD
遇到过的方式:
目标:
命令(这个命令不一定非要是系统命令,也可以是用户自己写的,经过编译后得到的bin命令。)
出处:林世霖老师的课堂笔记