生成文件 foreach

Makefile foreach

我正在尝试创建一个 makefile,它将一些先决条件文件下载到某个路径。

但遗憾的是 foreach documentation 缺少详细信息和示例。

我想要这样的东西:

image_files = a b
image_versions = 701.2 802.1
image_path = images
images = $(foreach ...) ??

我希望扩展到:

images/701.2/a
images/701.2/b
images/802.1/a
images/802.1/b

并且有一个虚假目标可以从 URL 下载它们,例如:

mytarget: $(images)
wget somepath $<

我该怎么做?


好的,我已经更进一步了。但我仍然对如何让它发挥作用感到困惑。

tag = my-registry:8443/boot-server-data
versions = 557.0.0 607.0.0

images_a = $(foreach ver, $(versions), images/$(ver)/coreos_production_pxe_image.cpio.gz)
images_b = $(foreach ver, $(versions), images/$(ver)/coreos_production_pxe.vmlinuz)

all: build
.PHONY: build $(images_a) $(images_b)

build:
        ./make-profiles
        docker build -t $(tag) .
        docker push $(tag) 

$(images_a): 
        wget http://stable.release.core-os.net/amd64-usr/$(foreach version... but depends on each image)/coreos_production

你是怎么做到的?

事实上,我只希望它下载不存在的图像。但出于某种原因,它每次都会下载它。我使用 Make 已经有好几年了。我通常使用另一个构建工具,但需要修改该构建工具以使其执行我在这里想要的操作。所以我想我会同时鞭打它。事实证明比预期的要难一些。

你很接近,但问题不在于foreach。让我们看一下执行下载的部分。当 make 读取 makefile 时,它​​以类似的方式结束(为了清楚起见,稍微缩短了名称):

images/1/file.cpio.gz images/2/file.cpio.gz:
    <recipe>

如果,由于某种原因,make 决定重建 images/1/file.cpio.gz 说,此时它将扩展配方,并将该扩展的每一行传递给分开 shell.

你的工作是编写一个不关心目标是 images/1/file.cpio.gz 还是 images/2/file.cpio.gz 的食谱。这是另一种说法,说明配方应该使用像 $@ 这样的宏(它将扩展到目标)。

草图:

${images_a}:
    wget -O $@ http://stable.release.core-os.net/amd64-usr/$@

您可能需要修改 $@ 以便 wget 获得正确的 url。举个例子:

${images_a}:
    wget -O $@ http://stable.release.core-os.net/$(dirname $@)/deeper/$(notdir $@)

关于您的原始 makefile 的一个抱怨:​​依赖关系是错误的。 build 需要下载完成才能运行。

.PHONY: build

build: $(images_a) $(images_b)
    ...

这些图像也不是假的(只要确保你不会在文件名附近 make 撒谎)。

以这种方式编写 makefile 的巨大优势在于它是并行安全的(这就是 makewhole 点)。当-j生效时,两个wgets可以同时进行,下载时间减半