2010-03-10 11 views
8

Estoy tratando de crear una plantilla de compilación genérica para mis Makefiles, algo así como lo discuten en el eval documentation.

Parece que la función de comodín no funciona en una evaluación. El código básico con el que estoy teniendo problemas se ve así.

SRC_DIR = ./src/ 

PROG_NAME = test 

define PROGRAM_template 
    $(1)_SRC_DIR = $(join $(SRC_DIR), $(1)/) 
    $(1)_SRC_FILES = $(wildcard $$($(1)_SRC_DIR)*.c) 
endef 

$(eval $(call PROGRAM_template, $(PROG_NAME))) 

all: 
    @echo $(test_SRC_DIR) 
    @echo $(test_SRC_FILES) 
    @echo $(wildcard $(wildcard $(test_SRC_DIR)*.c) 

Cuando corro hacer con esto, la salida es

./src/test 

[correct list of all .c files in ./src/test/] 

Básicamente, la llamada comodín dentro PROGRAM_template no está siendo eval'd como yo esperaba. La llamada da como resultado una lista vacía.
Sin embargo, la llamada de unión se evalúa correctamente.

Entonces, ¿qué estoy haciendo mal? Supongo que

$$($(1)_SRC_DIR) 

no es correcto, pero no puedo encontrar la manera correcta de hacerlo.

EDIT Una vez que esto fue resuelto, no me llevó mucho tiempo dar con otro problema con eval. lo publicado como una nueva cuestión en Workaround for GNU Make 3.80 eval bug

Respuesta

10

Es necesario duplicar escapar prácticamente todas las funciones y variables cuando se utiliza eval. En la mayoría de los casos, las únicas cosas que no deben ser deben escaparse por duplicado son argumentos de función (porque la función call las expandirá completamente). En este caso, técnicamente no es necesario que doble el escape join o SRC_DIR tampoco, pero simplificará su vida si siempre se duplican todas las variables y funciones al usar eval.

La razón por la que necesita el doble escape es que la expansión ocurre dos veces al usar eval. La función eval en sí misma realiza expansión, y luego la expansión se realiza nuevamente cuando el bloque finalmente se analiza como sintaxis de archivo MAKE (es decir, cuando se evalúa realmente).

De la forma en que lo tiene escrito, wildcard se invoca en la cadena literal $(test_SRC_DIR)*.c. Si lo desea, puede verlo usted mismo reemplazando wildcard con info en su versión y vea qué sucede.

Necesitas esperar antes de invocar realmente wildcard hasta la segunda expansión, por lo que es argumento se el resultado de la expansión de$(test_SRC_DIR).

Prueba esto:

SRC_DIR = ./src/ 

PROG_NAME = test 

define PROGRAM_template 
    $(1)_SRC_DIR = $$(join $$(SRC_DIR),$(1)/) 
    $(1)_SRC_FILES = $$(wildcard $$($(1)_SRC_DIR)*.c) 
endef 

$(eval $(call PROGRAM_template,$(PROG_NAME))) 

all: 
    @echo $(test_SRC_DIR) 
    @echo $(test_SRC_FILES) 
    @echo $(wildcard $(test_SRC_DIR)*.c) 

EDITAR: Después de publicar esto, pensé que sería mejor probarlo para asegurarse de que realmente funciona. Al hacerlo, descubrí otro problema. Debe evitar poner espacios entre la coma y el argumento al llamar a las funciones. Hace que un carácter de espacio literal se anteponga al argumento que se pasa a la función y conduce a resultados no deseados.He eliminado los espacios después de las comas en las llamadas de función en mi versión (aunque esto no es un problema para la llamada al join, también eliminé el espacio porque es un buen hábito para entrar).

+0

¡Gracias! Estaba a punto de comentar que no funcionó, luego volví y vi su edición. Parece que la línea $ (1) _SRC_DIR = $$ ($$ unen (SRC_DIR), $ (1) /) también funciona de la manera que lo tenía, pero para la línea de $ (comodín), debe el $$. – bengineerd

+0

@bengineerd: Sí, desde entonces he aclarado mi respuesta un poco. No necesita los dobles escapes en 'join' y' SRC_DIR' porque estos se * completamente * expandidos después de una sola expansión. Pero, como digo, hace la vida más fácil simplemente usar el doble escape. No dañarán nada cuando no sean necesarios. –

Cuestiones relacionadas