2009-02-16 9 views
7

Esiste un modo per rivalutare la definizione di una variabile ad ogni utilizzo? Per esempio:rivalutare le variabili del makefile

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] 

Così, MAP_FILES sarà valutata quando il makefile viene letta, e se non ci sono file .map nella directory $ TMP variabile sarà vuota. Tuttavia, una volta completata la regola generate_map_files, nella directory saranno presenti i file .map e vorrei che l'elenco di tali file .map fosse un prerequisito per la regola work_with_map_files.

Non conosco il nome file dei file .map prima che vengano generati, quindi non posso dichiarare esplicitamente una variabile con nomi di file. Ho bisogno che la variabile venga impostata con l'elenco dei file di mappe una volta che sono stati generati. Qualsiasi suggerimento sarebbe molto utile. Grazie.

risposta

4

Si potrebbe provare a fare un make ricorsivo, qualcosa come

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

In generale ciò non è possibile nei Makefile, perché per determinare quali obiettivi effettuare e in quale ordine, make deve conoscere le proprie dipendenze in anticipo prima che le regole vengano eseguite.

Nel tuo esempio, in che modo make sa quando valutare lo $(MAP_FILES) nella regola work_with_map_files? L'ordine non è definito in modo esplicito, ma dedotto dalle dipendenze. Nel tuo esempio vuoi che venga valutato dopo che è stata eseguita la regola generate_map_files, ma non c'è modo che make lo sappia perché è necessario conoscere il valore di questa variabile per le dipendenze necessarie per determinare l'ordine con cui questo il valore verrebbe valutato - questo è un loop autoreferenziale.

Un trucco semplice sarebbe ovviamente quella di eseguire fare due volte - si può avere quel fatto automaticamente con l'aggiunta di un comando make work_with_map_files dopo il comando ./mapbuilder nel modello generate_map_files, ma attenzione a questo, in generale, perché se work_with_map_files sarebbe in realtà essere dichiarati per dipendere da generate_map_files (che dovrebbe) ciò porterebbe ad un ciclo ricorsivo infinito make. E naturalmente questo sconfigge l'idea di make determinando automaticamente l'ordine. Altrimenti è necessario un ricambio make che possa essere indicato su tali ordini e effettuare più passaggi.

Questa è la ragione per cui in basi di codice più grandi con più file include, in cui non si vuole ripetere l'inclusione dipendenze nel Makefile, makedepend è spesso usato per generare un Makefile separato con quelle dipendenze, che è incluso nel principale Makefile. Per crearne uno, viene eseguito prima make depend che chiama makedepend per generare le dipendenze del file di inclusione e quindi make.

3

Con GNU make, è possibile sfruttare la funzione di makefile rifacimento, che fa sì che GNU make per riavviare automaticamente se uno dei makefile inclusi sono cambiati durante il passaggio iniziale. Per esempio:

.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 

Oltre alla funzione di rifare makefile, questa soluzione si avvale del fatto che GNU make consente di specificare più righe di prerequisiti per un obiettivo. In questo caso, i prereq dei file di mappa sono dichiarati nel file map_files.d generato dinamicamente. Dichiarare map_files.d come target PHONY assicura che venga sempre rigenerato quando si esegue la build; che può o non può essere appropriato a seconda delle esigenze.