英文:
How do I wildcard a rule with SECONDEXPANSION in GNU Make?
问题
# Docker Chain
src_files:=$(shell find src/ -name '*.py')
image_tags=$(shell find dkr/ -name '$(PROJECT).*.dockerfile' | xargs -n 1 basename -s '.dockerfile')
dkr/%.dockerfile: $(src_files)
docker build . -f $@ -t $*
.SECONDEXPANSION:
$(PROJECT).base: dkr/$$@.dockerfile
.SECONDEXPANSION:
$(PROJECT).%: $(PROJECT).base | dkr/$$*.dockerfile
publish-%:
$(MAKE) $*
./scripts/$@.sh $(RESOURCE_PREFIX) $* $(REGION)
publish:
$(foreach tag, $(image_tags), $(MAKE) publish-$(tag))
英文:
# Docker Chain
src_files:=$(shell find src/ -name '*.py')
image_tags=$(shell find dkr/ -name '$(PROJECT).*.dockerfile' | xargs -n 1 basename -s '.dockerfile')
dkr/%.dockerfile: $(src_files)
docker build . -f $@ -t $*
.SECONDEXPANSION:
$(PROJECT).base: dkr/$$@.dockerfile
.SECONDEXPANSION:
$(PROJECT).foo: $(PROJECT).base | dkr/$$@.dockerfile
.SECONDEXPANSION:
$(PROJECT).bar: $(PROJECT).base | dkr/$$@.dockerfile
publish-%:
$(MAKE) $*
./scripts/$@.sh $(RESOURCE_PREFIX) $* $(REGION)
publish:
$(foreach tag, $(image_tags), $(MAKE) publish-$(tag))
I would like to write the above as:
# Docker Chain
src_files:=$(shell find src/ -name '*.py')
image_tags=$(shell find dkr/ -name '$(PROJECT).*.dockerfile' | xargs -n 1 basename -s '.dockerfile')
dkr/%.dockerfile: $(src_files)
docker build . -f $@ -t $*
.SECONDEXPANSION:
$(PROJECT).base: dkr/$$@.dockerfile
.SECONDEXPANSION:
$(PROJECT).%: $(PROJECT).base | dkr/$$@.dockerfile
publish-%:
$(MAKE) $*
./scripts/$@.sh $(RESOURCE_PREFIX) $* $(REGION)
publish:
$(foreach tag, $(image_tags), $(MAKE) publish-$(tag))
However, the wildcarding in the rule (via '%') does not work. I suppose I have misunderstood rule substitution, and am guessing it is due to the SECONEXPANSION
.
But, my make
intuition is telling me this should work, and it should be good.
How would I perform substitution in this scenario?
答案1
得分: 0
代码上的问题出在上面,而不是“其他地方”。此外,你对.SECONDEXPANSION
的应用是正确的;问题不在那里。在这里:
在Makefile中,你可以有一个依赖规范,而不需要为其提供任何配方,就像你的第一个例子中一样:
$(PROJECT).foo: $(PROJECT).base | dkr/$$@.dockerfile
但是,如果你尝试使用模式(%
)来创建这样的依赖关系(没有配方),你就无法实现(Make使用这样的东西来表示其他东西)。要创建“模式规则”,你必须提供一个配方。如果你实际上没有一个配方,那就提供虚拟的配方,即在依赖关系行之后加上分号。
所以
$(PROJECT).%: $(PROJECT).base | dkr/$$@.dockerfile ;
这将解决你的问题。
顺便说一下,我不明白为什么你需要那些“顺序前提条件”(在|
之后)。它们用于防止目标仅因为先决条件更新而重新构建。由于这些目标没有配方,因此没有必要设置顺序前提条件。所以只需执行
$(PROJECT).%: $(PROJECT).base dkr/$$@.dockerfile ;
英文:
The problem is in the code above, not "elsewhere". Also, your application of .SECONDEXPANSION
is correct; the problem is not there. It is here:
You can have a dependency specification in a makefile, without any recipe to it, like in your first example:
$(PROJECT).foo: $(PROJECT).base | dkr/$$@.dockerfile
But, if you try to have such a dependency (without a recipe), with a pattern (%
), you can't (Make uses such a thing for something else). To have a "pattern rule", you must supply a recipe. If you don't really have a recipe, then supply the dummy recipe, which is a semicolon after the dependency line.
So
$(PROJECT).%: $(PROJECT).base | dkr/$$@.dockerfile ;
and that will solve your problem.
By the way, I don't see why you need those "order prerequisites" (after the |
). They are used to prevent the target from rebuilding solely because the prerequisite is newer. Since these targets do not have a recipe, there is no point in having order prerequisites. So just do
$(PROJECT).%: $(PROJECT).base dkr/$$@.dockerfile ;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论