我正在尝试创建一个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
并且有一个虚假目标可以从以下网址下载它们:
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以来,已经有好几年了。我通常使用另一个构建工具,但是需要修改该构建工具以使其在此处执行我想要的操作。所以我以为我会在此期间鞭打它。它有点比预期的更难。
答案 0 :(得分:1)
你非常接近,但问题不在于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 获取正确的网址。只举一个例子:
${images_a}:
wget -O $@ http://stable.release.core-os.net/$(dirname $@)/deeper/$(notdir $@)
关于原始makefile的一个抱怨:依赖项是错误的。 build
需要在运行之前完成下载。
.PHONY: build
build: $(images_a) $(images_b)
...
图像不是虚假的(只是确保你不要谎言使与文件名相邻)。
以这种方式编写makefile的巨大优势在于它是并行安全的(这是 make 的整个点)。当-j
生效时,两个wgets可以同时 ,将下载时间减半。