用来控制某一部分是否被包含在makefile中。
可以比较两个变量,也可以比较变量和常量字符串。
ifeq ($(CC),gcc)
else
endif
conditional-directive-one
text-if-one-is-true
else conditional-directive-two
text-if-two-is-true
else
text-if-one-and-two-are-false
endif
ifneq (arg1, arg2)
ifneq ’arg1’ ’arg2’
ifneq "arg1" "arg2"
ifneq "arg1" ’arg2’
ifneq ’arg1’ "arg2"
ifdef variable-name
定义了,且值非空,那么就是真。
ifndef variable-name
$(function arguments)
或
${function arguments}
函数名和第一个参数之间可以有1个或多个空格或tab。参数之间使用逗号分开。后续参数的空白是保留的。
$(subst from,to,text)
替换
$(subst ee,EE,feet on the street)
$(patsubst pattern,replacement,text)
模式替换
$(patsubst %.c,%.o,x.c.c bar.c)
$(strip string)
移除开头和结尾的空白字符
$(findstring find,in)
找到就是find,每找到就是空白字符。
$(filter pattern...,text)
返回text中匹配任何一个pattern的words,用空白分开
sources := foo.c bar.c baz.s ugh.h
$(filter %.c %.s,$(sources))
$(filter-out pattern...,text)
和上面类似,但是返回不匹配的words
$(sort list)
排序,并移除重复的words
$(word n,text)
返回第n个word,n从1开始,如果n大于个数,则返回空。
$(wordlist s,e,text)
返回第s个到第e之间的所有words
$(words text)
返回words的个数
$(firstword names...)
返回第一个word
$(lastword names...)
返回最后一个word
$(dir names...)
返回路径中的目录部分
$(dir src/foo.c hacks)
结果为src/ ./
$(notdir names...)
返回文件名部分
$(notdir src/foo.c hacks)
结果为foo.c hacks
$(suffix names...)
返回后缀部分
$(basename names...)
返回除后缀的部分
src/foo.c 是 src/foo
$(addsuffix suffix,names...)
添加后缀
$(addsuffix .c,foo bar)
结果foo.c bar.c
$(addprefix prefix,names...)
添加前缀
$(addprefix src/,foo bar)
结果是:src/foo src/bar
$(join list1,list2)
1对1拼接,如果个数不同,一方没有,则直接返回另一方
$(join a b,.c .o)
结果为a.c b.o
$(wildcard pattern)
返回匹配pattern的文件列表,用空格分开
$(realpath names...)
返回the canonical absolute name,canonical name不包含.和..
如果文件不存在,返回空,如果是符号链接,会返回最终的文件。
$(abspath names...)
返回绝对路径,不包含. .. 和重复的//,abspath不解析符号链接,也不检查文件是否存在。
$(if condition,then-part[,else-part])
首先去掉condition两头的空白字符,然后扩展,如果扩展结果为非空,那么结果为真。
$(or condition1[,condition2[,condition3...]])
返回第一个非空的扩展。
$(and condition1[,condition2[,condition3...]])
有一个为空,则返回空,否则返回最后一个
$(foreach var,list,text)
遍历list,每次遍历的值存放在var,然后执行text扩展。结果是所有遍历扩展结果的拼接,用空格分开。
dirs := a b c d
files := $(foreach dir,$(dirs),$(wildcard $(dir)/*))
执行foreach期间,var是simply-expanded variable,但是text的类型是根据定义的类型来的。
find_files = $(wildcard $(dir)/*)
dirs := a b c d
files := $(foreach dir,$(dirs),$(find_files))
效果是一样的,因为find_files使用=,是recursively-expanding variable。
var变量的作用域在foreach,不影响其外面的变量。
把文本写入到一个文件,有两种模式,覆盖和追加
$(file op filename[,text])
op可以为>或者>>,如果text不包含换行,则最后会添加一个换行。如果写失败,将导致错误。file函数的返回结果总是空
$(file >.oldmode,$(MODEL))
call函数可以基于变量创建一个带参数的函数:
$(call variable,param,param,...)
当make扩展这个函数时,它把每个参数赋给临时变量 $(1), $(2), etc。变量$(0)包含variable。参数的个数没有限制。
然后variable作为make的一个变量在临时赋值上下文被扩展,因此变量中任何引用$(1)的地方都被解析为call的第一个参数。
注意variable是变量名,不是变量的引用。如果variable是一个内置函数,那么总是会调用内置函数,即使有个叫variable的变量存在。
call在赋值到临时变量之前扩展参数。如果有内置的函数,这些函数会事先被扩展,这是需要注意的地方。
交换
reverse = $(2) $(1)
foo = $(call reverse,a,b)
variable通常要是recursively-expanded variable,否则是没意义的,$(1)需要延迟扩展。
返回变量未经扩展的值。
FOO = $PATH
$(value FOO) 就是字面量$PATH。
value函数经常和eval函数一起使用。
eval函数的参数被扩展,然后扩展的结果被作为makefile语法解析。扩展的结果可以定义新的变量,目标,显示规则等。
eval函数的结果总是一个空字符串,所以它可以放在任何地方,不产生语法错误。
要理解的是:eval参数扩展了两次,第一次是eval本身,另外一次是做为make的语法。
1 2 3 4 5 6 | define a := b: @echo b endef $(eval $(a)) |
指出变量是在哪里定义的
$(origin variable)
undefined
default
environment
environment override
file
command line
override
automatic
指出变量的种类:
$(flavor variable)
undefined
recursive
simple
$(error text ...)
无论何时这个函数被evaluated,都产生一个错误。
可以这么用:
1 2 3 4 | ERR = $(error found an error!) .PHONY: err err: ; $(ERR) |
$(warning text ...)
$(info text ...)
调用一个shell,执行命令,输出结果是函数的结果,
contents := $(shell cat foo)
注意:
make将结果中的newline转换一个space,结尾的newline被删除。