Makefile foreach

时间:2015-03-25 23:01:26

标签: makefile gnu-make

我正在尝试创建一个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以来,已经有好几年了。我通常使用另一个构建工具,但是需要修改该构建工具以使其在此处执行我想要的操作。所以我以为我会在此期间鞭打它。它有点比预期的更难。

1 个答案:

答案 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可以同时 ,将下载时间减半。