简体   繁体   English

多依赖makefile目标

[英]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足够智能以查看是否已经运行pullbuild并且依赖目标本身没有执行,因此将所有依赖视为完整吗? 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

TLDR TLDR

It is used to: 它用于:

  1. Pull the latest docker image 拉最新的Docker映像
  2. Run a generically designed Dockerfile against it to customize it 针对它运行通用设计的Dockerfile以对其进行自定义
  3. Tag it as :custom for internal use 标记为:custom供内部使用

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

UPDATE (ANSWER) 更新(答案)

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: 这允许:

  • Easy upkeep of 'all' targets, which constantly grows 轻松维护“所有”目标,并且不断增长
  • Running parallel via make -j (note the Dockerfile-$* file pattern) 通过make -j并行运行(注意Dockerfile-$*文件模式)
  • Much more beautiful than before 比以前漂亮得多

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路径到pullbuild都有多个路径-一个通过nodejdk8 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在达到/更新的pullbuild通过一个路径,然后将假定它们都是最新的,因此,不必再费心更新它们-无论任何改变针对特定的变量。

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 . 并且如果pullbuildnodejdk8是现有文件,则make应该构建pullbuild 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM