Ich denke, dass Sie die Make-Datei zu verstehen:
# Original
all: dir/analysis
.SECONDEXPANSION:
%/analysis: %/subdir
%/analysis: $(addsuffix /data, $$^)
@echo TARGET: [email protected] DEPS: $^
touch [email protected]
wie folgt aus:
- standardmäßig wir machen
dir/analysis
- Wir fordern sekundäre Expansion
- Wir sagen, dass was
/analysis
hängt von was auch immer/subdir
. So die dir/subdir
eine Voraussetzung für dir/analysis
- Wir machen auch sagen, dass was
/analysis
auf die Sache ab, die wir von suffixing bekommen /data
dem Stand der Voraussetzungen von was/analysis
. (Sekundär Erweiterung von $$^
gibt uns die vorherigen Voraussetzungen des Ziels).Und seit den vorherigen Voraussetzungen von dir/analysis
sind dir/subdir
, dass jetzt macht dir/subdir dir/subdir/data
die neuen Voraussetzungen von dir/analysis
.
Daraus ergibt sich die Ausgabe des Rezepts sollte sein:
TARGET: dir/analysis DEPS: dir/subdir/data dir/subdir
touch dir/analysis
Dieses Verständnis schlecht ist falsch. Sie verwirren und verschmelzen die Operation von Musterregeln mit der Operation oder gewöhnlichen Regeln.
Wenn ein Make-Datei sagt, zum Beispiel:
# A
xx: xa
xx: xb
xx: xc
touch [email protected]
oder sogar:
# B
xx: xa
xx: xb
%x: %c
touch [email protected]
dann die Voraussetzungen aller leeren Regeln für die Ziel xx
kombiniert werden mit denen die (eine) Nicht leere Regel, wenn xx
als Ziel betrachtet wird. So # A
entspricht:
xx: xa xb xc
touch [email protected]
und # B
entspricht:
xx: xa xb
%x: %c
touch [email protected]
und in beiden Fällen die Voraussetzungen des xx
xa xb xc
sind.
jedoch:
%x: %a
%x: %b
touch [email protected]
ist nicht entspricht:
%x: %a %b
touch [email protected]
Wenn Sie jemals eine leere Muster Regel schreiben, seine Wirkung ist einfach jede vorheriges Muster Regel zu löschen mit dem gleichen Ziel und den vorausgesetzten Mustern. Und wenn Sie jemals eine nicht leere Musterregel schreiben, ersetzen Sie einfach jede vorherige Musterregel mit den gleichen Ziel und Voraussetzung Muster. Siehe 10.5.6 Canceling Implicit Rules
So:
.SECONDEXPANSION:
%/analysis: %/subdir
%/analysis: $(addsuffix /data, $$^)
@echo TARGET: [email protected] DEPS: $^
touch [email protected]
entspricht:
.SECONDEXPANSION:
%/analysis: $(addsuffix /data, $$^)
@echo TARGET: [email protected] DEPS: $^
touch [email protected]
Dann, wenn dieses Muster Regel in Bezug auf dir/analysis
betrachtet wird, gibt es keine vor Voraussetzungen: $^
wird erweitern auf die leere Zeichenfolge und in der sekundären Erweiterung, so wird $$^
.So endlich ist das Rezept entspricht:
# Residual
%/analysis: /data
@echo TARGET: [email protected] DEPS: $^
touch [email protected]
Sie sich von dieser befriedigen kann durch beide der # Original
und # Residual
Makefiles im Debug-Modus (-d
) und Vergleichen der Ausgänge aktiv.
Dies erklärt, warum die Ausgaben in beiden Fällen schließen:
make: *** No rule to make target 'dir/analysis', needed by 'all'. Stop.
Ein Muster Regel nur ein Ziel wenn dabei einen Weg für das Ziel getroffen werden bietet machen instanziiert wird. Warum sonst noch wählen? Da die Voraussetzung /data
nicht existiert, ist die Musterregel nicht durchführbar und wird verworfen. So wie wenn man versuchte, make foo.o
mit der Make-Datei:
%.o: %c
touch [email protected]
wenn kein foo.c
im Verzeichnis ist.
Wenn Sie wirklich die Ausgabe, die Sie erwartet haben, um sehen möchten, dann können Sie es aus erhalten:
.PHONY: all clean
all: dir/analysis
%/analysis: %/subdir %/subdir/data
@echo TARGET: [email protected] DEPS: $^
touch [email protected]
clean:
rm -f dir/analysis
Aber es ist schwer zu glauben, dass das, was Sie wirklich sehen wollen. Dieses Makefile macht die Analyse abhängig von den Daten und auch auf das Verzeichnis, in dem die Daten befindet. Was kann der Sinn sein?
%/analysis: %/subdir/data
drückt vermutlich die gewünschte Beziehung zwischen den Daten und der Analyse: -
- Wenn die Daten nicht existieren dann die Analyse nicht mehr aktuell ist und nicht gemacht werden kann (bis Sie einige Daten erhalten).
- Wenn die Daten vorhanden und älter als die Analyse ist, muss die Analyse nicht durchgeführt werden.
- Wenn die Daten vorhanden sind und neuer als die Analyse ist, kann und wird die Analyse durchgeführt.
Durch all dir/subdir
eine unabhängige Voraussetzung machen, dass Sie erreichen, ist eine Anforderung einzuführen, um die Analyse neu zu machen, wenn es als älter wird das Verzeichnis in , die die Daten befinden - unabhängig von den Daten. Wenn also z.B. Ich starte touch dir/subdir
, , die make
benötigen, um die Analyse erneut auszuführen, obwohl sich die Daten nicht geändert haben.
Ich kann nur Sinn Ihrer Motivation machen damit auch in Realität angenommen Sie make
-wollen machen die Daten, und das Verzeichnis, in dem sie sich befindet, wenn sie existieren nicht passieren, wenn eine Analyse erforderlich ist.Wenn das die Situation dann ist wollen Sie eine Make-Datei auf den Linien von:
.PHONY: all clean
all: dir/analysis
.SECONDARY:
%/subdir:
mkdir -p [email protected]
%/subdir/data: | %/subdir
touch [email protected]
%/analysis: %/subdir/data
@echo TARGET: [email protected] DEPS: $^
touch [email protected]
clean:
rm -f dir/analysis dir/subdir/data
Hier wird die Musterregel:
%/subdir/data: | %/subdir
macht %/subdir
ein order-only prerequisite von %/subdir/data
. Es bedeutet, dass /dir/subdir
ist nicht berücksichtigt bei der Bestimmung, ob /dir/subdir/data
Bedürfnisse gemacht werden, aber wenn es bestimmt wird, dass /dir/subdir/data
gemacht werden soll, dann wird /dir/subdir
zuerst gemacht werden. Dieser Weg, /dir/subdir
wird erstellt, wenn es nicht existiert, wenn Sie es brauchen, um die Daten dort zu setzen, aber keinen Einfluss haben auf, ob Sie die Daten oder die Analyse machen müssen. Das spezielle Ziel .SECONDARY
ist ein technicality. Es weist make
an, nachfolgende Ziele nicht automatisch zu löschen, dass es zu intermediate Artefakten führt, die aus verketteten Musterregeln hervorgehen. Ohne es, in diesem Beispiel make
würde folgern, dass dir/subdir/data
und dir/subdir/
sind nur Abfallprodukte der Herstellung dir/analysis
und löschen sie automatisch am Ende.
Wenn Sie das Make-Datei laufen zunächst ohne dir/subdir/data
und ohne dir/subdir/
Sie erhalten:
$ make
mkdir -p dir/subdir
touch dir/subdir/data
TARGET: dir/analysis DEPS: dir/subdir/data
touch dir/analysis
Und anschließend:
$ make clean
rm -f dir/analysis dir/subdir/data
$ make
touch dir/subdir/data
TARGET: dir/analysis DEPS: dir/subdir/data
touch dir/analysis
Und dann:
$ make
make: Nothing to be done for 'all'.
$ touch dir/subdir
$ make
make: Nothing to be done for 'all'.
Danke die für die Aufnahme Zeit eine so hilfreiche und ausführliche Antwort zu schreiben. Ich würde dir mehr danken, wenn ich könnte. Das hilft mir zu sehen, dass ich für das, was ich erreichen möchte, eine andere Strategie brauche. Ich war dabei, mehr über meine weiteren Ziele und das, was ich mit Second Expansion in meinem realen System zu tun versuchte, zu diskutieren, aber ich denke, das wäre besser für eine separate Frage geeignet. –