1

Assume a target foo.tar, that depends on a list of files foo.files, e.g.

FOO_FILES := $(shell cat foo.files)

foo.tar: foo.files $(FOO_FILES)
    tar -cf foo $(FOO_FILES)

Now suppose that foo.files need to be generated e.g.:

foo.files: foo.files.template
    sed -e "s/@{VERSION}/$(VERSION)/" < $< > $@

It is clear that foo.files depends on foo.files.template, but how can one make sure that FOO_FILES is evaluated after foo.files is generated?

docwhat
  • 11,435
  • 6
  • 55
  • 54
Chen Levy
  • 15,438
  • 17
  • 74
  • 92

3 Answers3

4

Your original rules are correct. Because updating foo.files causes the value of FOO_FILES to become outdated you just need to make sure your Makefile is re-evaluated by gnu make when foo.files has been updated by making your Makefile depend on foo.files:

Makefile : foo.files
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
0

It can't be done in one pass; Make determines which targets must be rebuilt before it actually executes any rule, and in this case the full list of targets doesn't exist until one of the rules is executed.

This should do it:

FOO_FILES := $(shell cat foo.files)

foo.tar: foo.files
    $(MAKE) foo-tarball

.PHONY: foo-tarball
foo-tarball: $(FOO_FILES)
    tar -cf foo $^

EDIT:
As the OP points out, this will not work as written; I left out a prerequisite:

foo.tar: foo.files $(FOO_FILES)
    ...

Note that this will recurse even if foo.files has not changed, which is not strictly necessary; it is possible to correct this, but not elegantly. (For comparison, the selected solution, which I admit is cleaner than mine, recurses even if the target has nothing to do with foo.tar.)

Beta
  • 96,650
  • 16
  • 149
  • 150
  • This doesn't look right. It will work only due to that foo-tarball is .PHONY, but in this case why bother with all the other rules? Moreover the `foo.tar` rule is simply incorrect (one of the files listed in `foo.files` might change when `foo.files` stay the same). Adding insult to injury this Makefile is recursive (which is considered harmful). – Chen Levy Jan 23 '11 at 09:26
  • @Chen Levy: You're right, the rule was incorrect, I have fixed it. In my defense, 1) the other rules are necessary, and 2) Maxim Yegarushkin's solution is also recursive, just in a way that isn't as obvious. (I generally advise people to make up their own minds about recursive make-- it's sometimes necessary, as in this case, and I think more people refer to the "Is Considered Harmful" paper than have actually read it.) – Beta Jan 24 '11 at 06:40
0

So, I found an answer reading about Advanced Auto-Dependency Generation over at mad-scientist.net. Basically, it is possible to re-evaluate a makefile by way of a GNU/Make feature. When there is a rule to generate an included makefile, the entire makefile will be re-read after the generation of the included file. Thus --

# -*- mode: make -*-
VERSION := 1.2.3

foo.tar: foo.files $(FOO_FILES)
    tar cf $@ $(FOO_FILES)

clean:
    rm -f foo.files foo_files.mk foo.tar

foo.files: foo.files.template
    sed -e "s/@{VERSION}/$(VERSION)/" < $< > $@

# -- voodoo start here --
# This will ensure that FOO_FILES will be evaluated only
# *after* foo.files is generated.
foo_files.mk: foo.files
    echo "FOO_FILES := `xargs < $<`" > $@

include foo_files.mk
# -- voodoo ends here --

.PHONY: clean

-- seems to do the right thing.


... and just for completeness:

foo.files.template is:

a-$(VERSION)
b-$(VERSION)

and assume the presence of a-1.2.3 and b-1.2.3.

Chen Levy
  • 15,438
  • 17
  • 74
  • 92