'Preserving order of prerequisites in $^ in GNU make
Given this makefile
.SUFFIXES: .mmd .tmp .html
a.html : h.tmp a.tmp
b.html : h.tmp b.tmp
c.html : h.tmp c.tmp C.tmp
.tmp.html:
cat $^ > $@
.mmd.tmp:
Markdown.pl $< > $@
where h.mmd is a header to be inserted at the start of each html file.
The command make ?.html produces this
$ touch h.mmd
$ make ?.html
Markdown.pl h.mmd > h.tmp
cat a.tmp h.tmp > a.html
cat b.tmp h.tmp > b.html
cat c.tmp h.tmp C.tmp > c.html
The prerequisites have been sorted alphabetically. Can I preserve the order specified in the dependency lines so that the cat command includes each part in the specified order?
Solution 1:[1]
It doesn't have anything to do with alphabetical order or sorting. The prerequisites are not sorted and the value of $^ is not rearranged, with one exception:
In all implicit rules the implicit dependency is always the first element in the prerequisite list, regardless of whether you added it later as an explicit prerequisite in a different location.
It might be simpler to see if you convert your suffix rule into a pattern rule (but both work the same): A suffix rule like:
.tmp.html: ; cmd
is the same thing as a pattern rule like:
%.html: %.tmp ; cmd
So if you have:
%.html: %.tmp ; @echo $^
c.html : d.tmp b.tmp c.tmp a.tmp
because the pattern match for a target c.html is c, the matching prerequisite c.tmp will always be the first prerequisite even though they're listed in different order in the explicit prerequisites list. So the output of this will be:
c.tmp d.tmp b.dmp a.tmp
Note: not sorted, but the matching prerequisite appears first.
There is no way to "turn this off". The only solution, as suggested by @RedGrittyBrick, is to not list the prerequisite pattern at all. You can use their idea of:
%.html: ; @echo $^
c.html : d.tmp b.tmp c.tmp a.tmp
Or continue to use a suffix rule like:
.html: ; @echo $^
c.html : d.tmp b.tmp c.tmp a.tmp
and both will give the same result:
d.tmp b.tmp c.tmp a.tmp
Solution 2:[2]
I don't properly understand this but one way that worked for me was to make a one-line change to replace the suffix rule .tmp.html: with a pattern rule %.html:
.SUFFIXES: .mmd .tmp .html
a.html : h.tmp a.tmp
b.html : h.tmp b.tmp
c.html : h.tmp c.tmp C.tmp
%.html:
cat $^ > $@
.mmd.tmp:
Markdown.pl $< > $@
which preserves order
$ touch h.mmd
$ make ?.html
Markdown.pl h.mmd > h.tmp
cat h.tmp a.tmp > a.html
cat h.tmp b.tmp > b.html
cat h.tmp c.tmp C.tmp > c.html
So that is an answer, albeit incomplete because ...
What I understand:
- A target can have multiple rules.
- $^ is the combined set of all prerequisites from all rules for a target.
What I don't understand:
- Why this affects the order of the elements of $^ in the same command.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | MadScientist |
| Solution 2 |
