2009-02-16 13 views
7

Gibt es eine Möglichkeit, die Definition einer Variablen bei jeder Verwendung neu zu bewerten? Zum Beispiel:Makefile-Variablen neu bewerten

MAP_FILES = $(shell find $(TMP) -name "*.map") 

all: generate_map_files work_with_map_files 

generate_map_files: 
    ./map-builder 

work\_with\_map_files: $(MAP_FILES) 
    ./map-user 

%.map: 
    ./map-edit [email protected] 

So wird MAP_FILES ausgewertet werden, wenn die Make-Datei gelesen wird, und wenn es keine .map Dateien im Verzeichnis $ TMP die Variablen leer sein werden ist. Nachdem die generate_map_files-Regel abgeschlossen ist, befinden sich .map-Dateien im Verzeichnis und ich möchte, dass die Liste dieser .map-Dateien für die Regel work_with_map_files erforderlich ist.

Ich kenne die Dateinamen der .map-Dateien nicht, bevor sie generiert werden, so dass ich eine Variable mit Dateinamen nicht explizit deklarieren kann. Ich brauche die Variable mit der Liste der Map-Dateien, sobald sie erstellt wurden. Irgendwelche Vorschläge wären sehr hilfreich. Vielen Dank.

Antwort

4

Sie könnten versuchen, eine rekursive make tun, so etwas wie

MAP_FILES = $(shell find $(TMP) -name "*.map") 

all: generate_map_files 

generate_map_files: 
    ./map-builder; $(MAKE) work_with_map_files 

work\_with\_map_files: $(MAP_FILES) 
    ./map-user 

%.map: 
    ./map-edit [email protected] 
0

Im Allgemeinen ist dies in Makefiles nicht möglich, da make ihre Abhängigkeiten im Voraus kennen müssen, bevor die Regeln ausgeführt werden, um zu bestimmen, welche Ziele in welcher Reihenfolge zu erstellen sind.

In Ihrem Beispiel, wie würde make wissen, wann die $(MAP_FILES) in der work_with_map_files Regel auszuwerten? Die Reihenfolge ist nicht explizit definiert, sondern wird aus den Abhängigkeiten abgeleitet. In Ihrem Beispiel möchten Sie, dass es ausgewertet wird, nachdem die generate_map_files Regel ausgeführt wurde, aber es gibt keine Möglichkeit für make dies zu wissen, weil es den Wert dieser Variablen für die Abhängigkeiten kennen muss, die benötigt werden, um die Reihenfolge zu bestimmen Wert würde ausgewertet werden - das ist eine selbstreferentielle Schleife.

Ein einfacher Trick wäre natürlich zweimal laufen lassen - das kann man automatisch durch Hinzufügen eines make work_with_map_files Befehls nach dem ./mapbuilder Befehl in der generate_map_files Vorlage getan hat, sondern weil damit in der Regel vorsichtig sein, wenn work_with_map_files tatsächlich deklariert werden würde von generate_map_files (was es sollte) zu führen würde dies zu einer unendlichen rekursiven make Schleife führen. Und das vereitelt natürlich die Idee von make automatisch den Auftrag zu bestimmen. Sonst würden Sie einen make Ersatz benötigen, der auf solchen Aufträgen andeutet werden und mehrere Durchgänge machen kann.

Dies ist der Grund, dass in größerer Codebasis mit mehreren Dateien enthalten, wobei man die umfassen Abhängigkeiten in den Makefile nicht wiederholen will, makedepend wird häufig eine separate Makefile mit diesen Abhängigkeiten zu erzeugen, verwendet, die in der enthalten ist Haupt Makefile. Um einen zu erstellen, wird zuerst make depend ausgeführt, der makedepend aufruft, um die Include-Dateiabhängigkeiten zu generieren, und dann make.

3

Mit GNU machen, können Sie die Vorteile der Make-Datei remaking Funktion übernehmen können, die GNU automatisch machen verursacht neu zu starten, wenn eine der enthaltenen Makefiles geändert werden während des ersten Durchgangs. Zum Beispiel:

.PHONY: map_files.d 
-include map_files.d 
map_files.d: 
     ./map_builder 
     echo "work_with_map_files: `ls *.map`" > map_files.d 

work_with_map_files: 
     ./map_user 

Neben der Make-Datei remaking Feature, macht diese Lösung die Tatsache zunutze, dass GNU make Sie mehrere Zeilen von Voraussetzungen für ein Ziel angeben können. In diesem Fall werden die Voraussetzungen für die Kartendatei in der dynamisch generierten Datei map_files.d deklariert. Wenn Sie map_files.d als PHONY-Ziel deklarieren, wird sichergestellt, dass es beim Ausführen des Builds immer neu generiert wird. das kann oder kann nicht passend sein, abhängig von Ihren Bedürfnissen.