为何setlocal EnableDelayedExpansion在Windows下Makefile中不生效?
mingw32-make中setlocal EnableDelayedExpansion不生效的原因及解决办法
原因
Makefile默认会为每一行命令启动独立的cmd.exe进程执行。你写的setlocal EnableDelayedExpansion仅在它所在的那一行进程中生效,后续的set foo=hello和echo命令都是在新的cmd.exe进程里运行,这些新进程并没有开启延迟扩展,同时%foo%也因为新进程未定义该变量而无输出,最终只打印出未被解析的!foo!。
解决办法
1. 合并命令到同一行
用&分隔所有命令,让它们在同一个cmd.exe进程中执行:
SHELL := cmd.exe target: setlocal EnableDelayedExpansion & set foo=hello & echo !foo! %foo%
执行后会输出hello %foo%——!foo!通过延迟扩展拿到变量值,%foo%是即时扩展,在命令执行前就被解析(此时foo还未定义),所以保留原符号。
2. 使用define定义多行命令
通过Makefile的define语法将命令打包,确保它们在同一个shell进程中运行:
SHELL := cmd.exe define RUN_CMD setlocal EnableDelayedExpansion set foo=hello echo !foo! %foo% endef target: $(RUN_CMD)
这种方式下,define块内的所有命令会被传递给同一个cmd.exe进程,延迟扩展正常生效,输出结果和第一种方法一致。
3. 单独编写.cmd脚本
把需要执行的命令放到独立的.cmd脚本中,再在Makefile里调用该脚本:
创建script.cmd文件:
setlocal EnableDelayedExpansion set foo=hello echo !foo! %foo%
修改Makefile:
SHELL := cmd.exe target: script.cmd
脚本内的所有命令都在同一个shell进程执行,延迟扩展功能正常工作。
内容的提问来源于stack exchange,提问作者Time Killer
相关产品推荐
相关产品推荐

