模式规则依赖其他模式规则时执行顺序不符合预期
Make目标执行顺序不符合预期的问题解决
问题背景
我遇到了Make目标执行顺序不符合预期的问题,以下是我的Makefile:
.PHONY: deploy.% deploy.%: DEPLOY_ENV=$* deploy.%: fetch.% publish @echo "[deploy] $(DEPLOY_ENV)" .PHONY: publish publish: @echo "[publish]" .PHONY: fetch.% fetch.%: DEPLOY_ENV=$* fetch.%: @echo "[fetch] $(DEPLOY_ENV)"
执行命令:
make deploy.dev
期望输出
[fetch] dev [publish] [deploy] dev
实际输出
[publish] [fetch] dev [deploy] dev
调试输出(关键片段)
$ make --debug=i deploy.dev ... Found an implicit rule for `deploy.dev'. File `publish' does not exist. Must remake target `publish'. [publish] Successfully remade target file `publish'. File `fetch.dev' does not exist. Must remake target `fetch.dev'. [fetch] dev ...
原因分析
GNU Make处理同一目标的多个依赖时,会优先处理非模式匹配的明确目标,再处理需要通过模式规则生成的目标。在原Makefile中,publish是明确的.PHONY目标,而fetch.%是模式目标,因此Make会先执行publish,再生成并执行fetch.dev。即使依赖列表中fetch.%写在publish前面,由于publish无需模式匹配,Make仍会优先处理它。
解决方案
通过目标特定依赖,让publish仅在作为deploy.%的依赖时,依赖对应的fetch.%目标,从而强制fetch.%在publish之前执行。修改后的Makefile如下:
.PHONY: deploy.% deploy.%: DEPLOY_ENV=$* # 为deploy.%上下文下的publish添加特定依赖 deploy.%: publish: fetch.$(DEPLOY_ENV) deploy.%: publish @echo "[deploy] $(DEPLOY_ENV)" .PHONY: publish publish: @echo "[publish]" .PHONY: fetch.% fetch.%: DEPLOY_ENV=$* fetch.%: @echo "[fetch] $(DEPLOY_ENV)"
执行make deploy.dev后,输出将符合预期:
[fetch] dev [publish] [deploy] dev
更简洁的写法
可以合并依赖定义,让代码更紧凑:
.PHONY: deploy.% deploy.%: DEPLOY_ENV=$* deploy.%: publish @echo "[deploy] $(DEPLOY_ENV)" # 仅当publish作为deploy.%的依赖时,依赖fetch.$* deploy.%: publish: fetch.$* .PHONY: publish publish: @echo "[publish]" .PHONY: fetch.% fetch.%: DEPLOY_ENV=$* fetch.%: @echo "[fetch] $(DEPLOY_ENV)"
内容的提问来源于stack exchange,提问作者mamacdon
相关产品推荐
相关产品推荐

