2009-02-26 17 views
11

Tengo un makefile ligeramente hacker para la ejecución de pruebas:¿Por qué GNU make eliminar un archivo

### Run the tests 

tests := tests/test1 tests/test2 ... 

test: $(tests) 

$(tests): %: %.c 
    gcc -o [email protected] $(testflags) $< 
    [email protected] 

Funciona, pero las marcas Marca hacer algo que nunca he visto hacer antes. Mi prueba actualmente está rota y causa un error de bus. Haga la siguiente salida:

gcc -o tests/test1 [flags blah blah] tests/test1.c 
tests/test1 
make: *** [tests/test1] Bus error 
make: *** Deleting file `tests/test1' 

Tengo curiosidad acerca de la última línea. Nunca he visto Hacer eso antes. ¿Por qué Make elimina la prueba compilada?

Nota: he editado este ejemplo bastante para simplificarlo. Podría haber introducido algunos errores.

Respuesta

14

Porque es posible que el destino no se haya creado correctamente. La próxima vez que make el proyecto intente reconstruir el objetivo. Si el archivo no se ha eliminado, make no tendría forma de saber que algo salió mal. make no puede saber que la falla proviene de una prueba en lugar del proceso que crea el objetivo.


Si este comportamiento es deseable en su caso depende de la naturaleza de las pruebas. Si planea arreglar la prueba para que no cause un Bus error, eliminar el objetivo no es un gran problema. Si desea utilizar el destino para la depuración más adelante, deberá realizar un cambio en su proceso de creación.

Una forma de no eliminar objetivos es utilizar el objetivo .PRECIOUS.


Otra podría ser:

$(tests): %: %.c 
    gcc -o [email protected] $(testflags) $< 
    [email protected] 

no han sido evaluados, pero el documentation indica el objetivo no será removido:

Cuando ocurre un error que hacen que no se le ha dicho a ignorar , implica que el objetivo actual no puede rehacerse correctamente, ni tampoco puede hacerlo cualquier otro que dependa de él directa o indirectamente. No se ejecutarán más comandos para estos objetivos, ya que sus condiciones previas no se han logrado.

y:

Por lo general, cuando un comando falla, si ha cambiado el archivo de destino en absoluto, el archivo está dañado y no puede ser utilizado, o al menos no se encuentre totalmente actualizado. Sin embargo, la marca de tiempo del archivo dice que ahora está actualizado, por lo que la próxima vez que se ejecute, no intentará actualizar ese archivo. La situación es la misma que cuando una señal mata al comando; ver interrupciones. Por lo tanto, generalmente lo correcto es eliminar el archivo de destino si el comando falla después de comenzar a cambiar el archivo. make hará esto si .DELETE_ON_ERROR aparece como un objetivo. Esto es casi siempre lo que quieres hacer, pero no es una práctica histórica; por lo tanto, para compatibilidad, debe solicitarlo explícitamente.

11

Una forma de evitar este comportamiento es la de dividir la construcción y ejecución de la prueba en dos pasos:

tests := tests/test1 tests/test2 ... 

test: $(tests) runtests 

$(tests): %: %.c 
    gcc -o [email protected] $(testflags) $< 

runtests: %.out: % 
    $< | tee [email protected] 

(Probablemente hay errores de sintaxis en mi maquillaje, nadie se siente libre para corregirlo.) La idea general es hacer que la ejecución de prueba genere un archivo de salida, lo que hace que sea más fácil para make ejecutar cada prueba individualmente.

+1

+1 por ser la única respuesta para señalar que el comportamiento fue causado por un archivo MAKE defectuoso que combinó la generación del programa de prueba y su ejecución en una sola regla. –

+0

IMO esta es la mejor solución: limpiador y más "similar". Aunque, los detalles podrían manejarse más limpiamente. Primero, el autor del archivo MAKE debe decidir: ¿desea? Siempre ejecutar las pruebas, o solo ejecutar las pruebas si el archivo de prueba fue reconstruido (esto último es lo que hizo el ejemplo original). – MadScientist

6

Este es el comportamiento predeterminado de make. Cuando un comando devuelve un código de error (por ejemplo, un retorno distinto de cero), el objetivo de fabricación se elimina. Las directivas .PRECIOUS y .IGNORE de archivo MAKE pueden cambiar este comportamiento.

Cuestiones relacionadas