2010-06-15 7 views
10

Dies ist eine Art Fortsetzung der Frage von here. Das Problem ist, dass es eine Regel gibt, die mehrere Ausgaben von einer einzigen Eingabe erzeugt, und der Befehl ist zeitaufwendig, so dass wir eine Neuberechnung lieber vermeiden würden. Jetzt gibt es eine zusätzliche Wendung, dass wir verhindern wollen, dass Dateien als Zwischendateien gelöscht werden, und Regeln beinhalten Wildcards, um Parameter zuzulassen.GNU Makefile: mehrere Ausgaben von einer einzigen Regel + verhindern, dass Zwischendateien gelöscht werden


Die Lösung wurde vorgeschlagen, dass wir die folgende Regel ein:

file-a.out: program file.in 
    ./program file.in file-a.out file-b.out file-c.out 

file-b.out: file-a.out 
    @ 

file-c.out: file-b.out 
    @ 

Dann make file-c.out Aufruf erzeugt beide und wir vermeiden Probleme mit make parallel -j Schalter ausgeführt wird. Alles soweit in Ordnung.


Das Problem ist das folgende. Da die obige Lösung eine Kette in der DAG aufbaut, berücksichtigt make es anders; Die Dateien file-a.out und file-b.out werden als Zwischendateien behandelt und standardmäßig werden sie gelöscht, sobald file-c.out bereit ist.

Eine Art und Weise, dass zur Vermeidung von irgendwo hier erwähnt, und besteht aus file-a.out und file-b.out als Abhängigkeiten eines Ziel Hinzufügen .SECONDARY, die gelöscht sie davon abhält, zu werden. Leider löst das meinen Fall nicht, da meine Regeln Platzhalter verwenden. Insbesondere sehen meine Regeln mehr wie folgt aus:

file-a-%.out: program file.in 
    ./program $* file.in file-a-$*.out file-b-$*.out file-c-$*.out 

file-b-%.out: file-a-%.out 
    @ 

file-c-%.out: file-b-%.out 
    @ 

so dass man einen Parameter übergeben, die im Dateinamen enthalten wird, zum Beispiel durch

make file-c-12.out 

Die Lösung läuft die make Dokumentation vorschlägt, ist zu Fügen Sie diese als implizite Regeln der Liste der Abhängigkeiten von .PRECIOUS hinzu, damit diese Dateien nicht gelöscht werden.


Die Lösung mit .PRECIOUS funktioniert, aber es verhindert auch diese Dateien gelöscht wird, wenn eine Regel nicht und Dateien sind unvollständig. Gibt es einen anderen Weg, um das zu funktionieren?

Ein Hack, dies zu lösen, ist ein Ziel .SECONDARY ohne Voraussetzungen zu definieren, dh

.SECONDARY: 

die make darüber informiert, dass alle Dateien, die als Sekundär behandelt werden sollen und somit nicht entfernt werden, es sei denn, wenn make unterbrochen wird oder Eine Regel schlägt fehl. Leider erlaubt dies nicht das Auswählen einer Teilmenge von Regeln mit Platzhaltern, um auf diese Weise zu arbeiten, daher halte ich dies nur für einen Hack (obwohl es nützlich ist).

+0

Hmm, da in den Voraussetzungen kein Stamm ist (dh Sie verwende Datei.in statt Datei -% .in). Es wird viel einfacher, wenn Sie file- $ a- $ n.out aus Datei- $ n.in erstellen, und es ist komisch, wie es ist (make file-c-17.out file-c-18.out) erzeugen identische Ausgaben mit unterschiedlichen Namen, es sei denn, es gibt eine versteckte Eingabequelle wie die Zeit. Könnte die Regel geändert werden in Datei-a -%. Out: Programm-Datei -%. – p00ya

+0

Es ist irrelevant für die vorliegende Frage. Dies sind nur erfundene Regeln, der Punkt ist, dass sie Platzhalter enthalten. Die wirklichen Regeln sind wesentlich komplizierter, aber diese Komplexität würde das Problem, vor dem ich stehe, verbergen. – makesaurus

+0

Siehe meine Antwort für warum es relevant ist. – p00ya

Antwort

2

Wenn Ihre Ausgaben statt einer einzelnen file.in aus einer vorausgesetzten Datei generiert wurden, die den Vorspann enthielt, d. H.

file-a.out: program file-%.in 
    ./program file-$*.in file-a-$*.out file-b-$*.out file-c-$*.out 

Sie können dann eine Liste aller möglichen Ziel bauen matches:

inputs = $(wildcard file-*.in) 
secondaries = $(patsubst file-%.in,file-a-%.out,$(inputs)) \ 
    $(patsubst file-%.in,file-b-%.out,$(inputs)) 

Ebenso, wenn der Schaft aus einem endlichen Satz kommt:

batchnos = 17 18 19 20 
batchnos = $(shell seq 17 20) 
secondaries = $(patsubst %,file-a-%.out,$(batchnos)) $(patsubst %,file-b-%.out,$(batchnos)) 

Dann fügen Sie einfach diese als prereqs zu das .SECONDARY Ziel

+0

Das ist eine mögliche Lösung, die nicht immer sehr praktisch ist. In meinem Fall war es einfacher zu verlassen '.SECONDARY:' statt alle Möglichkeiten aufzulisten. Außerdem muss "%" nicht in den Namen der Eingabedatei eingefügt werden. Sie müssen lediglich alle möglichen Namen von Ausgabedateien zur Liste der Sekundärdateien hinzufügen. – makesaurus

16

Das Einfachste

file-a-%.out file-b-%.out file-c-%.out: program file.in 
    ./program $* file.in file-a-$*.out file-b-$*.out file-c-$*.out 

wird genau das tun, was Sie wollen.

(Pattern-Regeln mit mehreren Zielen unterschiedlich sind als die normale Regel mit mehreren Zielen, die Sie here zu fragen wurden. Siehe Bison Beispiel im make manual.)

Verwandte Themen