[英]Multi-dependency makefile target
The problem I'm experiencing is an all
target has dependencies on others that set a variable, then run matching dependencies. 我遇到的问题是
all
目标都对设置变量的其他目标具有依赖性,然后运行匹配的依赖性。
Outcome - It will run the first dependency then stop. 结果 -它将运行第一个依赖项,然后停止。
Expected - Run both dependencies, setting the variable properly between each run 预期 -运行两个依赖项,并在每次运行之间正确设置变量
Is make
smart enough to see pull
and build
were already ran and the dependency target itself has no execution, therefore it sees all dependencies as complete? make
足够智能以查看是否已经运行pull
和build
并且依赖目标本身没有执行,因此将所有依赖视为完整吗? Or I'm just abusing make
in ways it should not be used? 还是我只是滥用
make
而不应该使用它?
Said makefile
: 说的
makefile
:
repo=rippio
image=default
pull:
@docker pull $(repo)/$(image):latest
build: pull
@sed -e 's/{{repo}}/$(repo)/' -e 's/{{image}}/$(image)/' Dockerfile.in > Dockerfile && \
docker build -t=$(repo)/$(image):custom .
@rm -f Dockerfile
node: image=node
node: | pull build
jdk8: image=jdk8
jdk8: | pull build
all: | node jdk8
It is used to: 它用于:
Pretty handy for customizing images in a generic manner without managing many Dockerfiles
. 在不管理许多
Dockerfiles
情况下以通用方式自定义映像非常方便。
Dockerfile template ( Dockerfile.in
), incase interested: Dockerfile模板(
Dockerfile.in
), Dockerfile.in
感兴趣:
FROM {{repo}}/{{image}}:latest
... super secret sauce
Thanks to @GM , ended up with: 感谢@GM ,最终得到:
IMAGE_NAMES := node jdk8
TARGETS := $(patsubst %,build-%,$(IMAGE_NAMES))
repo=rippio
all: $(TARGETS)
build-%: pull-%
@$sed -e 's/{{repo}}/$(repo)/' -e 's/{{image}}/$*/' Dockerfile.in > Dockerfile-$* && \
$docker build -f=Dockerfile-$* -t=$(repo)/$*:custom .
@rm -f Dockerfile-$*
pull-%:
@$docker pull $(repo)/$*:latest
Which allows for: 这允许:
make -j
(note the Dockerfile-$*
file pattern) make -j
并行运行(注意Dockerfile-$*
文件模式) If you draw your dependency graph out long-hand you'll see that there are multiple paths from all
to both pull
and build
-- one via each of node
and jdk8
. 如果您长期绘制依赖关系图,您会发现从
all
路径到pull
和build
都有多个路径-一个通过node
和jdk8
。 But make
having reached/updated pull
and build
via one path will then assume that they are both up to date and, hence, not bother to update them further -- regardless of any change to target specific variables. 但
make
在达到/更新的pull
和build
通过一个路径,然后将假定它们都是最新的,因此,不必再费心更新它们-无论任何改变针对特定的变量。
I think what you're trying to do (assuming I've understood correctly) might be more easily achieved using pattern rules. 我认为您使用模式规则可以更轻松地实现您想做的事情(假设我理解正确)。
IMAGE_NAMES := node jdk8
TARGETS := $(patsubst %,build-%,$(IMAGE_NAMES))
repo=rippio
all: $(TARGETS)
build-%: pull-%
@$sed -e 's/{{repo}}/$(repo)/' -e 's/{{image}}/$*/' Dockerfile.in > Dockerfile && \
$docker build -t=$(repo)/$*:custom .
@rm -f Dockerfile
pull-%:
@$docker pull $(repo)/$*:latest
Note: You currently have all build
recipes using the same input/output file DockerFile
. 注意:当前,您具有使用相同输入/输出文件
DockerFile
所有build
配方。 That will cause problems if you ever want to use parallel builds -- make -j
etc. It might be wise to use the stem from the pattern rule match to uniquely identify the output file if that's possible. 如果您想使用并行构建(如
make -j
等),那将会引起问题。如果可能的话,使用模式规则匹配的词干来唯一地标识输出文件可能是明智的。
Normally, if you invoke make with: 通常,如果您使用以下命令调用make:
make all
and if none of pull
, build
, node
, jdk8
are existing files, make should build pull
and build
. 并且如果
pull
, build
, node
, jdk8
是现有文件,则make应该构建pull
和build
。 If you see only pull
being made, it can be because you invoke make without specifying a goal. 如果看到仅产生
pull
,则可能是因为您在未指定目标的情况下调用了make。 In this case make builds the first target it finds in the Makefile ( pull
in your case). 在这种情况下化妆建立发现Makefile中的第一个目标(
pull
你的情况)。
Anyway, there are several strange aspects in your Makefile: you use order-only prerequisites on what looks like phony targets and these phony targets are not declared as such. 无论如何,Makefile中有几个奇怪的方面:您对看起来像虚假目标的对象使用仅订购的先决条件,而这些虚假目标并未这样声明。
I am not sure I fully understand what you are trying to do but maybe something like this would be a good starting point: 我不确定我是否完全了解您要做什么,但是也许这样的事情会是一个很好的起点:
repo=rippio
image=default
.PHONY: all build node jdk8
all: node jdk8
node: image = node
jdk8: image = jdk8
build node jdk8:
@docker pull $(repo)/$(image):latest && \
sed -e 's/{{repo}}/$(repo)/' -e 's/{{image}}/$(image)/' Dockerfile.in > Dockerfile && \
docker build -t=$(repo)/$(image):custom . && \
rm -f Dockerfile
Note: if, instead of build
you name the default target default
you could even simplify further with: 注意:如果您不用
build
而是使用默认目标default
名称,则可以使用以下方法进一步简化:
repo=rippio
.PHONY: all default node jdk8
all: node jdk8
default node jdk8:
@docker pull $(repo)/$@:latest && \
sed -e 's/{{repo}}/$(repo)/' -e 's/{{image}}/$@/' Dockerfile.in > Dockerfile && \
docker build -t=$(repo)/$@:custom . && \
rm -f Dockerfile
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.