2009-06-10 15 views
8

Me parece que estoy escribiendo muchos Makefiles que se pueden limpiar con el uso de n-listas de tuplas. Pero no puedo encontrar ninguna forma de hacer esto correctamente (y limpiamente). Hasta ahora solo he podido usar $ (shell ...) y tr, sed, o estándares que no sean Makefile.¿Iterando sobre listas en Makefiles?

Por ejemplo, me gustaría hacer esto:

XYZs = \ 
    dog.c pull_tail bark \ 
    duck.c chase  quack \ 
    cow.c tip  moo 

all: 
    @- $(foreach X Y Z,$(XYZs), \ 
     $(CC) $X -o bully/$Y ; \ 
     ln bully/$Y sounds/$Z ; \ 
    ) 

¿Hay una buena manera de iterar n listas tupla en Makefile? ¡Gracias!

Respuesta

10

Los archivos Makefiles son esencialmente declarativos por naturaleza, por lo que no creo que make yourself proporcione lo que usted desea. Sin embargo, parece que desea asociar algunos valores de cadena con objetivos específicos, por lo que tal vez le interese la característica Target specific variable values de la marca GNU. Este es un extracto del manual:

Hay una característica más especial de las variables específicas de la diana: cuando define una variable específica de la diana, ese valor variable es también en efecto para todas las dependencias de este objetivo (a menos que esas dependencias lo anulen con su propio valor de variable específico de destino ). Así, por ejemplo, una declaración así:

prog : CFLAGS = -g

prog : prog.o foo.o bar.o

fijará CFLAGS--g en el de comandos para prog, sino que también establecer CFLAGS--g en el comando scripts que crean prog.o, foo.o, y bar.o, y los scripts de comandos que crean sus dependencias.

Si aún no lo ha leído, el manual de fabricación de GNU es bastante bueno.

Editar: para hacer lo que preguntaste en su comentario:

dog: ANIMAL=dog.c BULLY=pull_tail SOUND=bark 

uso:

dog: ANIMAL=dog.c 
dog: BULLY=pull_tail 
dog: SOUND=bark 
+0

fresca, y podría ser a mitad de camino! ¿Hay sintaxis para hacer esto? perro: ANIMAL = dog.c TIRANICE = SONIDO pull_tail = corteza – Dylan

+0

1, muy agradable. –

+2

¡El problema no es que make sea declarativo, es que no proporciona una sintaxis declarativa para este patrón tan frecuentemente necesario! – reinierpost

0

Estás haciendo al revés.

Está tratando de tratar hacer como si fuera un script. No es, en cambio, es un conjunto de reglas sobre cómo crear X dado Y. Luego, el motor de fabricación se da cuenta de lo que debe suceder para obtener ese resultado.

Para el ejemplo dado, realmente debería utilizar una secuencia de comandos para los pasos de generación. Tal vez llamar a eso de make, pero deje que maneje las cosas de CC.

+4

Esta es una limitación en el maquillaje que no tiene ninguna razón para estar allí en el primer lugar, y se puede evitar con $ (foreach) de todos modos. – reinierpost

2

Nada que yo sepa, pero eso se debe a que intenta forzar el trabajo y un lenguaje imperativo, cuando eso no es lo que es.

En GNU te hacen probablemente querrá hacer algo como:

pull_tail : SOUND=bark 
pull_tail : dog.c 
     $(CC) $< -o $^ 
     ln [email protected] $(SOUND) 

chase : SOUND=quack 
chase : duck.c 
     $(CC) $< -o $^ 
     ln [email protected] $(SOUND) 

... 

O mejor aún, redefinir la regla por defecto para los archivos .c para manejar la vinculación para usted, pero la extraña estructura de sus nombres (los nombres de los programas no tienen una relación léxica con los nombres de las fuentes) lo hace difícil.

Si lo que desea ser capaz de reconstruir esto de manera rápida y sin un montón de edición lado, es probable que desee escribir un script para generar el makefile framgment a partir de datos y utilizar la función de include de GNU make ...

5

Verificaría el manual GNU Make en foreach. aquí hay algunos recortes aleatorios que he usado en un proyecto diferente ... el ejemplo está incompleto, pero ¿quizás te dará algunas ideas? Podría limpiar esto más adelante si tengo más tiempo ...

REMAKE_PROGS:= dog duck cow 

XYZs = \ 
    dog.c pull_tail bark \ 
    duck.c chase  quack \ 
    cow.c tip  moo 

$(foreach src, $(XYZs), $(eval $MAKE $(src)) 

$(REMAKE_PROGS): 
     @echo "\n# === [email protected] linking\n" 
     $(call compile,[email protected],$([email protected]),$(CXX),$(MPICXX),$(LDFLAGS) $(LIBS) $(SYSLIBS) $(OTHER_LIB) $(EXTRA_LD_FLAGS)) 
     @echo "\n# --- [email protected] compiled\n" 

define compile 
    @mkdir -p $(dir $(1)) 
    $(if ${ANNOUNCE},@echo "\n# +++ ${MAKECMDGOALS} compiling\n" $(eval ANNOUNCE=)) 
    $(call compiler,$(1),NOMPI,$(3),$(4)) 
    $(eval MY_FLAGS=$(FLAGS_$(1)) $(5)) 
    $(if $(filter %xlf %xlf90,$(COMPILER_$(1))),$(eval MY_FLAGS:=$(MY_FLAGS:-D%=-WF,-D%))) 
    $(strip $(COMPILER_$(1)) $(2) $(MY_FLAGS) -o $(1)) 
endef 
+0

No uso foreach-call-make, pero foreach-eval-call, que es igual de feo. Ver http://www.gnu.org/software/automake/manual/make/Eval-Function.html#Eval-Function – reinierpost

0

puede utilizar reglas predeterminadas para un conjunto de archivos con la misma extensión que en cada archivo para compilar c a un o. Por supuesto, no está restringido a ninguna extensión de archivo especial. Para compilar un conjunto de archivos .c que podría hacerlo de esta manera:

OBJS = foo.o bar.o baz.o 
OUT = myprog 

all: $(OBJS) 
     $(SILENT) echo "LD [email protected]" 
     $(SILENT) $(CPP) -o $(OUT) $^ $(LDFLAGS) 

%.o: %.c 
     $(SILENT) echo "CC $<" 
     $(SILENT) $(CC) $(CCOPTS) -o [email protected] -c $< 
+0

El problema comienza cuando se necesita utilizar uno "valor (OBJ) los actuales $" dentro de la regla de patrón. GNU make no proporciona sintaxis declarativa para eso, y $ (foreach) es una solución fea (pero perfectamente funcional). – reinierpost

6

Gracias por los consejos - después de algún piratería creo que esto es más de lo que esperaba:

XYZs = \ 
    dog.c:pull_tail:bark \ 
    duck.c:chase:quack \ 
    cow.c:tip:moo 

all: 
    @- $(foreach XYZ,$(XYZs), \ 
     $(eval X = $(word 1,$(subst :, ,$(XYZ)))) \ 
     $(eval Y = $(word 2,$(subst :, ,$(XYZ)))) \ 
     $(eval Z = $(word 3,$(subst :, ,$(XYZ)))) \ 
     \ 
     $(CC) $X -o bully/$Y ; \ 
     ln bully/$Y sounds/$Z ; \ 
    ) 

Puede alguien ¿hacerlo mejor?

Cuestiones relacionadas