2009-02-16 19 views
7

¿Hay alguna manera de reevaluar la definición de una variable en cada uso? Por ejemplo:reevaluar las variables del archivo MAKE

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] 

Así, MAP_FILES se evaluará cuando se lee el archivo MAKE, y si no hay archivos .map en el directorio $ TMP la variable estará vacía. Sin embargo, después de que se complete la regla generate_map_files, habrá archivos .map en el directorio y me gustaría que la lista de esos archivos .map sea un requisito previo para la regla work_with_map_files.

No conozco los nombres de archivo de los archivos .map antes de que se generen, por lo que no puedo declarar una variable con nombres de archivo explícitamente. Necesito que la variable se establezca con la lista de archivos de mapas una vez que se hayan generado. Cualquier sugerencia sería muy útil. Gracias.

Respuesta

4

Usted puede tratar de hacer un make recursivo, algo así como

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 general, esto no es posible en Makefiles, porque para determinar qué objetivos realizar y en qué orden, make necesita conocer sus dependencias por adelantado antes de que se ejecuten las reglas.

En su ejemplo, ¿cómo sabría make cuándo evaluar el $(MAP_FILES) en la regla work_with_map_files? El orden no se define explícitamente, sino que se deduce de las dependencias. En el ejemplo, desea que se evalúe después de que se ejecutó la regla generate_map_files, pero no hay forma de que make lo sepa porque necesita conocer el valor de esta variable para las dependencias que se necesitan para determinar el orden en el que se evaluaría el valor, es decir, un bucle autorreferencial.

Un truco sencillo sería, por supuesto ejecutar make dos veces - que puede tener que realiza automáticamente mediante la adición de un comando make work_with_map_files después del comando ./mapbuilder en la plantilla generate_map_files, pero tener cuidado con esto, en general, porque si work_with_map_files realidad se declararía depender de generate_map_files (lo cual debería) esto llevaría a un bucle make infinito recursivo. Y, por supuesto, esto derrota la idea de make determinando automáticamente el orden. De lo contrario, necesitaría un reemplazo de make que puede insinuarse en tales pedidos y hacer múltiples pases.

Esta es la razón por la que en bases de códigos más grandes con múltiples archivos de inclusión, donde uno no quiere repetir las dependencias include en Makefile, makedepend se usa a menudo para generar un Makefile separado con esas dependencias, que se incluye en principal Makefile. Para compilar uno, se ejecuta primero make depend que llama a makedepend para generar las dependencias de archivos de inclusión y luego make.

3

Con GNU make, se puede aprovechar la característica makefile rehacer, lo que provoca GNU make para reiniciar automáticamente si se ha modificado cualquiera de los archivos make incluidos durante el pase inicial. Por ejemplo:

.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 

Además de la función de rehacer makefile, esta solución hace uso del hecho de que GNU make le permite especificar varias líneas de requisitos previos para un objetivo. En este caso, los prereqs del archivo de mapa se declaran en el archivo map_files.d generado dinámicamente. Declarar map_files.d como un objetivo PHONY asegura que siempre se regenere cuando ejecuta la compilación; eso puede o no ser apropiado dependiendo de sus necesidades.

Cuestiones relacionadas