makefille中特殊变量
$(MAKE) 当前make解释器的文件名
$(MAKECMDGOALS) 命令行中指定的目标名
$(MAKEFILE_LIST) make所需处理的makefile文件列表,当前makefile的文件名总是位于列表的最后,文件名之间以空格进行分隔
test :
$(MAKE) first
$(MAKE) second
$(MAKE) third
目标first second third可以为其他文件的伪目标,用来关联多个makefile文件
$(MAKE_VERSION) 当前make解释器的版本号
$(CURDIR) 当前make解释器的工作目录
$(.VARIABLES) 所有已定义的变量名列表(预定义变量和自定义变量)
变量值的替换
使用指定字符(串)替换变量值中的后缀字符(串)
语法格式:$(var:a=b)或${var:a=b}
变量的模式替换
使用%保留变量值中的指定字符,替代其他字符
语法格式:$(var:a%b=x%y)或${var:a%b=x%y}
规则中的模式替换
targets : target-pattern : prerequisite-pattern
command1\
command2\
…
意义:通过target-pattern从targets中匹配子目标,再通过prereq-pattern从子目标生成依赖,进而构成完成的规则
OBJS := fun.o main.o
$(OBJS) : %.o : %.c
gcc -o $@ -c $^
变量值的嵌套引用
x := y
y := z
a := $($(x))
运行make时,在命令行定义变量,命令行变量默认覆盖makefile中定义的变量
Override关键字用于指示makefile中定于的变量不能背覆盖
hm := hello makefile
override var := override-test
test :
@echo "hm => $(hm)"
@echo "var => $(var)"
@echo "fool => $(fool)"
make hm=123
make var=eee
make fool=aaaa
Define关键字用于makefile中定义多行变量,多行变量的定义从变量名开始到ended结束,常用于生成命令
例如
define foo
I am good!
endef
makefile中能够直接使用环境变量,定义了同名变量,环境变量将会被覆盖,通过make - e选项优先使用环境变量
变量在不同的makefile文件中传递
1.采用环境变量
2.使用export定义变量进行传递
3.定义make命令行变量进行传递(推荐)
JAVEA_HOEME := java home
export var := qqq
new := huang
//makefile
test :
@echo “JAVEA_HOEME => $(JAVEA_HOEME)”
@$(MAKE) -f makefile1 new:=$(new)
make test
make -e test
//makefile1
test :
@echo “JAVEA_HOEME => $(JAVEA_HOEME)”
@echo “var = $(var)”
@echo “new = $(new)”
目标变量为局部变量,作用域只在指定目标及连带规则中
模式变量是目标变量的扩展
var := 123
test : var:= test-var
test :
@echo "var => $(var)"
var => test-var
//
var := 123
test : var:= test-var
test :
@echo "var => $(var)"
another :
@echo "var => $(var)"
make another
var => 123
//
new := qqq
%e : override new := awe
test :
@echo "new = $(new)"
rule :
@echo "new = $(new)"
make test rule
new = qqq
new = awe
条件判断语句,依据条件的至来决定make的执行,只能控制make实际执行的语句,但是不能控制规则中命令的执行
If (arg1, arg2) //括号可以用单双引号代替
else
endif
条件判断关键字 ifeq infer ifdef ifndef
.PHONY : test
var1 := A
var2 := $(var1)
var3 :=
test :
ifeq ($(var1), $(var2))
@echo "var1 == var2"
else
@echo "var1 != var2"
endif
ifneq ($(var2), )
@echo "var2 is not empty"
else
@echo "var2 is empty"
endif
ifdef var2
@echo "var2 is not empty"
else
@echo "var2 is empty"
endif
ifndef var3
@echo "var3 is empty"
else
@echo "var2 is not empty"
endif
make
var1 == var2
var2 is not empty
var2 is not empty
var3 is empty
条件判断语句之前可以有空格,但是不能有tab字符(‘\t’)
在条件语句中不要使用自动变量($@, $^, $<)
一条完整的条件语句必须位于同一个makefile中
条件判断语句类似于c语言中的宏,预处理阶段有效,执行阶段无效
Make在加载makefile时,根据判断语句的表达式决定执行的内容
.PHONY : test
var1 :=
var2 := $(var1)
var3 =
var4 = $(var3)
test :
ifdef var1
@echo "var1 is defined"
else
@echo "var1 is not defined"
endif
ifdef var2
@echo "var2 is defined"
else
@echo "var2 is not defined"
endif
ifdef var3
@echo "var3 is defined"
else
@echo "var3 is not defined"
endif
ifdef var4
@echo "var4 is defined"
else
@echo "var4 is not defined"
endif
make
var1 is not defined
var2 is not defined
var3 is not defined
var4 is defined
递归复制,make解释器无法解析var4是否定义,默认为已定义
函数的定义及调用
1.make解释器提供了一系列函数供makefile调用
2.通过define关键字实现自定义函数
//定义
define fun1
@echo “My name is $(0).”
@echo “Param => $(1)”
endef
//调用
test :
$(call func1)
自定义函数是一个多行命令,无法直接调用,是一种过程调用,没有任何的返回值
自定义函数是make解释器在预定义时call函数在调用时将参数传递给多行变量
.PHONY : test
define func1
@echo "My name is $(0)."
@echo "Param => $(1)"
endef
var := $(call func1)
new := $(func1)
test :
@echo "var => $(var)"
@echo "new => $(new)"
$(call func1, hello)
var => @echo My name is func1
new => @echo My name is
My name is func1.
Param => hello
//
.PHONY : test
define func1
@echo "My name is $(0)."
endef
func2 := @echo "My name is $(0)."
test :
$(call func1)
$(call func2)
make
My name is func1.
My name is .
原因是call只能处理多行变量
变量与函数的综合示例
$(wildcard _pattern) 获取当前工作目录满足_pattern的文件或目录列表
$(addprefix _prefix, names) 给名字列表_names中的每一个名字增加前缀_prefix
SRCS := $(wildcard *.c) 自动获取当前目录下的源文件列表
OBJS := $(SRCS:.c = .o ) 替换变量值,将.c替换为.o文件
OBJS := $(addprefix path/, $(OBJS)) 对每一个目标文件列表加上路径前缀
%.c用于模式匹配当前目录下的文件列表
%.o : %.c
gcc -o $@ -c $^
CC := gcc
MKDIR := mkdir
RM := rm -fr
DIR_OBJS := objs
DIR_TARGET := target
DIRS := $(DIR_OBJS) $(DIR_TARGET)
TARGET := $(DIR_TARGET)/hello-makefile.out
# main.c const.c fun.c
SRCS := $(wildcard *.c)
# main.o const.o fun.o
OBJS := $(SRCS:.c=.o)
# objs/main.o objs/const.o objs/fun.o
OBJS := $(addprefix $(DIR_OBJS)/, $(OBJS))
.PHONY : rebuild clean all
$(TARGET) : $(DIRS) $(OBJS)
$(CC) -o $@ $(OBJS)
@echo "Target file ==> $@"
$(DIRS) :
$(MKDIR) $@
$(DIR_OBJS)/%.o : %.c
$(CC) -o $@ -c $^
rebuild : clean all
all : $(TARGET)
clean :
$(RM) $(DIRS)
make all
mkdir objs
mkdir target
gcc -o objs/const.o -c const.c
gcc -o objs/fun.o -c fun.c
gcc -o objs/main.o -c main.c
gcc -o target/hello-makefile.out objs/const.o objs/fun.o objs/main.o
Target file ==> target/hello-makefile.out