make使用总结(4)-Makefile语法
函数
为了方便Makefile的编写,make已经为我们定义了多个常用函数。make函数的调用格式与变量引用相似,基本格式如下:$(function arguments)
或 ${function arguments}
.arguments为函数的参数,参数以,
进行分割。函数处理参数时,若参数中存在其它变量或函数的引用,则先展开参数再进行函数处理,展开顺序与参数的先后顺序一致。函数中的参数不能直接出现逗号和空格,前导空格会被忽略,若需要使用逗号和空格则需要将它们赋值给变量。下面一一介绍。
文本替换函数
函数subst,patsubst以字符串中的单词为单位。
subst
函数- format:$(subst FROM,TO,TEXT)
- 将字符串
TEXT
中的FROM
单词替换为TO
。
patsubst
函数- format:$(patsubst PATTERN,REPLACEMENT,TEXT)
- 查找TEXT字符串中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式PATTERN,如果匹配的话,则以REPLACEMENT替换。这里,PATTERN可以包括通配符
%
,表示任意长度的字串。如果REPLACEMENT中也包含%
,那么REPLACEMENT中的这个%
将是PATTERN中的那个%
所代表的字串。(可以用“\”来转义,以“%”来表示真实含义的“%”字符).
- strip函数
- format:$(strip STRING)
- 简化字符串中的空格,将多个连续空格合并成一个
使用例程如下:
#test function subst patsubst strip
.PHONY:raw sub patsub
str_a := a.o b.o c.o f.o.o abcdefg
str_b := $(subst .o,.c,$(str_a))
str_c := $(patsubst %.o,%.c,$(str_a))
str_d := $(patsubst .o,.c,$(str_a))
str_e := $(patsubst a.o,a.c,$(str_a))
str_1 := " a b c "
str_2 := $(strip $(str_1))
sub:raw
@echo "str_b=" $(str_b) #replace all match char for per word
patsub:raw
@echo "str_c=" $(str_c) #replace match pattern
@echo "str_d=" $(str_d) #replace nothing
@echo "str_e=" $(str_e) #replace all-match word
strip:
@echo "str_1=" $(str_1) #looks like auto strip by make4.1
@echo "str_2=" $(str_2)
raw:
@echo "str_a=" $(str_a)
字符串处理函数
findstring
函数- format:$(findstring FIND,IN)
- 在字符串IN中查找字符串FIND,若存在返回字符串,否则返回空.
filter
函数- $(filter PATTERN…,TEXT)
- 去除字符串TEXT中指定模式的字符串.
filter-out
函数- format:$(filter-out PATTERN…,TEXT)
- 保留指定模式的字符串,去除其它字符串
sort
函数- format:$(sort LIST)
- 按首字母顺序进行排序
word
函数- format:$(word N,TEXT)
- 获取第N个单词
wordlist
函数- format:$(wordlist S,E,TEXT)
- 获取从S位置到E位置的单词
words
函数- format:$(words TEXT)
- 统计字符串中的单词数量
firstword
函数- format:$(firstword NAMES…)
- 获取第一个单词
join
函数- format:$(join LIST1,LIST2)
- 将LIST1和LIST2中的单词按顺序逐个连接
- eg:
str_a := cxx.o n.o fxx.o str_join := ./dira/ ./dirb/ ./dirc/ str_n := $(join $(str_join),$(str_a)) # 链接结果 # str_n= ./dira/cxx.o ./dirb/n.o ./dirc/fxx.o
call
函数- format:$(call VARIABLE,PARAM,PARAM,…)
- 此函数用于用户对自定义函数的引用。
使用例程如下:
#test wrods related function
.PHONY:raw find filt filt_out sort word word_list first_word words join call
str_a := cxx.o n.o fxx.o xy.c fab.o zy.py jor.py abc.o
str_b := $(findstring xx,$(str_a)) #make sure if xx include in str_a
str_c := $(findstring .o x,$(str_a)) #even can include space char
str_d := $(findstring nothing,$(str_a)) #search no-exist words
str_e := $(filter %.py,$(str_a)) #filster
str_f := $(filter-out %.py,$(str_a)) #filter-out
str_g := $(sort $(str_a)) #sort according first char,if same then next char
str_h := $(word 3,$(str_a)) # get the 3rd word
str_i := $(word 99,$(str_a)) # out of range
str_j := $(wordlist 3,5,$(str_a)) #list 3rd to 5rd words
str_k := $(wordlist 3,99,$(str_a)) #list our of range
str_l := $(firstword $(str_a)) #first word
str_m := $(words $(str_a)) #cacu words num
str_join := ./dira/ ./dirb/ ./dirc/ ./dird/ ./dire/ ./dirf/
str_n := $(join $(str_join),$(str_a))
part_rev = $(4) $(3) $(2) $(1)
str_o = $(call part_rev,a,b,c,d,e,f,g) #must use "="
raw:
@echo "str_a=" $(str_a)
find:raw
@echo "str_b=" $(str_b)
@echo "str_c=" $(str_c)
@echo "str_d=" $(str_d)
filt:raw
@echo "str_e=" $(str_e)
filt_out:raw
@echo "str_f=" $(str_f)
sort:raw
@echo "str_g=" $(str_g)
word:raw
@echo "str_h=" $(str_h)
@echo "str_i=" $(str_i)
word_list:raw
@echo "str_j=" $(str_j)
@echo "str_k=" $(str_k)
first_word:raw
@echo "str_l=" $(str_l)
words:raw
@echo "str_m=" $(str_m)
join:raw
@echo "str_join=" $(str_join)
@echo "str_n=" $(str_n)
call:
@echo "str_o=" $(str_o)
文件名处理相关的函数
dir
函数- format:$(dir NAMES…)
- 获取目录
notdir
函数- format:$(notdir NAMES…)
- 获取文件名
suffix
函数- format:$(suffix NAMES…)
- 获取文件名的后缀
basename
函数- format:$(basename NAMES…)
- 获取文件名的前缀
addsuffix
函数- format:$(addsuffix SUFFIX,NAMES…)
- 增加后缀
addprefix
函数- format:$(addprefix PREFIX,NAMES…)
- 增加前缀
wildcard
函数- format:$(wildcard PATTERN)
- 通配符使用。在Makefile规则中,通配符会被自动展开。但在变量定义和函数引用时,通配符将失效。但可以使用wildcard()函数来完成通配符的使用。在Makefile中,它被展开为已经存在的、使用空格分开的、匹配此模式的所有文件列表.如果不存在任何符合此模式的文件,函数会忽略模式字符并返回空。
.PHONY:init clean dir notdir base suffix addprefix addsuffix wildcard
dirs := dir_a
files := file_a.c file_b.s file_c.o #each file under per dir
files_a := $(foreach each,$(files),$(dirs)"/"$(each)) #get all files under a dir by foreach & word func
all_files := $(files_a)
detect_files := $(foreach each,$(dirs),$(wildcard $(each)/*))
detect_files := $(foreach each,$(detect_files),$(PWD)"/"$(each))
show := $(patsubst %,"\n"%,$(detect_files)) #add '\n' for view
vari_dir := $(dir $(detect_files))
show_dir := $(patsubst %,"\n"%,$(vari_dir))
vari_files := $(notdir $(detect_files))
vari_base := $(basename $(detect_files))
show_base := $(patsubst %,"\n"%,$(vari_base))
vari_suffix := $(suffix $(detect_files))
vari_addprefix := $(addprefix "full name:",$(detect_files))
show_addprefix := $(patsubst %,"\n"%,$(vari_addprefix))
vari_addsuffix := $(addsuffix ".text",$(detect_files))
show_addsuffix := $(patsubst %,"\n"%,$(vari_addsuffix))
test:
@echo "detected files:" $(vari_addprefix)
init:
@mkdir $(dirs);\
touch $(all_files);\
tree
dir:
@echo "detected files:" $(show)
@echo "get dir:" $(show_dir)
notdir:
@echo "detected files:" $(show)
@echo "get files:"
@echo $(vari_files)
base:
@echo "detected files:" $(show)
@echo "file base name:" $(show_base)
suffix:
@echo "detected files:" $(show)
@echo "file suffix:" $(vari_suffix)
addprefix:
@echo "detected files:" $(show)
@echo "file add prefix:" $(show_addprefix)
addsuffix:
@echo "detected files:" $(show)
@echo "file add suffix:" $(show_addsuffix)
clean:
@rm -rf $(dirs)
控制和变量相关的函数
shell
函数- format:$(shell CMD…)
- 调用shell并传入CMD作为参数。我们在除了规则以外的地方使用shell命令时就要用此函数来调用shell命令。
foreach
函数- format:$(foreach VAR,LIST,TEXT)
- 把LIST字符串中的单词依次赋给VAR,并执行TEXT中的表达式
if
条件函数- format:
$(if CONDITION,THEN-PART[,ELSE-PART])
- 如果满足CONDITION条件,执行THEN-PART语句,否则执行ELSE-PART语句
- format:
error
函数- format:$(error TEXT…)
- 产生致命错误并以TEXT内容进行提示
warning
函数- format:$(warning TEXT…)
- 产生警告并以TEXT内容进行提示
value
函数- format:$(value VARIABLE)
- 返回VARIABLE未展开前的定义值,即makefile中定义变量时所书写的字符串。
origin
函数- format:$(value VARIABLE)
- 返回变量的初始定义方式,包括:undefined,default,environment,environment override,file,command line,override,automatic
eval
函数
makefile1
.PHONY:init clean for_loop if_cond err warn shell
dirs := dir_a dir_b dir_c dir_d #each dir
files := file_a file_b file_c #each file under per dir
files_a := $(foreach each,$(files),$(word 1,$(dirs))"/"$(each)) #get all files under a dir by foreach & word func
files_b := $(foreach each,$(files),$(word 2,$(dirs))"/"$(each))
files_c := $(foreach each,$(files),$(word 3,$(dirs))"/"$(each))
files_d := $(foreach each,$(files),$(word 4,$(dirs))"/"$(each))
all_files := $(files_a)
all_files += $(files_b)
all_files += $(files_c)
all_files += $(files_d)
detect_files := $(foreach each,$(dirs),$(wildcard $(each)/*))
detect_files := $(patsubst %,"\n"%,$(detect_files)) #add '\n' for view
vari_a :=
vari_b := b
vari_c := $(if $(vari_a),"vari_a has value:"$(vari_a),"vari_a has no value")
vari_d := $(if $(vari_b),"vari_b has value:"$(vari_b),"vari_b has no value")
err_exit := $(if $(vari_e),$(error "you generate a error!"),"no error defined") #define vari_e to enable error
warn_go := $(if $(vari_f),$(warning "you generate a warning!"),"no warning defined") #define vari_f to enalbe warning
shell_cmd := $(shell date)
init:
@mkdir $(dirs);\
touch $(all_files);\
tree
for_loop:
@echo "files=" $(detect_files)
if_cond:
@echo "vari_a=" $(vari_a)
@echo "vari_b=" $(vari_b)
@echo "vari_c=" $(vari_c)
@echo "vari_d=" $(vari_d)
warn:
@echo $(warn_go)
err:
@echo $(err_exit)
shell:
@echo $(shell_cmd)
clean:
@rm -rf $(dirs)
makefile2
#this is a eval func test
PROGRAMS = server client
server_OBJS = server.o server_pri.o server_access.o
server_LIBS = priv protocol
client_OBJS = client.o client_api.o client_mem.o
client_LIBS = protocol
.PHONY:all
define PROGRAM_template
$(1):
touch $$($(1)_OBJS) $$($(1)_LIBS)
@echo $$@ " build finished!"
endef
$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog))))
$(PROGRAMS):
clean:
$(RM) *.o $(server_LIBS) $(client_LIBS)
makefile3
.PHONY:value origin
vari_a = abc
vari_b = $(vari_a)
vari_c = $(vari_a) "+" $(vari_b)
override vari_d = vari_a
vari_e = $($(vari_d))
vari_1 = $(value vari_a)
vari_2 = $(value vari_b)
vari_3 = $(value vari_c)
vari_4 = $(value vari_d)
vari_5 = $(value vari_e)
FOO=$PATH
all:
@echo $(FOO)
@echo $(value FOO)
value:
@echo "vari_1=" '$(vari_1)'
@echo "vari_2=" '$(vari_2)'
@echo "vari_3=" '$(vari_3)'
@echo "vari_4=" '$(vari_4)'
@echo "vari_5=" '$(vari_5)'
origin:
@echo "origin vari_a:" $(origin vari_a)
@echo "origin vari_b:" $(origin vari_b)
@echo "origin vari_c:" $(origin vari_c)
@echo "origin vari_d:" $(origin vari_d)
@echo "origin vari_e:" $(origin vari_e)
@echo 'origin $$@:' $(origin @)
@echo "origin vari_f:" $(origin vari_f)
@echo "origin PATH:" $(origin PATH)
@echo "origin MAKE:" $(origin MAKE)
自定义函数
除此之外,我们还可以自定义一些函数。使用下面的格式定义函数:
define DELFILE
$(Q) if exist $1 (del /f /q $1)
endef
其中$1
~$9
表示函数输入的参数。调用自定义函数需要使用make已经定义好的call
函数。如$(call DELFILE, Make.dep)
.
关于技术交流
此处后的文字已经和题目内容无关,可以不看。
qq群:825695030
微信公众号:嵌入式的日常
如果上面的文章对你有用,欢迎打赏、点赞、评论。