循环Makefile中父文件夹中的子文件夹



我有一个文件夹,其中包含未知数量的子文件夹。每个子文件夹都包含一个Dockerfile。我想写一个Makefile命令来批量构建以子文件夹命名的所有图像,并相应地对它们进行标记。

我首先从简单的试用开始:

build.all.images:
for f in $(find $(image_folder) -type d -maxdepth 1 -mindepth 1 -exec basename {} ;); do echo $${f}; done

当我使用硬编码的image_folder值单独运行find命令时,子文件夹将成功列出。然而,当我尝试运行make命令时,我只看到下面的输出:

for f in ; do echo ${f}; done

我还尝试使用ls命令与tfcut链接来获得子文件夹的列表,但结果是一样的。

build.all.images:
for f in $(ls -l $(image_folder) | grep '^d' | tr -s ' ' | cut -d ' ' -f 9); do echo $${f}; done

我做错了什么?

在shell执行配方之前,它们会通过make进行扩展。因此,$(find something)被展开,并且由于没有名为find something的make宏,所以它被空字符串替换。将$符号加倍(或使用反勾号(,就像对shell变量f:所做的那样

build.all.images:
for f in $$(find $(image_folder) -type d -maxdepth 1 -mindepth 1 -exec basename {} ;); do echo $${f}; done

但在制作配方中使用for循环通常不是一个好主意。Makefile不是shell脚本。使用您的解决方案(在修复$问题之后(,您将无法从make的威力中获益。Make分析目标和先决条件之间的依赖关系,只重做需要重做的内容。它还具有并行功能,这对加快构建过程非常有用。

这是另一个更实用的解决方案。我改变了一些逻辑,找到Dockerfiles而不是子目录,但如果你喜欢其他方式,它很容易适应。

DOCKERFILES := $(shell find $(image_folder) -type f -name Dockerfile)
TARGETS     := $(patsubst %/Dockerfile,%.done,$(DOCKERFILES))
.PHONY: build.all.images clean
build.all.images: $(TARGETS)
$(TARGETS): %.done: %/Dockerfile
printf 'sub-directory: %s, Dockerfile: %sn' "$*" "$<"
touch $@
clean:
rm -f $(TARGETS)

演示:

$ mkdir -p {a..d}
$ touch {a..d}/Dockerfile
$ make -s -j4 build.all.images
sub-directory: c, Dockerfile: c/Dockerfile
sub-directory: a, Dockerfile: a/Dockerfile
sub-directory: d, Dockerfile: d/Dockerfile
sub-directory: b, Dockerfile: b/Dockerfile

使用这种方法,只有当其Dockerfile自上次构建以来发生更改时,您才能重建映像。图像FOO的最后构建的日期/时间是配方在构建之后创建或触摸的名为FOO.done的空文件的最后修改日期/时间。所以,这是较少的工作要做。

此外,由于静态模式规则相当于要构建的图像的独立规则,make可以并行构建过时的图像。如果您有8个核心,请尝试make -j 8 build.all.images,然后查看。

相关内容

  • 没有找到相关文章

最新更新