2009-02-16 12 views
7

Existe-t-il un moyen de réévaluer la définition d'une variable à chaque utilisation? Par exemple:réévaluer les variables du fichier 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] 

Ainsi, MAP_FILES sera évalué lorsque le makefile est lu, et s'il n'y a pas de fichiers .map dans le répertoire $ TMP la variable sera vide. Cependant, une fois la règle generate_map_files terminée, il y aura des fichiers .map dans le répertoire et je voudrais que la liste de ces fichiers .map soit une condition préalable à la règle work_with_map_files.

Je ne connais pas les noms de fichier des fichiers .map avant qu'ils ne soient générés, donc je ne peux pas déclarer explicitement une variable avec des noms de fichiers. J'ai besoin que la variable soit définie avec la liste des fichiers de carte une fois qu'ils ont été générés. Toute suggestion serait très utile. Merci.

Répondre

4

Vous pouvez essayer de faire un make récursif, quelque chose comme

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

En général, cela n'est pas possible dans Makefiles, car pour déterminer les cibles à créer et dans quel ordre, make doit connaître leurs dépendances à l'avance avant l'exécution des règles. Dans votre exemple, comment make peut-il savoir quand évaluer $(MAP_FILES) dans la règle work_with_map_files? L'ordre n'est pas explicitement défini, mais déduit des dépendances. Dans votre exemple, vous voulez qu'il soit évalué après que la règle generate_map_files a été exécutée, mais il n'y a aucun moyen pour make de le savoir car il a besoin de connaître la valeur de cette variable pour les dépendances qui sont nécessaires pour déterminer l'ordre dans lequel cette valeur serait évaluée - c'est une boucle auto-référentielle.

Une astuce simple serait bien sûr de courir faire deux fois - vous pouvez avoir ce fait automatiquement en ajoutant une commande make work_with_map_files après la commande ./mapbuilder dans le modèle generate_map_files, mais faites attention à cela en général parce que si work_with_map_files serait effectivement être déclarée pour dépendre de generate_map_files (ce qu'il devrait) cela conduirait à une boucle make récursive infinie. Et bien sûr, cela vainc l'idée de make déterminer automatiquement la commande. Sinon, vous auriez besoin d'un remplacement make qui peut être laissé entendre sur de telles commandes et faire plusieurs passes. C'est la raison pour laquelle dans les bases de code plus grandes avec plusieurs fichiers d'inclusion, où l'on ne veut pas répéter les dépendances d'inclusion dans le Makefile, makedepend est souvent utilisé pour générer un Makefile séparé avec ces dépendances, qui est inclus dans le principal Makefile. Pour en créer un, exécute en premier make depend qui appelle makedepend pour générer les dépendances de fichier d'inclusion, puis make.

3

Avec GNU make, vous pouvez profiter de la makefile fonction refaisant, ce qui provoque GNU make pour redémarrer automatiquement si l'un des makefiles inclus sont modifiés pendant la passe initiale. Par exemple:

.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 

En plus de la fonction de makefile refaisant, cette solution utilise le fait que GNU make vous permet de spécifier plusieurs lignes de pré-requis pour une cible. Dans ce cas, les prérequis du fichier de carte sont déclarés dans le fichier map_files.d généré dynamiquement. Déclarer map_files.d en tant que cible PHONY garantit qu'il est toujours régénéré lorsque vous exécutez la construction; cela peut ou peut ne pas convenir selon vos besoins.

Questions connexes