如何通过目标扩展名控制Makefile命令流?条件判断失效排查
问题原因
你遇到的核心问题是Makefile的条件判断语句(ifneq/ifeq)属于预处理阶段执行的逻辑,而$@、$*这类自动变量是在目标实际执行时才会被替换为对应的值。
在Makefile解析阶段,$(subst .,,$(suffix $@))还没有被替换成具体的扩展名(此时$@是空值),所以filter的结果为空,ifneq条件永远不成立,自然每次都输出nop。
解决方案
有两种可行的解决思路,根据你的需求选择:
方案一:用Shell条件判断(灵活适配多扩展名)
把Makefile的预处理条件换成Shell的条件逻辑,因为Shell命令是在目标执行阶段运行的,此时自动变量已经完成替换:
.PHONY: foo.% foo.%: @echo $* @ext=$(subst .,,$(suffix $@)); \ case $$ext in \ a|b|c) echo 'yep' ;; \ *) echo 'nop' ;; \ esac
或者用grep做匹配:
.PHONY: foo.% foo.%: @echo $* @ext=$(subst .,,$(suffix $@)); \ if printf "%s\n" "a b c" | grep -wq "$$ext"; then \ echo 'yep'; \ else \ echo 'nop'; \ fi
方案二:拆分目标(适合扩展名较少的场景)
如果需要适配的扩展名不多,可以直接拆分目标,分别定义不同的命令:
# 定义所有伪目标 PHONY_TARGETS := foo.a foo.b foo.c foo.d .PHONY: $(PHONY_TARGETS) # 匹配a/b/c扩展名的目标 foo.a foo.b foo.c: @echo $* @echo $(subst .,,$(suffix $@)) @echo 'yep' # 其他扩展名的目标 foo.d: @echo $* @echo $(subst .,,$(suffix $@)) @echo 'nop'
内容的提问来源于stack exchange,提问作者Victor Mattos Dimen
相关产品推荐
相关产品推荐

