文章目录
- @echo 用法
- eval 函数
- ln 命令
- cc-option 函数
- cc-disable-warning 函数
- dir 函数
- basename 函数
- notdir 函数
- wildcard 函数
- addprefix 函数
- foreach函数
- filter函数
- filter-out函数
- patsubst函数
- sort函数
- call函数
- subst函数
- strip函数
- firstword函数
- @F
- cmp 命令
- touch 命令
- fixdep工具
- escsq函数(uboot)
- make-cmd函数(uboot)
- echo-why函数(uboot)
- echo-cmd函数(uboot)
- set -e
- cmd函数(uboot)
- if_changed_dep函数(uboot)
- if_changed函数(uboot)
- filechk 函数(uboot)
- deprecated 函数(uboot)
@echo 用法
如果规则的命令行以字符
@
开始,则make在执行这个命令时就不会回显这个将要被执行的命令。
例如:
@echo '开始编译XXX模块'
执行时,将会得到“开始编译XXX模块
”这条输出信息。
如果在命令行之前没有字符@
,那么,make 的输出将是:“echo '开始编译XXX模块'
”
eval 函数
$(eval text)
作用:是Makefile的一个内建函数,用于在Makefile中动态创建新的make规则。会将参数文本解析为Makefile语法,然后执行。
参数:text
是你想要创建的make规则或者定义的变量
返回:文件所在目录。
ln 命令
ln [选项]... [-T] 目标 链接名
# 创建一个到目标的链接,名称为链接名
ln [选项]... 目标
# 在当前目录中创建一个到目标的链接
ln [选项]... 目标... 目录
# 在目录中创建指向每个目标的链接
选项:
--backup[=CONTROL] :
为每个已存在的目标文件创建备份文件
-b:
类似–backup,但不接受任何参数
-d, -F, --directory :
创建指向目录的硬链接(只适用于超级用户)
-f, --force:
强行删除任何已存在的目标文件
-i, --interactive:
提示是否删除目的地
-L, --logical:
解引用的目标是符号链接
-n, --no-dereference:
将链接名视为普通文件,它是指向目录的符号链接
-P, --physical:
将硬链接直接设置为符号链接
-r, --relative:
创建相对于链接位置的符号链接
-s, --symbolic:
用符号链接代替硬链接
-S, --suffix=SUFFIX :
覆盖通常的备份后缀
-t, --target-directory=DIRECTORY :
指定在其中创建链接的DIRECTORY
-T, --no-target-directory:
始终将LINK_NAME视为普通文件
-v, --verbose:
打印每个链接文件的名称
--help:
显示此帮助信息并退出
--version:
显示版本信息并退出
cc-option 函数
$(call cc-option,-fno-stack-protector)
第一个参数赋给$ (1)(这里是指-fno-stack-protector),
第二个参数给$(2)(这里为空)。
变量cc-option的值
是函数try-run的执行结果
,函数try-run又是$(shell ....)输出的结果
;也就是if …else…的结果。在函数try-run中:
- $(1) : $(CC) -Werror $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "
- $(2) : 函数cc-option的 $(1) (这里是指-fno-stack-protector)
- $(3) : 函数cc-option的 $(2) (这里为空)
如果函数try-run的$(1)能执行,那么echo $(2),否则echo $(3);echo 的值正是cc-option的值 。
综上:
如果交叉编译工具$(CC)
支持cc-optionl函数
的参数1
表示的选项(也就是指-fno-stack-protector),那么cc-option函数的返回就是该选项(指-fno-stack-protector),否则返回的是call函数的参数2
表示的选项。cc-option:检测$(CC) 是否支持给定的选项
cc-disable-warning 函数
cc-disable-warning
检查 gcc 是否支持给定的警告,并返回命令行开关以禁用它。此特殊函数是必需的,因为 gcc 4.4 及更高版本接受任何未知的-Wno-*
选项,并且仅在源文件中有其他警告时才发出警告。KBUILD_CFLAGS += $(call cc-disable-warning, stringop-truncation)
在上面的示例中,只有当 gcc 真正接受
-Wno-stringop-truncation
变量时,才会将其添加到KBUILD_CFLAGS
。
dir 函数
$(dir <names...>)
作用:获取文件所在目录,本质是获取最后一个反斜杠 ‘/’ 以前的内容。如果没有反斜杠 ‘/’ ,返回 ./
参数:不同文件名之间以空格隔开。
返回:文件所在目录。
basename 函数
$(basename <names...>)
作用:从文件名序列<names>
中取出各个文件名的前缀部分。
参数:文件名序列
返回:返回文件名序列<names>
的前缀序列,如果文件没有前缀,则返回空字串。
例如:$(basename src/main.c src/hello.c) 返回值为:src/main src/hello
notdir 函数
$(notdir <names...>)
作用:获取一个文件路径的非目录部分,也可以理解为获取文件名(含后缀),本质是获取最后一个反斜杠 ‘/’ 之后的内容。如果没有反斜杠,直接返回本身。
参数:不同文件名之间以空格隔开。
返回:文件名(含后缀)。
wildcard 函数
$(wildcard PATTERN...)
作用:在Makefile中用于获取匹配指定模式的所有文件名列表。
参数:指定模式。
返回:返回与模式相匹配的所有文件名列表,如果没有任何匹配,那么返回空字符串。
addprefix 函数
$(addprefix PREFIX,NAMES…)
作用:文件名添加前缀的函数,为“NAMES…”中的每一个文件名添加前缀“PREFIX”
参数:“NAMES…”是空格分割的文件名序列;“PREFIX”是给文件名添加的前缀。
返回:以单空格分割的添加了前缀“PREFIX”的文件名序列。
foreach函数
$(foreach VAR,LIST,TEXT)
作用:执行时把"LIST"中使用空格分隔的字符串依次取出赋值给变量"VAR",然后执行"TEXT"表达式。重复直到"LIST"的最后一个字符串。"TEXT"中的变量或函数引用在执行时才被展开,因此,如果在"TEXT"中存在对"VAR"的引用,那么"VAR"的值在每一次展开式将会是不同的值。如果存在变量或函数的引用,首先需要展开变量"VAR"和"LIST"的引用
参数:"VAR"是一个局部的临时变量,它只在"foreach"函数的上下文有效,它的定义不影响其他部分定义的同名"VAR"变量的值。
返回:无。
filter函数
$(filter PATTERN…,TEXT)
作用:过滤掉字串“TEXT”中所有不符合模式“PATTERN”的单词,保留所有符合此模式的单词。可以使用多个模式。模式中一般需要包含模式字符“%”。存在多个模式时,模式表达式之间使用空格分割。
参数:
返回:空格分割的“TEXT”字串中所有符合模式“PATTERN”的字串。
filter-out函数
$(filter-out PATTERN…,TEXT)
作用:过滤掉字串“TEXT”中所有符合模式“PATTERN”的单词,保留所有不符合此模式的单词。可以有多个模式。存在多个模式时,模式表达式之间使用空格分割。
参数:
返回:空格分割的“TEXT”字串中所有不符合模式“PATTERN”的字串。
patsubst函数
$(patsubst pattern,replacement,text)
作用:过查找text中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式pattern,如果匹配的话,则以replacement替换。这里,pattern可以包括通配符“%”,表示任意长度的字串。如果replacement中也包含“%”,那么,replacement中的这个“%”将是pattern中的那个“%”所代表的字串。(可以用“\”来转义,以“%”来表示真实含义的“%”字符)
参数:
返回:返回被替换过后的字符串。
sort函数
$(sort list)
作用:是Makefile的一个内建函数,它用于将列表中的词进行排序,并删除重复的词。
参数:
返回:
call函数
$(call 函数名 参数1, 参数2, ...)
作用:给自定义函数传递参数,并展开。一般而言,call 本身并不具备编译功能,call 只是将自定义函数在当前位置展开,遇到Makefile内置函数会自动执行(比如 info,warning等),调用函数的时候要使用字符“$”,后面可以跟小括号也可以使用花括号。
参数:参数之间要用逗号分隔开,参数和函数名之间使用空格分开。
返回:函数名对应的函数返回值就是 call 函数的返回值。
注意: make 执行这个函数的时候,函数名对应的函数参数中的变量$(1)、$(2)、$(3)等,会被参数1,参数2,参数3依次取代。
subst函数
$(subst <from>,<to>,<text>)
作用:字符串处理函数,把字符串<text>中的<from>字符串替换成<to>。
参数:
返回:返回被替换过后的字符串。
strip函数
$(strip STR)
作用:去掉字符串中多余的空格符(若干单词,使用若干空字符分割) “STR”开头和结尾的空字符,并将其中多个连续空字符合并为一个空字符。
参数:
返回:无前导和结尾空字符、使用单一空格分割的多单词字符串。
firstword函数
$(firstword <text>)
作用:取字符串中的第一个单词。
参数:
返回:返回字符串的第一个单词。
@F
@F
表示"$@“的文件部分,如果”$@“值是"dir/foo.o”,那么"$(@F)“是"foo.o”,“$(@F)“相当于函数”$(notdir $@)”
cmp 命令
cmp 命令是 Linux 系统中用于比较两个文件是否有差异的命令。它能够比较两个文件的内容,并在发现差异时显示差异的位置。如果两个文件完全相同,cmp 命令不会输出任何信息。
使用 cmp 命令时,可以指定两个文件名作为参数,也可以使用 - 作为参数来从标准输入读取数据。此外,cmp 命令支持多种选项来控制其行为,例如:
-l 或--verbose
:显示所有不同之处。
-s 或--quiet
或--silent
:不显示错误信息。
-c 或--print-chars
:除了标明差异处的十进制字码之外,一并显示该字符所对应字符。
-i <字符数目> 或 --ignore-initial=<字符数目>:指定一个数目,忽略每个文件开头的指定数量的字符后再进行比较。
-v 或 --version:显示版本信息。
–help:显示帮助信息。
touch 命令
touch [选项] [文件名]
作用:用来创建新的空文件或者修改已有文件的访问时间和修改时间。如果文件不存在
,则会创建出一个空内容的文本文件;如果文件已经存在
,则会对文件的Atime(访问时间)和Ctime(修改时间)进行修改操作,管理员可以完成此项工作,而普通用户只能管理主机的文件。
参数1:[选项]
-a:只修改访问时间
-c:仅在文件不存在的情况下创建文件
-m:只修改修改时间
-d:使用指定的时间,而非当前时间作为文件的时间
参数2:[文件名] 创建或修改的文件。
示例:
- 创建新文件:
touch newfile.txt
在当前目录下创建一个名为newfile.txt的空文件- 批量创建文件:
touch file{1..5}.txt
创建file1.txt、file2.txt、file3.txt、file4.txt、file5.txt这五个文件- 更新文件时间戳:
touch -m file.txt
将file.txt的修改时间更新为当前时间- 指定时间戳:
touch -d "2022-01-01" file.txt
将file.txt的时间属性修改为指定的日期- 创建带有目录结构的文件:
mkdir dir && touch dir/file.txt
先创建一个名为dir的目录,然后在该目录下创建一个名为file.txt的文件- 更新多个文件的时间戳:
touch file*.txt
更新所有以file开头且以.txt结尾的文件的时间戳- 修改访问时间而不新建文件:
touch -a file.txt
将file.txt的访问时间更新为当前时间- 禁止创建新文件:
touch -c newfile.txt
如果newfile.txt文件已经存在,则不会有任何变化;如果文件不存在,则不会创建新文件
fixdep工具
fixdep <depfile> <target> <cmdline>
作用:查找实现目标所用的命令、源码、头文件等全部信息。
参数1:<depfile>编译产生的依赖文件*.d
参数2:<target>编译生成的目标
参数3:<cmdline>编译使用的命令
返回:实现目标所用的命令、源码、头文件等全部信息
escsq函数(uboot)
作用:将参数1(字符串)中的
'
替换成\'
返回:返回被替换过后的字符串。
分析:此函数在 scripts/Kbuild.include 第32行定义:7 squote := ' 32 escsq = $(subst $(squote),'\$(squote)',$1)
make-cmd函数(uboot)
作用:将$(cmd_$(1)) 中的
\$
替换成$$
,然后将替换后的字符串中的#
替换成$(pound)
[即 \#],再次将替换后的字符串中'
替换成\'
返回:返回$(cmd_$(1))
被替换过后的字符串。
分析:此函数在 scripts/Kbuild.include 第32行定义:11 pound := \# 252 make-cmd = $(call escsq,$(subst $(pound),$$(pound),$(subst $$,$$$$,$(cmd_$(1)))))
echo-why函数(uboot)
作用:条件不成立,函数为空
分析:此函数在 scripts/Kbuild.include 第299-318行定义:299 ifeq ($(KBUILD_VERBOSE),2) 300 why = \ 301 $(if $(filter $@, $(PHONY)),- due to target is PHONY, \ 302 $(if $(wildcard $@), \ 303 $(if $(strip $(any-prereq)),- due to: $(any-prereq), \ 304 $(if $(arg-check), \ 305 $(if $(cmd_$@),- due to command line change, \ 306 $(if $(filter $@, $(targets)), \ 307 - due to missing .cmd file, \ 308 - due to $(notdir $@) not in $$(targets) \ 309 ) \ 310 ) \ 311 ) \ 312 ), \ 313 - due to target missing \ 314 ) \ 315 ) 316 317 echo-why = $(call escsq, $(strip $(why))) 318 endif
由于输入
make V=1
,所以$(KBUILD_VERBOSE)=1
,这里条件不成立,echo-why 为空
echo-cmd函数(uboot)
作用:将
$($(quiet)cmd_$(1)))
中的'
替换成\'
后打印
返回:将$($(quiet)cmd_$(1)))
中的'
替换成\'
后打印
分析:此函数在 scripts/Kbuild.include 第220行定义:220 echo-cmd = $(if $($(quiet)cmd_$(1)),\ 221 echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
判断
$($(quiet)cmd_$(1)))
是否存在,不存在echo-cmd=空
,否则将$($(quiet)cmd_$(1)))
中的'
替换成\'
后打印
set -e
set -e
是 Linux shell 中的一个选项,它的作用是在脚本执行过程中,一旦出现任何命令执行失败(返回非零的退出状态码),脚本就会立即退出。
cmd函数(uboot)
作用: 执行
cmd_$(1)
内容,打印其内容。
分析:由于在顶层Makefile的第386行中引用include scripts/Kbuild.include
, cmd函数在此文件224行中定义:7 squote := ' 32 escsq = $(subst $(squote),'\$(squote)',$1) ...... 299 ifeq ($(KBUILD_VERBOSE),2) 300 why = \ 301 $(if $(filter $@, $(PHONY)),- due to target is PHONY, \ 302 $(if $(wildcard $@), \ 303 $(if $(strip $(any-prereq)),- due to: $(any-prereq), \ 304 $(if $(arg-check), \ 305 $(if $(cmd_$@),- due to command line change, \ 306 $(if $(filter $@, $(targets)), \ 307 - due to missing .cmd file, \ 308 - due to $(notdir $@) not in $$(targets) \ 309 ) \ 310 ) \ 311 ) \ 312 ), \ 313 - due to target missing \ 314 ) \ 315 ) 316 317 echo-why = $(call escsq, $(strip $(why))) 318 endif ...... 220 echo-cmd = $(if $($(quiet)cmd_$(1)),\ 221 echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';) 222 223 224 cmd = @$(echo-cmd) $(cmd_$(1))
第220行,$(quiet) 在顶层Makefile中定义:
命令行中输入:make V=number
其中number不等于1时,quiet=quiet_
,否则为空
命令行中输入:make -s
时,quiet=silent_
,否则为空
由于输入的是make V=1
,所以quiet=
第220行,escsq函数定义在第32行,最终 $(call escsq, ( ( ((quiet)cmd_$(1))) 展开后为 cmd_$(1)
第220行,$(echo-why)定义在第317行,由于输入的是make V=1
,所以KBUILD_VERBOSE=1
,条件不成立,$(echo-why)为空
第220行,最终展开为:即判断cmd_$(1)
是否存在,存在则打印其内容220 echo-cmd = $(if $(cmd_$(1)),echo ' $(cmd_$(1))';)
第224行,最终展开为:即判断
cmd_$(1)
是否存在,不论是否存在都不回显其内容,最后执行cmd_$(1)
内容224 cmd = @$(if $(cmd_$(1)),echo ' $(cmd_$(1))';) $(cmd_$(1))
if_changed_dep函数(uboot)
作用: 打印和执行
cmd_$(1)
,并将实现目标$@所用的命令、源码、头文件等信息全部写入到$(obj)/.$@.cmd
文件中。
分析:由于在顶层Makefile的386行引用scripts/Kbuild.include
, if_changed_dep 函数在此文件266行中定义:5 comma := , 14 # Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o 15 dot-target = $(dir $@).$(notdir $@) 20 depfile = $(subst $(comma),_,$(dot-target).d) ...... 237 ifneq ($(KBUILD_NOCMDDEP),1) 238 # Check if both arguments are the same including their order. Result is empty 239 # string if equal. User may override this check using make KBUILD_NOCMDDEP=1 240 arg-check = $(filter-out $(subst $(space),$(space_escape),$(strip $(cmd_$@))), \ 241 $(subst $(space),$(space_escape),$(strip $(cmd_$1)))) 242 else 243 arg-check = $(if $(strip $(cmd_$@)),,1) 244 endif ...... 256 any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^) ...... 266 if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), \ 267 @set -e; \ 268 $(echo-cmd) $(cmd_$(1)); \ 269 scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp;\ 270 rm -f $(depfile); 271 mv -f $(dot-target).tmp $(dot-target).cmd, @:) \
第266行中$(any-prereq)在第256行中定义,
$?
依赖文件列表中被改变过的所有文件,$^
表示所有的依赖文件,所以$(filter-out $(PHONY) $(wildcard $^),$^)
返回的是空字符串。
最终: any-prereq=$? 【依赖文件列表中被改变过的所有文件】
第266行中$(arg-check)在第237-244行中定义,只有在命令行中输入make KBUILD_NOCMDDEP=1
时,执行243行,所以这里执行240行,其中的$(space),$(space_escape)
在8-10行定义。
最终: arg-check = 将 $(cmd_$1) 中所有空格替换成 -SPACE- 后的字符串8 empty := 9 space := $(empty) $(empty) 10 space_escape := _-_SPACE_-_
所以第266行条件成立,最终展开为:
if_changed = @set -e; \ $(echo-cmd) $(cmd_$(1)); \ scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp; \ rm -f $(depfile); \ mv -f $(dot-target).tmp $(dot-target).cmd
$(depfile)
在5-20行定义,最终: depfile = $(dir $@).$(notdir $@).d
$(dot-target)
在5-20行定义,最终: dot-target = $(dir $@).$(notdir $@)
最终:
set -e
:在脚本执行过程中,出现任何命令执行失败,脚本立即退出;$(echo-cmd)
:将$(cmd_$(1))中的'
替换成\'
后打印;$(cmd_$(1))
:执行里面的命令;scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp
:fixdep工具将实现目标$@所用的命令、源码、头文件等信息全部写入到中间文件 $(depfile) 中,并输出到 $(dot-target).tmp 文件中;rm -f $(depfile)
:删除中间文件;mv -f $(dot-target).tmp $(dot-target).cmd
:从输出文件重命名为 $(dot-target).cmd。
if_changed函数(uboot)
作用: 打印和执行
cmd_$(1)
,并将cmd_$@ := cmd_$(1)
的内容输入到$(obj)/.$@.cmd
文件中。
分析:由于在顶层Makefile的386行引用scripts/Kbuild.include
, if_changed函数在此文件260行中定义:5 comma := , 14 # Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o 15 dot-target = $(dir $@).$(notdir $@) 20 depfile = $(subst $(comma),_,$(dot-target).d) ...... 14 # Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o 15 dot-target = $(dir $@).$(notdir $@) ...... 237 ifneq ($(KBUILD_NOCMDDEP),1) 238 # Check if both arguments are the same including their order. Result is empty 239 # string if equal. User may override this check using make KBUILD_NOCMDDEP=1 240 arg-check = $(filter-out $(subst $(space),$(space_escape),$(strip $(cmd_$@))), \ 241 $(subst $(space),$(space_escape),$(strip $(cmd_$1)))) 242 else 243 arg-check = $(if $(strip $(cmd_$@)),,1) 244 endif ...... 256 any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^) ...... 260 if_changed = $(if $(strip $(any-prereq) $(arg-check)), \ 261 @set -e; \ 262 $(echo-cmd) $(cmd_$(1)); \ 263 printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
第260行中$(any-prereq)在第256行中定义,
$?
依赖文件列表中被改变过的所有文件,$^
表示所有的依赖文件,所以$(filter-out $(PHONY) $(wildcard $^),$^)
返回的是空字符串。
最终: any-prereq=$? 【依赖文件列表中被改变过的所有文件】
第260行中$(arg-check)在第237-244行中定义,只有在命令行中输入make KBUILD_NOCMDDEP=1
时,执行243行,所以这里执行240行,其中的$(space),$(space_escape)
在8-10行定义。
最终: arg-check = 将 $(cmd_$1) 中所有空格替换成 -SPACE- 后的字符串8 empty := 9 space := $(empty) $(empty) 10 space_escape := _-_SPACE_-_
所以第260行条件成立,最终展开为:
if_changed = @set -e; \ $(echo-cmd) $(cmd_$(1)); \ printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd
$(dot-target)
在5-20行定义,最终: dot-target = $(dir $@).$(notdir $@)
最终:
set -e
:在脚本执行过程中,出现任何命令执行失败,脚本立即退出;$(echo-cmd)
:将$(cmd_$(1))中的'
替换成\'
后打印;$(cmd_$(1))
:执行里面的命令;printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd
:将 cmd_$@ := cmd_$(1) 信息输出到 $(dot-target).tmp 文件中;
filechk 函数(uboot)
作用: 执行
$(filechk_$(1))
命令,并将执行后的结果写入$@
文件中,最后显示filechk函数
内容。
分析:由于在顶层Makefile的386行引用scripts/Kbuild.include
, filechk 函数在此文件56行中定义:36 kecho := : 39 kecho := $($(quiet)kecho) ...... 56 define filechk 57 $(Q)set -e; \ 58 mkdir -p $(dir $@); \ 59 $(filechk_$(1)) < $< > $@.tmp; \ 60 if [ -r $@ ] && cmp -s $@ $@.tmp; then \ 61 rm -f $@.tmp; \ 62 else \ 63 $(kecho) ' UPD $@'; \ 64 mv -f $@.tmp $@; \ 65 fi 66 endef
57行:
set -e
表示在脚本执行过程中,一旦出现任何命令执行失败(返回非零的退出状态码),脚本立即退出。
58行:创建目标所在的目录。
59行:<
表示输入重定向,即从$<
(第一个依赖) 文件中读取输入,然后将结果输出到$@.tmp
文件中(没有自动创建)。
60行:cmp -s
用来比较$@
和$@.tmp
两个文件是否有差异,如果两个文件完全相同,不输出任何信息,不显示错误信息。
61行:由于60行中$@
文件不存在,条件不成立,所以这里不执行。
63行:由36-39行可知,这里为: ' UPD $@';
64行:将$@.tmp
重命名为$@
deprecated 函数(uboot)
作用: (
参数4 != 空
) && (参数1
中没有y
),则输出错误信息,否则什么都不做。
分析:deprecated 函数在顶层Makefile的1066行定义:# 顶层 Makefile 1046 cfg: u-boot.cfg 1053 got = $(foreach cfg,$(1),$($(cfg))) 1056 expect = $(foreach cfg,$(1),y) ...... 1066 define deprecated 1067 @if [ -n "$(strip $(4))" ]; then if [ "$(got)" != "$(expect)" ]; then \ 1068 echo >&2 "===================== WARNING ======================"; \ 1069 echo >&2 "This board does not use $(firstword $(1)) (Driver Model"; \ 1070 echo >&2 "for $(2)). Please update the board to use"; \ 1071 echo >&2 "$(firstword $(1)) before the $(3) release. Failure to"; \ 1072 echo >&2 "update by the deadline may result in board removal."; \ 1073 echo >&2 "See doc/driver-model/migration.rst for more info."; \ 1074 echo >&2 "===================================================="; \ 1075 fi; fi 1076 1077 endef
if [ -n "$(strip $(4))" ]
:当参数4的字符串长度大于0时为真(串非空) ;if [ "$(got)" != "$(expect)" ]
:依次取出参数1中的字符串,当参数1中的字符串中没有y
则为真;>&2
:将错误输出到文件描述为2的文件,其实是标准错误。