Pregunta

Tengo un makefile ligeramente hacker para la ejecución de pruebas:

### Run the tests

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

test: $(tests)

$(tests): %: %.c
    gcc -o $@ $(testflags) $<
    $@

Funciona, pero hace Hacer hacer algo que nunca he visto hacer antes. Mi prueba es actualmente roto, y provoca un error de bus. Hacer da el siguiente resultado:

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 que antes de conformarse. ¿Por qué hacer borrar la prueba recopilada?

Nota: He editado este ejemplo bastante fuerte para hacerlo más sencillo. Podría haber introducido algunos errores.

¿Fue útil?

Solución

Debido a que el objetivo no podría haber sido construido correctamente. La próxima vez que make el proyecto, se intentará reconstruir el objetivo. Si el archivo no había sido retirado, make no tendría forma de saber algo salió mal. make no puede saber que el fracaso venía de una prueba más que el proceso que se basa el objetivo.


Si o no este comportamiento es deseable en su caso depende de la naturaleza de las pruebas. Si usted planea en la fijación de la prueba para que no cause un Bus error, quitando el objetivo no es un gran problema. Si desea utilizar el destino para depurar más tarde, tendrá que realizar un cambio en su proceso de maquillaje.

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


Otra podría ser:

$(tests): %: %.c
    gcc -o $@ $(testflags) $<
    -$@

No se ha probado, pero la documentación del indica el objetivo no ser eliminado:

  

Cuando ocurre un error que hacen que no se le ha dicho a ignorar, implica que el objetivo actual no puede ser rehecha correctamente, y así tampoco cualquier otra que depende de él, ya sea directa o indirectamente. No hay más órdenes serán ejecutadas por estos objetivos, ya que no se han alcanzado sus condiciones previas.

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 es hasta la fecha, por lo que la próxima vez que haga carreras, no va a tratar de actualizar ese archivo. La situación es la misma que cuando el comando es matado por una señal; ver interrupciones. Por lo general, lo que hay que hacer es eliminar el archivo de destino si el comando falla después de comenzar a cambiar el archivo. que va a hacer esto si .DELETE_ON_ERROR aparece como un objetivo. Esto es casi siempre lo que quiere hacer que hacer, pero no es práctica histórica; por lo que para la compatibilidad, debe solicitar explícitamente.

Otros consejos

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 $@ $(testflags) $<

runtests: %.out: %
    $< | tee $@

(probablemente hay errores en mi sintaxis de marca, a nadie se sienten libres para corregirlo.) La idea general es tener la prueba de funcionamiento generar un archivo de salida, lo que hace que sea más fácil para make para ejecutar cada prueba individual.

Este es el comportamiento por defecto de maquillaje. Cuando un comando devuelve un código de error (por ejemplo no nulo de retorno) a continuación, se elimina el objetivo make. Las directivas makefile .PRECIOUS y .IGNORE pueden cambiar este comportamiento.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top