曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 6863|回复: 0
打印 上一主题 下一主题

[Kernel] make-cmd,escsq

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34397
跳转到指定楼层
楼主
发表于 2011-7-17 19:49:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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]
运行输出:
$ make
echo '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 时没有问题。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-6-18 04:03 , Processed in 0.060914 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表