origin
查询参数VARNAME
的出处。VARNAME
为变量名,所以一般不通过$
进行引用
$(origin VARNAME)
-
若从未定义过该变量,
origin
返回undefined
all: @echo $(origin V)
make
时输出:undefined -
若该变量为环境变量,则返回
enviroment
all: @echo $(origin USER) # 或者 # VAR = USER # all: # @echo $(origin $(VAR))
make
时输出:enviroment -
若该变量是个默认定义,则返回
default
all: @echo $(origin CC)
make
时输出:default -
如果该变量被定义在Makefile文件中,则返回
file
VAR := 1 all: @echo $(origin VAR)
make
时输出:file -
如果变量来自命令行,则返回
command line
all: @echo $(origin COMMANDVAR)
make COMMANDVAR="hello"
时输出:command line -
如果变量被
override
重新定义过,则返回override
override SHELL=/bin/sh all: @echo $(origin SHELL)
make
时输出:override -
如果变量是自动化变量(如
$@
,$<
),则返回automatic
all: @echo $(origin $@)
make
时输出:automatic
strip
去掉字符串str
开头和结尾的空字符。若字符串中间有连续的空字符,将其合并为一个。返回去掉空字符后的字符串
str := abc
$(strip $(str))
shell
在Makefile里可以调用shell脚本,但调用存在 一些语法规则
-
在Makefile中只能在
target
中调用shell脚本VAR = hello all: @echo ${VAR}
在echo命令前加@表示不回显echo命令本身
make
输出结果:hello -
若想在makefile里执行shell命令,必须使用如下形式:
$(shell <command>)
例如:
x = $(shell echo "hello") y = $(shell pwd) all: @echo $x;\ echo $y
make
执行后输出结果为hello /home/qxy/Desktop/test
-
在
target
里执行shell命令,一行创建一个进程执行,可以在行末加;\
保证代码是一行而不是多行,使它们在同一个进程中执行,例如all: @pwd @cd .. @pwd
make
执行后输出为/home/qxy/Desktop/test /home/qxy/Desktop/test
而如果想要
cd
对后续的命令切实的起到更换目录的作用,需要用以下写法:all: @pwd;\ cd ..;\ pwd
make
执行后输出为/home/qxy/Desktop/test /home/qxy/Desktop
可以发现后者的
cd
命令确实的起了作用。因为前者的cd
与它后面的pwd
不属于同一个进程,它们都继承了该makefile执行时的环境变量,cd
无法影响与他不属于同一个进程的命令的环境变量 -
在Makefile中所有
$
打头的单词都会被解释成makefile的变量,如果需要使用shell的变量,要加两个$$VAR = 1 all: @VAR=2;\ echo $(VAR);\ echo $$VAR
make
执行后输出为1 2
这里有两个注意点:一是在makefile语法中赋值的等号两边可以有空格,但在shell语法中不可以有空格;二是在target中调用shell命令一行为一个进程,前文也有提到,因此想让
echo $$VAR
访问到刚刚定义的VAR=2
就必须在结尾书写;\
,使他们在同一个进程执行
wildcard
搜索指定目录下所有指定结尾的文件,生成一个以空格间隔的文件名列表并返回。当前目录文件只有文件名,子目录下的文件名包含路径信息,比如./foo/3.c
src = $(wildcard arg1, arg2, ...)
# example:
# 假设当前目录下有 1.c 和 2.c 两个文件和 foo/ 一个文件夹
# foo/ 文件夹中有 3.c, 4.c 两个文件
src = $(wildcard *.c ./foo/*.c)
all:
@echo $(src)
make
执行后输出为:1.c 2.c ./foo/3.o ./foo/4.o
notdir
去除所有的目录信息,返回文件名列表
src = $(wildcard *.c ./foo/*.c)
file = $(notdir $(src))
all:
@echo $(file)
make
执行后输出为:1.c 2.c 3.c 4.c
patsubst
将src
中所有后缀为.c
的文件后缀替换为.o
obj = $(patsubst %.c %.o $(src))
all:
@echo $(obj)
make
执行后输出为:1.o 2.o 3.o 4.o
foreach
用于循环
$(foreach <var>, <list>, <text>)
这个函数把<list>
中的单词逐一取出放到<var>
指定的变量中,然后执行<text>
的表达式。每次<text>
返回一个字符串,foreach
结束后<text>
返回的所有字符串组成的整个字符串(以空格分隔)作为foreach
表达式的返回值
例如:
names := a b c d
files := $(foreach n, $(names), $(n).o)
all:
@echo $(files)
make
执行后输出为:a.o b.o c.o d.o
call
$(call <expression>,<parm1>,<parm2>,<parm3>...)
当call
被执行时,<expression>
参数中的变量如$(1), $(2), $(3)...
会被按编号顺序替换成<parm1>, <parm2>, <parm3>...
,<expression>
的返回值即为call
函数的返回值。例如;
reverse = $(1) $(2)
foo = $(call reverse, a, b)
此时foo
的值为a b
若写成
reverse = $(2) $(1)
foo = $(call reverse, a, b)
变量按顺序替换后$(2)
被替换成b
,$(1)
被替换成a
,因此此时foo
的值为b a