2012-03-13 15 views
23

Estoy usando GNU make 3.81. Aquí es un makefile prueba que demuestra el problema:¿Cómo puedo usar macros para generar múltiples objetivos/reglas de Makefile dentro de foreach? Comportamiento misterioso

define BOZO 

a$(1): b c 
    touch a$(1) 

endef 

$(foreach i,1 2 3,$(call BOZO,$(i))) 

La idea aquí es utilizar una plantilla de macro (BOZO) para generar reglas que siguen un patrón predecible.

Problema: cuando corro hacer en este archivo make me sale un error diciendo:

Makefile.fake:10: *** multiple target patterns. Stop. 

(donde la línea 10 es la línea con el foreach).

Ahora, sé lo que ese error normalmente indica. Veamos a qué se extiende esa línea utilizando la función info para enviar la expansión a la salida estándar. Cómo cambio la línea 10 para ser:

$(info $(foreach i,1 2 3,$(call BOZO,$(i)))) 

y corro:

$ make -n 

a1: b c 
    touch a1 

a2: b c 
    touch a2 

a3: b c 
    touch a3 

make: *** No targets. Stop. 

Tenga en cuenta que los "no blancos" Se espera que el mensaje, ya que el $ (info ...) evalúa la función de vaciar, pero hace que imprima las reglas generadas.

Vamos a ejecutar esas reglas, ¿o sí?

$make -n > out.txt 
make: *** No targets. Stop. 
$make -f out.txt a1 a2 a3 
touch a1 
touch a2 
touch a3 
$ 

AAARGH! Las reglas funcionan bien. Entonces ... ¿está el error en la marca, o en mi entendimiento?

Una última pista que podría ayudar a diagnosticar: si cambio de la línea foreach para:

$(foreach i,1,$(call BOZO,$(i))) 

(de manera que foreach tiene sólo una iteración)

y luego hacer

$make a1 

Me sale un error diferente:

make: *** No rule to make target `a1'. Stop. 

No sé de ninguna manera para "ver" la expansión de $(foreach) que hace que vea a excepción de $(info), y su salida es legal, así que estoy bastante perplejo.

Respuesta

36
$(foreach i,1 2 3,$(eval $(call BOZO,$(i)))) 

El eval function le dice a make para analizar las estructuras de la sintaxis como makefile, a "promulgar" ellos. No estoy seguro de por qué Make se opuso a las reglas no evaluadas de esta manera particular, pero eso es algo académico.

+0

D'OH! Bien, soy nuevo en Macros de Makefile. Todavía no entiendo muy bien por qué es necesario, pero funciona, así que meditaré en ello. ¡Gracias! – Joe

30

La respuesta de Beta es correcta, pero quería abordar el comentario, "No estoy seguro de por qué Make se opuso a las reglas no evaluadas".

La razón por la que las reglas no evaluadas no funcionan es que un archivo MAKE se basa finalmente en la línea y las líneas se cortan ANTES de que las variables se expandan. Por lo tanto, no es posible que una expansión de una variable se convierta en un resultado multilínea: incluso si la expansión contiene líneas nuevas, se trata todo como una "línea".Cuando termina la expansión marca el bucle foreach y analiza los resultados que básicamente se ve esto:

a1: b c touch a1 a2: b c touch a2 a3: b c touch b3 

razón por la cual se obtiene el error "múltiples patrones de destino".

El eval hace que se vuelva a interpretar el resultado de la expansión desde el principio como un fragmento completo de sintaxis de archivo, incluyendo el corte de línea, etc., y es por eso que una expansión multilínea funciona allí.

+0

¡Gracias, muy útil! – Joe

+0

Esta explicación fue muy útil para ayudarme a comprender un archivo make particularmente complicado que encontré en el trabajo. –

0

after using eval function still i am facing multiple pattern stop issue. I am recursively building target using foreach but i am facing this multiple target issue. while running make file on window 32 bit platform(which run correctly for linux machine)

define BOZO 
$(CWD)/$(1).o:$(CWD).$(1).def 
endef 
$(foreach target,$(basename $(list)),$(eval $(call BOZO,$(target)))) 

$(CWD)/%.def: a.out 
    @echo building [email protected] 
    a.out %.def 

Algo como esto. ¿Puedes sugerir esto ...?

+1

Gracias por este fragmento de código, que puede proporcionar ayuda inmediata. Una explicación adecuada [mejoraría en gran medida] (// meta.stackexchange.com/q/114762) su valor educativo al mostrar * por qué * esta es una buena solución al problema, y ​​lo haría más útil para lectores futuros con similares, pero no idénticas, preguntas. Por favor [edite] su respuesta para agregar una explicación y dar una indicación de qué limitaciones y suposiciones se aplican. –

Cuestiones relacionadas