make使用总结(4)-Makefile语法

make使用总结(4)-Makefile语法

函数

为了方便Makefile的编写,make已经为我们定义了多个常用函数。make函数的调用格式与变量引用相似,基本格式如下:$(function arguments)${function arguments}.arguments为函数的参数,参数以,进行分割。函数处理参数时,若参数中存在其它变量或函数的引用,则先展开参数再进行函数处理,展开顺序与参数的先后顺序一致。函数中的参数不能直接出现逗号和空格,前导空格会被忽略,若需要使用逗号和空格则需要将它们赋值给变量。下面一一介绍。

文本替换函数

函数subst,patsubst以字符串中的单词为单位。

  1. subst函数
    1. format:$(subst FROM,TO,TEXT)
    2. 将字符串TEXT中的FROM单词替换为TO
  2. patsubst函数
    1. format:$(patsubst PATTERN,REPLACEMENT,TEXT)
    2. 查找TEXT字符串中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式PATTERN,如果匹配的话,则以REPLACEMENT替换。这里,PATTERN可以包括通配符%,表示任意长度的字串。如果REPLACEMENT中也包含%,那么REPLACEMENT中的这个%将是PATTERN中的那个%所代表的字串。(可以用“\”来转义,以“%”来表示真实含义的“%”字符).
  3. strip函数
    1. format:$(strip STRING)
    2. 简化字符串中的空格,将多个连续空格合并成一个

使用例程如下:

#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)

字符串处理函数

  1. findstring函数
    1. format:$(findstring FIND,IN)
    2. 在字符串IN中查找字符串FIND,若存在返回字符串,否则返回空.
  2. filter函数
    1. $(filter PATTERN…,TEXT)
    2. 去除字符串TEXT中指定模式的字符串.
  3. filter-out函数
    1. format:$(filter-out PATTERN…,TEXT)
    2. 保留指定模式的字符串,去除其它字符串
  4. sort函数
    1. format:$(sort LIST)
    2. 按首字母顺序进行排序
  5. word函数
    1. format:$(word N,TEXT)
    2. 获取第N个单词
  6. wordlist函数
    1. format:$(wordlist S,E,TEXT)
    2. 获取从S位置到E位置的单词
  7. words函数
    1. format:$(words TEXT)
    2. 统计字符串中的单词数量
  8. firstword函数
    1. format:$(firstword NAMES…)
    2. 获取第一个单词
  9. join函数
    1. format:$(join LIST1,LIST2)
    2. 将LIST1和LIST2中的单词按顺序逐个连接
    3. 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
    
  10. call函数
    1. format:$(call VARIABLE,PARAM,PARAM,…)
    2. 此函数用于用户对自定义函数的引用。

使用例程如下:

#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)

文件名处理相关的函数

  1. dir函数
    1. format:$(dir NAMES…)
    2. 获取目录
  2. notdir函数
    1. format:$(notdir NAMES…)
    2. 获取文件名
  3. suffix函数
    1. format:$(suffix NAMES…)
    2. 获取文件名的后缀
  4. basename函数
    1. format:$(basename NAMES…)
    2. 获取文件名的前缀
  5. addsuffix函数
    1. format:$(addsuffix SUFFIX,NAMES…)
    2. 增加后缀
  6. addprefix函数
    1. format:$(addprefix PREFIX,NAMES…)
    2. 增加前缀
  7. wildcard函数
    1. format:$(wildcard PATTERN)
    2. 通配符使用。在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)

控制和变量相关的函数

  1. shell函数
    1. format:$(shell CMD…)
    2. 调用shell并传入CMD作为参数。我们在除了规则以外的地方使用shell命令时就要用此函数来调用shell命令。
  2. foreach函数
    1. format:$(foreach VAR,LIST,TEXT)
    2. 把LIST字符串中的单词依次赋给VAR,并执行TEXT中的表达式
  3. if条件函数
    1. format:$(if CONDITION,THEN-PART[,ELSE-PART])
    2. 如果满足CONDITION条件,执行THEN-PART语句,否则执行ELSE-PART语句
  4. error函数
    1. format:$(error TEXT…)
    2. 产生致命错误并以TEXT内容进行提示
  5. warning函数
    1. format:$(warning TEXT…)
    2. 产生警告并以TEXT内容进行提示
  6. value函数
    1. format:$(value VARIABLE)
    2. 返回VARIABLE未展开前的定义值,即makefile中定义变量时所书写的字符串。
  7. origin函数
    1. format:$(value VARIABLE)
    2. 返回变量的初始定义方式,包括:undefined,default,environment,environment override,file,command line,override,automatic
  8. 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
微信公众号:嵌入式的日常
如果上面的文章对你有用,欢迎打赏、点赞、评论。二维码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Makefile 是用于自动化编译程序的工具,它使用一种名为“规则”的方式来描述源文件和目标文件之间的依赖关系,然后根据这些规则自动编译程序。 Makefile 通常包括以下几个部分: 1. 变量定义:定义需要的变量,如编译器、编译选项等。 2. 目标文件:定义需要编译的目标文件、依赖文件和编译规则。 3. 伪目标:定义一些伪目标,如 clean、install 等。 下面是 Makefile语法: 1. 变量定义: 变量定义的语法格式为: ``` 变量名 = 变量值 ``` 例如: ``` CC = gcc CFLAGS = -Wall -O2 ``` 2. 目标文件: 目标文件的格式为: ``` 目标文件: 依赖文件 编译规则 ``` 例如: ``` main.o: main.c $(CC) $(CFLAGS) -c main.c -o main.o ``` 其: - 目标文件是 main.o。 - 依赖文件是 main.c。 - 编译规则是 $(CC) $(CFLAGS) -c main.c -o main.o,表示使用 gcc 编译器和编译选项将 main.c 编译成 main.o。 3. 伪目标: 伪目标的格式为: ``` 伪目标: 命令 ``` 例如: ``` clean: rm -rf *.o ``` 其: - 伪目标是 clean。 - 命令是 rm -rf *.o,表示删除所有的 .o 文件。 这些是 Makefile 的基本语法,你可以根据需要添加更多的规则来实现自动化编译。 ### 回答2: Makefile是用于自动化构建和管理软件项目的一种脚本语言,它描述了软件项目的文件依赖关系和构建规则。Makefile文件通常包含一系列规则和命令。 Makefile的基本语法包括: 1.目标(Target):由一组规则组成,表示一个或多个文件的生成或操作。目标的命名可以是任意合法的文件名。 2.依赖(Prerequisites):目标所依赖的文件或目标。依赖可以是文件、目录或其他目标。当依赖发生变化时,相应的目标将重新生成。 3.命令(Command):规则执行的命令。命令必须以Tab键开头,并且可以有多条。 4.规则(Rule):目标、依赖和命令的组合。规则表示了如何生成目标文件或执行一系列操作。 5.变量(Variables):用于存储常用的值或字符串,以便在Makefile重复使用。变量以$符号开头,并用括号括起来。 6.条件判断(Conditionals):用于根据特定条件选择不同的规则或命令执行路径。条件判断以ifeq、ifneq等关键字开头。 7.循环(Loops):可以在Makefile使用循环语句,例如foreach、while等,用于重复执行特定的操作。 Makefile的执行过程是根据文件的依赖关系来决定哪些目标需要重新生成。当执行make命令时,Makefile会被解析,并根据依赖关系构建目标文件,如果目标文件已经存在且依赖没有发生变化,则不会重新生成。 Makefile的优点是可以自动化构建过程、减少重复操作、提高项目的可维护性和可靠性。它可以根据项目的需要灵活定义构建规则,并自动处理文件间的依赖关系,大大简化了项目的管理工作和构建过程。 ### 回答3: makefile是一种用于构建和管理软件项目的工具,它使用明确的规则来指导编译和链接操作。它通常用于编译C/C++等编程语言的项目。 makefile的基本语法包含了规则、变量和命令。 规则是makefile的核心,它由目标、依赖和命令组成。目标是需要生成的文件,依赖是生成目标所依赖的文件或其他目标,命令是生成目标的具体操作。规则的格式如下: ``` 目标: 依赖 [tab] 命令 ``` 变量在makefile用于保存常用的路径、编译选项等信息。可以通过变量的引用来简化makefile的书写和维护。变量的定义使用等号(=)来完成,如: ``` 变量名 = 值 ``` 命令是makefile的具体操作步骤,用于生成目标。每条命令都必须以一个制表符(tab)开头,否则会被当作普通文本处理。 makefile还有一些常用的指令,如clean、all等。clean指令用于清理编译生成的目标文件和可执行文件,all指令用于编译所有文件。 makefile的优势在于可以自动判断哪些文件需要重新编译,从而提高了构建效率。它可以根据文件的修改时间和依赖关系来确定需要重新编译的文件,并只编译这些文件,避免了不必要的重复操作。 总之,makefile是一种强大的构建工具,它以简洁的语法和智能的依赖关系判断,能够实现高效的软件构建和管理。但需要注意的是,makefile语法在不同的平台和编译器上可能会有一些差异,需要根据具体情况进行调整和学习。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

theboynoName

感谢鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值