使用 m4 构建 Dockerfiles 的 Makefile 未重建
Makefile using m4 to build Dockerfiles is not rebuilding
我有 6 个不同的 Dockerfile,它们看起来非常相似,所以我使用 m4 和 include 从片段构建它们。
我不太了解将 Makefile 用于 C++ 以外的目的,并且我遇到了一个问题,即当 m4 文件更改时 make 不会重建,除非目标更改,否则不会 运行 迭代复制操作。
请提供一些关于更好做法的意见和帮助?
参见:https://github.com/ptr727/NxWitness/tree/master/Make
.DEFAULT_GOAL := check
# Even if the m4 files changed make still reports up to date?
INPUTS = $(wildcard ${CURDIR}/*.m4)
OUTPUTS = $(addsuffix .dockerfile, $(basename $(INPUTS)))
# Why does the output look funky?
TARGETS = $(abspath ${CURDIR}/..)/$(basename $(notdir $(INPUTS)))/Dockerfile
%.dockerfile : %.m4
m4 $< > $@
check:
@echo "INPUTS = $(INPUTS)"
@echo "OUTPUTS = $(OUTPUTS)"
@echo "TARGETS = $(TARGETS)"
create: $(OUTPUTS)
clean:
-rm *.dockerfile $(OUTPUTS)
# Why does make report up to date even after clean?
# $(foreach file, $(OUTPUTS), $(cp $(file) $(abspath ${CURDIR}/..)/$(basename $(notdir $(file)))/Dockerfile))
replace:
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
build:
docker build -f ../DWSpectrum/Dockerfile ../DWSpectrum
docker build -f ../DWSpectrum-LSIO/Dockerfile ../DWSpectrum-LSIO
docker build -f ../NxWitness/Dockerfile ../NxWitness
docker build -f ../NxWitness-LSIO/Dockerfile ../NxWitness-LSIO
docker build -f ../NxMeta/Dockerfile ../NxMeta
docker build -f ../NxMeta-LSIO/Dockerfile ../NxMeta-LSIO
在您的 Docker 文件中,您有 build
和 replace
等与真实文件不对应的 Make 目标。那些将始终被认为是过时的并且需要重建,即使他们的输入没有改变。 (在 GNU Make 中,将它们标记为 .PHONY:
是一种很好的做法。)
如果你有一些任务,比如构建一个 Docker 图像,它不会直接自己生成一个文件,一个有用的技术是放置某种 "marker" 文件来记录它完成了。完成任务后,touch
标记文件。如果它的输入之一发生变化,它将比标记文件更新,并导致 Docker 重建文件。
%/.docker-build: %/Dockerfile
docker build $(dir $@)
touch "$@"
您可以使用类似的模式语法从 m4 文件生成 Docker 文件。 (这几乎与您上面的规则完全相同,但目标不同。)
%/Dockerfile: %.m4
m4 $< >$@
如果您有目录列表
DIRS := DWSpectrum DWSpectrum-LSIO NxWitness NxWitness-LSIO NxMeta NxMeta-LSIO
那么你可以让 "build" 目标只依赖于标记文件
.PHONY: build
build: $(DIRS:%=%/.docker-build)
和 "clean" 规则应该清除我们生成的所有内容
.PHONY: clean
clean:
rm -f $(DIRS:%=%/.docker-build)
rm -f $(DIRS:%=%/Dockerfile)
我在这里使用了两种语法来替换您的函数调用和 foreach
循环。构建规则时,如果%
在规则的两边,可以用相同的字符串代替,组成pattern rule; Make knows that DWSpectrum/.docker-build
can be built from DWSpectrum/Dockerfile
via this rule. $(DIRS:%=%/Dockerfile)
is a substitution reference;对于 $(DIRS)
中与模式 %
匹配的每个项目(即每个项目),将其替换为匹配的字符串加上 /Dockerfile
后缀。
我有 6 个不同的 Dockerfile,它们看起来非常相似,所以我使用 m4 和 include 从片段构建它们。
我不太了解将 Makefile 用于 C++ 以外的目的,并且我遇到了一个问题,即当 m4 文件更改时 make 不会重建,除非目标更改,否则不会 运行 迭代复制操作。
请提供一些关于更好做法的意见和帮助?
参见:https://github.com/ptr727/NxWitness/tree/master/Make
.DEFAULT_GOAL := check
# Even if the m4 files changed make still reports up to date?
INPUTS = $(wildcard ${CURDIR}/*.m4)
OUTPUTS = $(addsuffix .dockerfile, $(basename $(INPUTS)))
# Why does the output look funky?
TARGETS = $(abspath ${CURDIR}/..)/$(basename $(notdir $(INPUTS)))/Dockerfile
%.dockerfile : %.m4
m4 $< > $@
check:
@echo "INPUTS = $(INPUTS)"
@echo "OUTPUTS = $(OUTPUTS)"
@echo "TARGETS = $(TARGETS)"
create: $(OUTPUTS)
clean:
-rm *.dockerfile $(OUTPUTS)
# Why does make report up to date even after clean?
# $(foreach file, $(OUTPUTS), $(cp $(file) $(abspath ${CURDIR}/..)/$(basename $(notdir $(file)))/Dockerfile))
replace:
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
build:
docker build -f ../DWSpectrum/Dockerfile ../DWSpectrum
docker build -f ../DWSpectrum-LSIO/Dockerfile ../DWSpectrum-LSIO
docker build -f ../NxWitness/Dockerfile ../NxWitness
docker build -f ../NxWitness-LSIO/Dockerfile ../NxWitness-LSIO
docker build -f ../NxMeta/Dockerfile ../NxMeta
docker build -f ../NxMeta-LSIO/Dockerfile ../NxMeta-LSIO
在您的 Docker 文件中,您有 build
和 replace
等与真实文件不对应的 Make 目标。那些将始终被认为是过时的并且需要重建,即使他们的输入没有改变。 (在 GNU Make 中,将它们标记为 .PHONY:
是一种很好的做法。)
如果你有一些任务,比如构建一个 Docker 图像,它不会直接自己生成一个文件,一个有用的技术是放置某种 "marker" 文件来记录它完成了。完成任务后,touch
标记文件。如果它的输入之一发生变化,它将比标记文件更新,并导致 Docker 重建文件。
%/.docker-build: %/Dockerfile
docker build $(dir $@)
touch "$@"
您可以使用类似的模式语法从 m4 文件生成 Docker 文件。 (这几乎与您上面的规则完全相同,但目标不同。)
%/Dockerfile: %.m4
m4 $< >$@
如果您有目录列表
DIRS := DWSpectrum DWSpectrum-LSIO NxWitness NxWitness-LSIO NxMeta NxMeta-LSIO
那么你可以让 "build" 目标只依赖于标记文件
.PHONY: build
build: $(DIRS:%=%/.docker-build)
和 "clean" 规则应该清除我们生成的所有内容
.PHONY: clean
clean:
rm -f $(DIRS:%=%/.docker-build)
rm -f $(DIRS:%=%/Dockerfile)
我在这里使用了两种语法来替换您的函数调用和 foreach
循环。构建规则时,如果%
在规则的两边,可以用相同的字符串代替,组成pattern rule; Make knows that DWSpectrum/.docker-build
can be built from DWSpectrum/Dockerfile
via this rule. $(DIRS:%=%/Dockerfile)
is a substitution reference;对于 $(DIRS)
中与模式 %
匹配的每个项目(即每个项目),将其替换为匹配的字符串加上 /Dockerfile
后缀。