¿Por qué falla diff cuando se invoca desde un Makefile?

Reducción de un problema de parche que estoy tratando de solucionar: solo dos files, cada uno con un tamaño de 1 byte:

  • file a (que contiene 'a' )
  • file b (que contiene 'b' ) y

El objective es crear y luego aplicar un parche que cambie el valor de 'b' a 'a' . Los contenidos de Makefile son:

 patch: diff -uba > b2a.patch patch -o b.corrected b < b2a.patch diff a b.corrected clean: rm -f b2a.patch b.corrected 

Dado lo anterior, make falla con el siguiente resultado:

 $ make diff -uba > b2a.patch make: *** [patch] Error 1 

Sin embargo, si ejecuto los commands en el Makefile uno después del otro en el shell bash, no hay ningún problema.

Hacer asume que un código de salida de 0 significa éxito, cualquier otra cosa significa fracaso. Esta es la convención estándar utilizada por casi todas las herramientas de command-line.

Desafortunadamente, diff no es uno de esos. Verificando la página de información de diff de GNU, y también la input de "diff" de la especificación de Unix único , 0 significa que no se encontraron diferencias, 1 significa que se encontraron diferencias, y ≥2 significa error.

Puede hacer que Make ignore el estado de salida por completo anteponiendo el command con un guión, como lo hizo en su comentario, pero esto ignorará los errores reales, probablemente no lo que desea. En cambio, puedes:

 patch: diff -uba > b2a.patch; [ $$? -eq 1 ] patch -o b.corrected b < b2a.patch diff a b.corrected; [ $$? -eq 1 ] 

Tenga en count el ; [ $$? -eq 1 ] ; [ $$? -eq 1 ] ; [ $$? -eq 1 ] bit que he agregado al final de las dos líneas de diff. Puedes usar ; test $$? -eq 1 ; test $$? -eq 1 ; test $$? -eq 1 también, por supuesto. ¿El $? la variable de shell es $$? debido a las convenciones normales de escape de Makefile. Tenga en count que esto también rechaza el estado de salida 0 (sin diferencias), que es probablemente lo que desea.

Por cierto: parece que esto realmente debería ser:

 patch: b.corrected diff … b.corrected: b2a.patch patch … b2a.patch: ab diff … 

para que las modificaciones de a y b se recojan y los files se regeneren correctamente.