通过Makefile生成Tcl文件时内容未按预期更新的问题求助
Makefile生成Tcl文件时变量为空的问题解决
问题场景
我编写了一个包含生成Tcl文件目标的Makefile,期望通过Makefile更新Tcl文件内容,但执行后未达到预期:
- abc.mk中定义变量:
FILE_ARGS = select[file_tpye=txt] - Makefile核心代码如下:
.SILENT: include ./abc.mk FILE_ARGS_NEW = $(shell echo $(FILE_ARGS) | sed 's/\[/\\[;s/\]/\\]/') FILE_TCL="\ set FILE_ARGS_NEW \"$(FILE_ARGS_NEW)\" \n \ ... all: def.tcl def.tcl : echo -e $(FILE_TCL) > def.tcl
执行make all后,def.tcl中FILE_ARGS_NEW的值为空,而预期应该是select\\[file_tpye=txt\\]。
问题原因
Makefile中[和]属于通配符字符,当解析$(FILE_ARGS)时,会将其当作文件名匹配规则去查找当前目录的文件。由于没有匹配的文件,$(FILE_ARGS)被展开为空字符串,后续的sed处理自然也得不到有效结果。
解决方案
方案1:使用Makefile内置函数处理转义(推荐)
通过$(value)获取变量原始值(避免通配符展开),再用subst函数直接转义括号,无需调用shell,更高效:
.SILENT: include ./abc.mk # 获取变量原始值,跳过通配符匹配 FILE_ARGS_RAW = $(value FILE_ARGS) # 依次转义[和] FILE_ARGS_NEW = $(subst ],\\],$(subst [,\\[,$(FILE_ARGS_RAW))) FILE_TCL = "\ set FILE_ARGS_NEW \"$(FILE_ARGS_NEW)\" \n \ " all: def.tcl def.tcl : echo -e $(FILE_TCL) > def.tcl
方案2:通过shell命令处理(需注意引号包裹)
如果依赖shell处理,需要先确保变量原始值被正确传递给shell,避免Makefile展开通配符:
.SILENT: include ./abc.mk # 用$(value)传递原始值,并用单引号包裹避免shell解析 FILE_ARGS_NEW = $(shell echo '$(value FILE_ARGS)' | sed 's/\[/\\[/g; s/\]/\\]/g') FILE_TCL = "\ set FILE_ARGS_NEW \"$(FILE_ARGS_NEW)\" \n \ " all: def.tcl def.tcl : echo -e $(FILE_TCL) > def.tcl
验证效果
执行make all后,def.tcl的内容会符合预期:
set FILE_ARGS_NEW "select\\[file_tpye=txt\\]"
内容的提问来源于stack exchange,提问作者kcv9712
相关产品推荐
相关产品推荐

