使用m4生成DockerFile的Makefile未重建

使用m4生成DockerFile的Makefile未重建,docker,makefile,m4,Docker,Makefile,M4,我有6个不同的DockerFile,它们看起来非常相似,所以我使用m4和include从代码片段构建它们 我不太了解使用MaFfile的目的,除了C++之外,当M4文件改变时,我不存在重建的问题,除非目标改变,否则不运行迭代复制操作。 请提供一些关于更好实践的意见和帮助 见: 。默认目标:=检查 #即使m4文件已更改,是否仍使报告保持最新? 输入=$(通配符${CURDIR}/*.m4) 输出=$(addsuffix.dockerfile,$(basename$(输入))) #为什么输出看起来很

我有6个不同的DockerFile,它们看起来非常相似,所以我使用m4和include从代码片段构建它们

我不太了解使用MaFfile的目的,除了C++之外,当M4文件改变时,我不存在重建的问题,除非目标改变,否则不运行迭代复制操作。 请提供一些关于更好实践的意见和帮助

见:

。默认目标:=检查
#即使m4文件已更改,是否仍使报告保持最新?
输入=$(通配符${CURDIR}/*.m4)
输出=$(addsuffix.dockerfile,$(basename$(输入)))
#为什么输出看起来很时髦?
目标=$(abspath${CURDIR}/)/$(basename$(notdir$(输入)))/Dockerfile
%.dockerfile:%.m4
m4$<>$@
检查:
@echo“输入=$(输入)”
@echo“输出=$(输出)”
@echo“目标=$(目标)”
创建:$(输出)
清洁:
-rm*.dockerfile$(输出)
#为什么即使在清洁后也要更新报告?
#$(foreach文件,$(输出),$(cp$(文件)$(abspath${CURDIR}/)/$(basename$(notdir$(文件)))/Dockerfile))
替换:
cp DWSpectrum.dockerfile../DWSpectrum/dockerfile
cp DWSpectrum-LSIO.dockerfile../DWSpectrum LSIO/dockerfile
cp NxWitness.dockerfile../NxWitness/dockerfile
cp NxWitness-LSIO.dockerfile../NxWitness LSIO/dockerfile
cp NxMeta.dockerfile../NxMeta/dockerfile
cp NxMeta-LSIO.dockerfile../NxMeta LSIO/dockerfile
建造:
docker构建-f../DWSpectrum/Dockerfile../DWSpectrum
docker构建-f../DWSpectrum LSIO/Dockerfile../DWSpectrum LSIO
docker构建-f../NxWitness/Dockerfile../NxWitness
docker构建-f../NxWitness LSIO/Dockerfile../NxWitness LSIO
docker构建-f../NxMeta/Dockerfile../NxMeta
docker构建-f../NxMeta LSIO/Dockerfile../NxMeta LSIO

在Dockerfile中,您创建了与实际文件不对应的目标,如
构建
替换
。即使它们的输入没有改变,它们也总是被认为过时了,需要重建。(在GNU Make中,将它们标记为
.PHONY:
是一种很好的做法。)

如果你有一些任务,比如建立一个Docker镜像,它本身不会直接生成一个文件,一个有用的技术是放置一些“标记”文件来记录它的完成。完成任务后,
触摸标记文件。如果其中一个输入已更改,它将显示为比标记文件更新,并将导致Docker重新生成该文件

%/.docker-build: %/Dockerfile
        docker build $(dir $@)
        touch "$@"
您可以使用类似的模式语法从m4文件生成DockerFile。(这几乎就是上面的规则,但目标不同。)

然后,您可以让“构建”目标仅依赖于标记文件

.PHONY: build
build: $(DIRS:%=%/.docker-build)
“干净”规则应该清理我们产生的一切

.PHONY: clean
clean:
        rm -f $(DIRS:%=%/.docker-build)
        rm -f $(DIRS:%=%/Dockerfile)

我在这里使用了两种语法来替换函数调用和
foreach
循环。在构建规则时,如果
%
位于规则的两侧,则可以将其替换为相同的字符串以生成规则;Make知道可以通过此规则从
DWSpectrum/Dockerfile
生成
DWSpectrum/.docker build
<代码>$(目录:%=%/Dockerfile)
是一个;对于
$(DIRS)
中匹配模式
%
(即每个项目)的每个项目,将其替换为匹配的字符串加上
/Dockerfile
后缀。

谢谢,您的方法使用预定义的目录名,而不是迭代所有m4文件并基于m4文件创建输出目录,你能举个例子吗?我确实让你的版本正常工作了,但是我不得不在目录名前加上../因为目录是一级目录。对于docker build现在所在的位置,我不清楚如何-t标记该构建,以便以后可以在clean docker image rm中标记该图像?在运行
docker build
的规则中,(GNU)Make变量
$*
应该具有包含
docker文件的目录的名称,或
$@
将是戳记文件的名称;您可以根据需要操纵这些命令来构建
docker build-t
选项。如果需要,可以使用现有的
wildcard
调用来查找目录名,例如
DIRS:=$(subst.m4,,$(wildcard*.m4))
DIRS := DWSpectrum DWSpectrum-LSIO NxWitness NxWitness-LSIO NxMeta NxMeta-LSIO
.PHONY: build
build: $(DIRS:%=%/.docker-build)
.PHONY: clean
clean:
        rm -f $(DIRS:%=%/.docker-build)
        rm -f $(DIRS:%=%/Dockerfile)