2009-03-12 12 views
7

Últimamente estamos discutiendo sobre la forma en que manejamos los archivos .d para las dependencias en nuestro proceso de compilación basado en make. Se ha planteado el problema de que a veces los archivos .d se pueden dañar cuando se interrumpen las compilaciones.Cómo hacer para eliminar archivos adicionales en caso de error

Estamos utilizando el destino .DELETE_ON_ERROR para garantizar que si una compilación se interrumpe o falla, los archivos de objeto que estaba en proceso de generación se eliminan. Sin embargo, también estamos usando GCC para generar archivos .d en tiempo de compilación, que también deberían eliminarse. No parece haber una forma directa de decir sobre esto.

Entonces, la pregunta es, ¿hay alguna manera de convencernos para eliminar nuestro objeto y nuestros archivos de dependencia en caso de error? ¿Hay alguna forma en que podamos configurar las reglas para que sepa que los archivos .d y .o se generan al mismo tiempo y deben eliminarse si hay un error?

O bien, ¿hay algo más que podamos hacer para solucionar el problema de los archivos .d corruptos? Una sugerencia en este sentido es generar los archivos .d con un nombre temporal y tener un paso de compilación posterior por cada archivo que lo copie al nombre correcto.

Respuesta

6

En términos generales, GNU make no admite destinos con múltiples salidas. Sin embargo, hay una excepción a esa regla: reglas de patrones. Si puede estructurar su archivo MAKE de modo que use reglas de patrones para generar los archivos objeto, puede lograr sus objetivos. Por ejemplo:

.DELETE_ON_ERROR: 

all: foo.o 

%.o %.d: %.c 
    @touch $*.d 
    @touch $*.o 
    @exit 1 

verá que con este archivo MAKE cuando se detecta el "error" en la regla, tanto el .dy el archivo .o se eliminan. La ventaja de este enfoque es que expresa con mayor precisión el gráfico de dependencia al describir cómo se generará el archivo .d y qué regla lo generará.

Como alternativa, un paradigma común en este caso es el que usted sugirió: haga que GCC genere el archivo .d en un nombre de archivo temporal y muévalo solo en su lugar después de que el comando GCC se haya completado correctamente. Por lo general, esto se logra con un efecto de la cáscara:

all: foo.o 

%.o: %.c 
    gcc -o [email protected] -MMD -MF $(basename [email protected]).d.tmp -c $< \ 
     && mv $(basename [email protected]).d.tmp $(basename [email protected]).d 

Aquí el truco "mágica" es el uso de las banderas del CCG -MMD, que genera el archivo de dependencia como un efecto secundario de la compilación, y -MF, que le permite especificar el nombre de salida para el archivo de dependencia; y el uso de la sintaxis shell cmd1 && cmd2, que provoca que el shell ejecute solo cmd2 si cmd1 finaliza correctamente.

+0

El '.DELETE_ON_ERROR:' en la parte superior del archivo make me permite deshacerme de todos mis archivos temporales. ¡Gracias! –

+0

Sugeriría poner el mv como la segunda línea en la receta para la regla de patrón "% .o:% .c".No veo ningún cambio en el comportamiento ni en los beneficios del uso del intérprete de comandos '&&' para colocarlo en la primera línea. –

+0

@RichardPerrin su propuesta producirá un comportamiento incorrecto si se invoca gmake con la opción '-i' (ignorar errores). En ese caso, su versión ejecutará el comando 'mv' ya sea que haya o no un error en' gcc', mientras que mi original no lo hará. –

-1

No obtuve ninguno de los ejemplos de Eric para que funcionen correctamente. GCC (versión 4.4) no compila nada cuando pasa el modificador -MM para que no parezca que puede compilar y escribir el .d de una vez. Esto es lo que hice:

%.o: %.c 
    @rm -f [email protected] $(patsubst %.o,%.d,[email protected]) 
    gcc -c $< -o [email protected] 
    @$(CXX) -MM -MG > $(patsubst %.o,%.d,[email protected]) 

Se comienza por la eliminación de un archivo .d existente, la tercera línea que genera el nuevo sólo se ejecuta si el segundo comando, el paso de compilación real, tiene éxito (& & truco de Eric no es necesario, make hace esto automáticamente). Por alguna razón que no entiendo, un archivo .o existente no se elimina automáticamente si la compilación falla, pero eso se resolvió fácilmente agregando [email protected] al primer rm.

+0

Correcto, gcc no compilará el archivo si solo especifica '-MM'. También debe usar '-MF' como se describe en mi respuesta original. –

+0

@Eric Añadí el modificador -MF también, pero el preprocesador parece no enviar ningún resultado a la parte del compilador de gcc, así que termino con un archivo de objeto de cero bytes ... – Wim

+0

Disculpa, cometí un error: tu quiere '-MMD', no' -MM'. Corregí la respuesta original también. –

Cuestiones relacionadas