2010-06-15 19 views
10

Esto es una especie de continuación de la pregunta de here. El problema es que hay una regla que genera múltiples salidas desde una sola entrada, y el comando es lento, por lo que preferiríamos evitar el recálculo. Ahora hay un giro adicional, que queremos evitar que los archivos se eliminen como archivos intermedios, y las reglas involucran comodines para permitir los parámetros.GNU Makefile: múltiples salidas de una sola regla + evitar que se eliminen los archivos intermedios


La solución propuesta fue que establecimos la siguiente regla:

file-a.out: program file.in 
    ./program file.in file-a.out file-b.out file-c.out 

file-b.out: file-a.out 
    @ 

file-c.out: file-b.out 
    @ 

Entonces, llamando make file-c.out crea a la vez y evitamos problemas con el funcionamiento de make en paralelo con -j interruptor. Todo bien hasta ahora.


El problema es el siguiente. Debido a que la solución anterior establece una cadena en el DAG, make lo considera de manera diferente; los archivos file-a.out y file-b.out se tratan como archivos intermedios, y de forma predeterminada se eliminan como innecesarios tan pronto como file-c.out esté listo.

Una manera de evitar que se mencionó en algún lugar aquí, y consiste en agregar file-a.out y file-b.out como dependencias de un destino .SECONDARY, lo que evita que se eliminen. Desafortunadamente, esto no soluciona mi caso porque mis reglas usan patrones de comodines; específicamente, mis reglas se parecen más a esto:

file-a-%.out: program file.in 
    ./program $* file.in file-a-$*.out file-b-$*.out file-c-$*.out 

file-b-%.out: file-a-%.out 
    @ 

file-c-%.out: file-b-%.out 
    @ 

modo que uno puede pasar un parámetro que consigue incluido en el nombre del archivo, por ejemplo, mediante la ejecución de

make file-c-12.out 

La solución que make documentación sugiere es agréguelos como reglas implícitas a la lista de dependencias de .PRECIOUS, evitando que estos archivos se eliminen.


La solución con .PRECIOUS obras, sino que también impide que estos archivos se eliminen cuando una regla de falla y los archivos están incompletos. ¿Hay alguna otra manera de hacer que esto funcione?

un corte de resolver esto es para definir un objetivo .SECONDARY con ningún requisito previo, es decir,

.SECONDARY: 

que informa make que todos los archivos deben ser tratados como secundaria y por lo tanto no se elimina, a menos que cuando make se interrumpe o una regla falla Desafortunadamente, esto no permite seleccionar un subconjunto de reglas con comodines para que funcionen de esta manera, por lo que considero esto solo un truco (aunque es útil).

+0

Hmm, no hay madre en los requisitos allí (es decir, está usando file.in en vez de file -%. in). Se vuelve mucho más fácil si construyes el archivo- $ a- $ n.out desde el archivo- $ n.in, y es extraño como está (haz el archivo-c-17.out file-c-18.out) producir salidas idénticas con diferentes nombres a menos que haya alguna fuente de entrada oculta como el tiempo. ¿Podría la regla cambiarse a file-a -%. Out: archivo de programa -%. In? – p00ya

+0

Es irrelevante para la pregunta en cuestión. Estas solo son reglas inventadas, el punto es que contienen comodines. Las reglas reales son significativamente más complicadas, pero esa complejidad escondería el problema que estoy enfrentando. – makesaurus

+0

Consulte mi respuesta para saber por qué es relevante. – p00ya

Respuesta

2

Si, en lugar de un solo archivo.in, las salidas se generaron a partir de un archivo de requisito previo que incluía el eje, es decir,

file-a.out: program file-%.in 
    ./program file-$*.in file-a-$*.out file-b-$*.out file-c-$*.out 

a continuación, puede crear una lista de todos los destinatarios posibles coincidencias:

inputs = $(wildcard file-*.in) 
secondaries = $(patsubst file-%.in,file-a-%.out,$(inputs)) \ 
    $(patsubst file-%.in,file-b-%.out,$(inputs)) 

Del mismo modo, si el tallo proviene de un conjunto finito:

batchnos = 17 18 19 20 
batchnos = $(shell seq 17 20) 
secondaries = $(patsubst %,file-a-%.out,$(batchnos)) $(patsubst %,file-b-%.out,$(batchnos)) 

Entonces sólo tiene que añadir estos como los prerrequisitos en el objetivo .SECONDARIO

.SECONDARY: $(secondaries) 
+0

Esa es una posible solución que no siempre es muy práctica. En mi caso, era más simple dejar '.SECONDARY:' en lugar de enumerar todas las posibilidades. Además, no requiere poner '%' en el nombre del archivo de entrada. Todo lo que necesita es agregar todos los nombres posibles de los archivos de salida a la lista de secundarios. – makesaurus

16

Lo más simple

file-a-%.out file-b-%.out file-c-%.out: program file.in 
    ./program $* file.in file-a-$*.out file-b-$*.out file-c-$*.out 

hará exactamente lo que quiera.

(reglas patrón con múltiples objetivos son diferentes a la regla normal con múltiples objetivos que estabas preguntando por here. Véase el ejemplo de bisontes en el make manual.)

Cuestiones relacionadas