Makefile中Shell函数调用引发递归问题求助
问题分析与解决
1. 「REV: command not found」错误的原因
你用!=时犯了Makefile基础语法错误:!=是GNU Make的变量赋值语法,不属于shell命令,不能用tab缩进。你把REV != ...写在了compile:规则下缩进的位置,Make会把它当成shell命令执行,而shell自然找不到REV这个命令。
正确写法是把赋值行放在规则下但不要缩进(和规则顶格对齐):
compile: REV != $(REVTOOL) -r $(BASEPARM) $(LIBPARM) $(EXTPARM) $(SUBPARM) @echo "REV的值是: $(REV)"
2. 递归进程爆炸的原因
你用$(eval REV := $(shell ...))时出现递归,大概率是因为revtool的输出包含Make的特殊语法字符(比如$开头的变量/函数)。
当Make执行$(shell)获取revtool输出后,会把输出内容作为REV变量的值,同时自动解析内容里的Make语法(比如$foo会被当成变量展开)。如果输出里的特殊语法刚好触发了compile规则的重新执行(比如展开了和当前目标相关的自动变量),就会导致Make反复调用自己和revtool,形成递归爆炸。
而去掉-S "$(SUB_NAMES)"后,revtool的输出不再包含这些特殊字符,递归也就停止了。
3. 可行的解决方法
方法一:转义输出中的特殊字符
在调用revtool时,用sed把输出里的$转义成\$,让Make无法解析这些特殊语法:
compile: $(eval REV := $(shell $(REVTOOL) -r $(BASEPARM) $(LIBPARM) $(EXTPARM) $(SUBPARM) | sed 's/\$$/\\$$/g'))
方法二:用文件中转避免直接解析
把revtool的输出写入临时文件,再用Make的$(file)函数读取($(file)会原样读取内容,不解析Make语法):
compile: $(REVTOOL) -r $(BASEPARM) $(LIBPARM) $(EXTPARM) $(SUBPARM) > .rev_temp $(eval REV := $(file < .rev_temp)) @rm -f .rev_temp # 后续使用$(REV)的逻辑
方法三:修正!=的用法(推荐)
用!=赋值时不要缩进,同时如果输出有特殊字符,可以结合转义:
compile: REV != $(REVTOOL) -r $(BASEPARM) $(LIBPARM) $(EXTPARM) $(SUBPARM) | sed 's/\$$/\\$$/g' @echo "REV的值是: $(REV)"
内容的提问来源于stack exchange,提问作者Volker
相关产品推荐
相关产品推荐

