|
Makefile 对应内核版本:2.6.35.13
escsq 和 make-cmd 定义在 scripts/Kbuild.include 中:
escsq:
[code=Makefile]
squote := '
###
# Escape single quote for use in echo statements
escsq = $(subst $(squote),'\$(squote)',$1)
[/mw_shl_code]
make-cmd:
[code=Makefile]
# >'< substitution is for echo to work,
# >$< substitution to preserve $ when reloading .cmd file
# note: when using inline perl scripts [perl -e '...$$t=1;...']
# in $(cmd_xxx) double $$ your perl vars
make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))[/mw_shl_code]
上面 $(cmd_$(1)) 表示编译某个目标时所用的编译命令。
escsq 函数用来取消在 echo 中使用含有单引号的语句引起的解析错误。比如有下面的 Makefile:
[code=Makefile]cmd = It's a good idea
all:
echo '$(cmd)'[/mw_shl_code]
运行输出:
$ makeecho 'It's a good idea'
/bin/sh: -c: line 0: unexpected EOF while looking for matching `''
/bin/sh: -c: line 1: syntax error: unexpected end of file
make: *** [all] Error 1 由于 $(cmd) 变量中含有单引号,那么如果直接在 echo 中展开该变量时,就会造成单引号不配对,使解析器不知道该再哪结束该 echo 语句,从而出错。
下面使用 escsq 函数来消除上述错误:
[code=Makefile]
squote := '
escsq = $(subst $(squote),'\$(squote)',$1)
cmd = It's a good idea
all:
echo '$(call escsq,$(cmd))'[/mw_shl_code]
运行输出:[beyes@beyes escsq]$ make
echo 'It'\''s a good idea'
It's a good idea
在 make-cmd 中,subst \#,\\\#, 用来保留命令中的 '\#' 符号。比如在编译 cmd_init/calibrate.o 这个目标中有一个命令片段为:-D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(calibrate)" 在 subst \#,\\\# 中,\# 中的反斜线表示取原本的 # 符号;\\\# 中的前 2 个反斜线表示取原本 '\' 符号,然后 \# 表示取原本的 # 符号,这样综合起来就是将 # 符号替换为 \# 。比较下面例子:
[code=Makefile]
make-cmd = $(subst \#,\\\#,$(string1))
string1 := -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(calibrate)"
all:
echo '$(make-cmd)'
echo '$(subst \#,\\\#,$(string1))'
echo '$(string1)'
echo '-D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(calibrate)"'
[/mw_shl_code]
运行输出:$ make
echo '-D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(calibrate)"'
-D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(calibrate)"
echo '-D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(calibrate)"'
-D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(calibrate)"
echo '-D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(calibrate)"'
-D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(calibrate)"
echo '-D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(calibrate)"'
-D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(calibrate)" 上面的输出中,第 1 条和第 4 条是正确的输出,第 2 条和第 3 条是错误的输出(遗漏了 '\' 符号)。
第 4 条输出正确是因为在 echo 中单引号对里的所有的字符都按照它们自身模样输出,反斜线符号不具有转义功能。
在第 2 条和第 3 条的错误中:
当 echo '$(string1)' 时,因为 echo 认为 $(string1) 中的 \# 反斜线还未经过转义,所以先将其转义,因此转以后只剩下 # 符号。
当 echo '$(subst \#,\\\#,$(string1))' 时,同样 echo 认为$(string1) 中的 \# 反斜线还未经过转义,所以先将其转义,转以后只剩下 # 符号;这样一来,subst 函数里首先检测 $(string1) 中是否含有 \# 时自然是检测不到,所以替换到 \\\# 这种行为也不会发生,从而导致替换失败。
第 1 条是成功的,因为 $(make-cmd) 变量是事先由 $(subst \#,\\\#,$(string1)) 转义好再赋值的,所以最后在 echo 时没有问题。 |
|