Makefile: Reihenfolge der Abhängigkeitsbewertung
-
23-10-2019 - |
Frage
Ein Ziel annehmen foo.tar
, das hängt von einer Liste von Dateien ab foo.files
, z.B
FOO_FILES := $(shell cat foo.files)
foo.tar: foo.files $(FOO_FILES)
tar -cf foo $(FOO_FILES)
Nehmen wir nun an, dass Foo.files generiert werden müssen, z.
foo.files: foo.files.template
sed -e "s/@{VERSION}/$(VERSION)/" < $< > $@
Es ist klar, dass foo.files
kommt drauf an foo.files.template
, aber wie kann man sicherstellen, dass foo_files bewertet wird nach foo.files wird erzeugt?
Lösung
Ihre ursprünglichen Regeln sind korrekt. Da die Aktualisierung von Foo.files den Wert von Foo_files veraltet hat, müssen Sie nur sicherstellen, dass Ihr Makefile von GNU make-make neu bewertet wird, wenn foo.files aktualisiert wurde, indem Ihr Makefile von Foo.files abhängt:
Makefile : foo.files
Andere Tipps
Also fand ich eine Antwort darüber Erweiterte Generierung von Auto-Abhängigkeiten bei Mad-Scientist.net. Grundsätzlich ist es möglich, ein Makefile über eine GNU/Make-Funktion neu zu bewerten. Wenn es eine Regel gibt, um ein enthaltenes Makefile zu generieren, wird das gesamte Makefile nach der Erzeugung der enthaltenen Datei erneut gelesen. Daher --
# -*- 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
- scheint das Richtige zu tun.
... und nur zur Vollständigkeit:
foo.files.template
ist:
a-$(VERSION)
b-$(VERSION)
und übernehmen die Anwesenheit von a-1.2.3
und b-1.2.3
.
Es kann nicht in einem Pass gemacht werden; Bestimmen Sie bestimmt, welche Ziele wieder aufgebaut werden müssen, bevor es tatsächlich eine Regel ausführt, und in diesem Fall existiert die vollständige Liste der Ziele erst, wenn eines der Regeln ausgeführt wird.
Dies sollte es tun:
FOO_FILES := $(shell cat foo.files)
foo.tar: foo.files
$(MAKE) foo-tarball
.PHONY: foo-tarball
foo-tarball: $(FOO_FILES)
tar -cf foo $^
BEARBEITEN:
Wie das OP betont, wird dies nicht wie geschrieben funktionieren. Ich habe eine Voraussetzung ausgelassen:
foo.tar: foo.files $(FOO_FILES)
...
Beachten Sie, dass dies auch dann wiederholt wird, wenn foo.files
hat sich nicht geändert, was nicht streng notwendig ist; Es ist möglich, dies zu korrigieren, aber nicht elegant. (Zum Vergleich ist die ausgewählte Lösung, die ich zu gebe, sauberer als meine, auch wenn das Ziel nichts zu tun hat foo.tar
.)