1. .PHONY 声明的目标总是被调用
.PHONY:zzg echo "hello zzg" @echo "good morning" # @符号表示不显示被执行的命令,但是会执行。
2. $(info start working) info 是make内置的函数,后面跟的是参数,打印消息,类似的函数还有warning,error,不同的是error在打印完消息后会终止执行并退出。
3. 调用make
$make -f Makefile target_in_makefile
4. 赋值符号
:= 在makefile被解析时就立即展开并赋值 (立即展开)
= 只有当所定义的变量在使用时才展开 (延迟展开)
?= 条件赋值,只有该变量还没有值时才赋值 (延迟展开)
+= 附加赋值 (出现在target后面会延迟,而普通情况下会立即展开)
5. 条件控制语句
if-condition text if the condition is true endif if-condition text if the condition is true else text if the condition is true endif 其中condition只能进行两种判断,一种是判断表达式是否相等,另一种是判断表达式是否被定义: ifdef var ifndef var ifeq (a, b) ifneq (a, b)
6. 宏(函数)定义
按调用方式可以分为三类
a). make内置函数调用 $(func_name, param...) b) 用户定义函数 $(call func_name, param...) c) 用户定义的无参函数,也成为宏 $(func_name) 函数的定义方法: define func_name command # 命令前没有tab键,宏被展开时make解释器会自动添加 endef 函数参数的获取: $(0) 函数名 $(1) 第一个参数
7.常用函数
a)字符串操作函数 $(filter pattern..., text) $(filter-out pattern..., text) $(findstring string, text) $(subst from, to, text) $(patsubst from, to, text) $(strip text) $(words text) $(word n, text) $(firstword, text) $(wordlist start, end, text) $(sort list) b) 文件名操作 $(wildcard *.c) $(dir f1.c src/f2.c) $(notdir f1.c src/f2.c) $(suffix f1.c f1.h) $(basename f1.c src/f1.h) $(addsuffix .c, f1 src/f2) $(addprefix src/, f1.c f2.c) $(join f1 f2, .c .h) c) 过程控制函数:前面的ifeq、ifneq是脚本解析的时候起作用,有点像c语言的宏,即预处理。过程控制则需要函数来完成 $(if condition, then-part, else-part) #condition为true的条件是其不为空 $(error text) $(foreach variable, list, body) eg: $(foreach name, zhao wang zhao qian, $(shell echo hello $(name)\,))
8. 内置符号
$@ target名称 $* 和$@类似,只是不包含target的后缀 $^ 所有先决条件名称,以space分隔,自动去重 $? 有更新的先决条件列表, 例如有4个先决条件,其中有3个甘冈被修改过,则$?就代表刚刚被修改过的先决条件,以空格分隔 $+ 所有先决条件,和$^类似,只是$+包含了重复的先决条件,而$^会去重 $< 第一个先决条件
9. 目标特定的变量赋值
tar2:CFLAGS= #只对此编译起作用
tar:
gcc $(CFLAGS) main.c
======
tar2: override CFLAGS= # override 完胜
tar:
gcc $(CFLAGS) main.c
========
make tar2 -e CFLAGS="-c -g"
10. 常用选项
-e --environment-overrides: 强制使用make命令参数中的变量赋值
-t --touch 仅更新文件的时间戳,却不执行target对应的命令
-c --directory 指定要执行那个的makefile的路径
-f --file 指定make用的文件
-n --just-print 仅打印要执行的命令,不真正执行,方便分析
-l 指定 编译时所需要的lib文件例如lName 寻找 libName.so ,如果没有再找 libName.a
11. 隐含规则:
a) 后缀规则
.c.o: # 后缀成对出现,将.c转换为.o
gcc -c -o $@ $<;
b) 模式规则
%.c:%.o
gcc -c -o $@ $<;
12. 内置符号:
$^ 所有依赖集合,去重后的
$+ 所有依赖集合,没有去重
$? 所有依赖集合中比目标新的文件的集合
$< 依赖集合中的第一个文件
$* 不包含扩展名的目标文件名称。
$@ 目标的完整名称
$% 如果目标是归档成员,则该变量表示目标的归档成员名称。例如,如果目标名称
为 mytarget.so(image.o),则 $@ 为 mytarget.so,而 $% 为 image.o。