Reputation: 38879
I'm trying to create a makefile which downloads some pre-requisite files to a path.
But the foreach documentation is sadly lacking in detail and examples.
I want something like:
image_files = a b
image_versions = 701.2 802.1
image_path = images
images = $(foreach ...) ??
I'd like that to result in an expansion to:
images/701.2/a
images/701.2/b
images/802.1/a
images/802.1/b
And have a phony target to download them from a URL like:
mytarget: $(images)
wget somepath $<
How do I do that?
Ok I have gotten a little further with this. But I'm still a little perplexed as to how I can get this to work.
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
How do you do this?
In fact I only want it to download the images if they aren't there. But for some reason it downloads it every time. It's literally been years since I used Make. I normally use another build tool, but that build tool needs to be modified to make it do what I want here. So I thought I'd just whip this up in the meantime. It's prooving to be a little harder than expected.
Upvotes: 1
Views: 5242
Reputation: 15483
You are pretty close, but the problem does not lie with foreach
. Let's have a look at just the bit that does the downloading. When make reads the makefile it ends up with something like (after shortening the names a bit for clarity):
images/1/file.cpio.gz images/2/file.cpio.gz:
<recipe>
If, for some reason, make decides to rebuild images/1/file.cpio.gz
say, at this point it will expand the recipe, and pass each line of that expansion to a separate shell.
Your job is to write a recipe that does not care whether the target is images/1/file.cpio.gz
or images/2/file.cpio.gz
. That's another way of saying the recipe should use macros like $@
(it will expand to the target).
A sketch:
${images_a}:
wget -O $@ http://stable.release.core-os.net/amd64-usr/$@
You may have to munge $@
so that wget gets the right url. Just one example:
${images_a}:
wget -O $@ http://stable.release.core-os.net/$(dirname $@)/deeper/$(notdir $@)
One complaint about your original makefile: the dependencies are wrong. build
needs the downloads to have completed before it runs.
.PHONY: build
build: $(images_a) $(images_b)
...
The images are not phony (just ensure you don't lie to make abut their filenames) either.
The massive advantage of writing your makefile in this way is that it's parallel safe (and that's the whole point of make). When -j
is in force, both wgets can proceed at the same time, halving the download time.
Upvotes: 3