2008-10-22 8 views
18

Tengo un Makefile que comienza ejecutando una herramienta antes de aplicar las reglas de compilación (que esta herramienta escribe para mí). Si esta herramienta, que es una secuencia de comandos python, sale con un código de estado no nulo, quiero que GNU Make se detenga allí y no continúe con la construcción del programa.

Actualmente, hago algo como esto (nivel superior, es decir, la columna 1):

$(info Generating build rules...) 
$(shell python collect_sources.py) 
include BuildRules.mk 

Pero esto no impide que si collect_sources.py salidas con un código de estado de 1. Esto también captura la salida estándar de collect_sources.py pero no lo imprime, así que tengo la sensación de que estoy mirando en la dirección incorrecta.

Si es posible, la solución incluso debería funcionar cuando un shell simple de MS-DOS es el shell estándar del sistema.

¿Alguna sugerencia?

+1

Si tiene GNU 4.2 o superior, puede verificar la variable '$ (. SHELL_STATUS)' que contendrá el estado de salida de la última función '$ (shell ...)' evaluada. – MadScientist

+0

El nombre de la variable es '$ (. SHELLSTATUS)', sin '_'. https://www.gnu.org/software/make/manual/html_node/Shell-Function.html # Shell-Function – user3159253

Respuesta

4

Ok, aquí está mi propia solución, que por desgracia no se basa en el código de estado del guión collect_sources.py, pero que funciona para mí (TM) y me permite ver cualquier salida que produce la secuencia de comandos:

SHELL_OUTPUT := $(shell python collect_sources.py 2>&1) 
ifeq ($(filter error: [Errno %],$(SHELL_OUTPUT)),) 
    $(info $(SHELL_OUTPUT)) 
else 
    $(error $(SHELL_OUTPUT)) 
endif 

El script se escribe para que cualquier error produzca un resultado que comience con "collect_sources: error:". Además, si python no puede encontrar o ejecutar el script dado, genera un mensaje de error que contiene el mensaje "[Errno 2]" o similar. Así que este pequeño fragmento de código simplemente captura la salida (redireccionando stderr a stdout) y busca mensajes de error. Si no se encuentra ninguno, simplemente usa $(info) para imprimir la salida; de lo contrario, usa $(error), lo que hace que Make se detenga.

Tenga en cuenta que la sangría en ifeq ... endif se hace con espacios. Si se utilizan pestañas, Make cree que está intentando invocar un comando y se queja de ello.

6

Puede haber una mejor manera, pero intentado lo siguiente y funciona:

$(if $(shell if your_command; then echo ok; fi), , $(error your_command failed)) 

Aquí lo hice suponer que your_command no da ninguna salida, pero no debería ser difícil de evitar tales una situacion.

Editar: Para que funcione con el shell predeterminado de Windows (y probablemente cualquier shell decente) puede escribir your_command && echo ok en lugar de if dentro de la función shell. No creo que esto sea posible para shells (antiguos) de DOS. Para estos, probablemente desee adaptar your_command o escribir un script de envoltura para imprimir algo por error (o éxito).

+0

Aunque supone un shell unix. – JesperE

+0

Gracias, parece un paso en la dirección correcta; desearía que se pudiera macroizar como Sherr(), no lo he logrado hasta ahora. –

+0

Solo poniéndolo por ahí, si estás dispuesto a asumir Unix (totalmente), esta fue la única variante que encontré que funcionó. Estaba haciendo algunas tonterías en una 'plantilla de definición' que más tarde fue' $ (eval $ (call template, arg1, arg2) '... que era horrible. Pero funciona totalmente con lo anterior, teniendo cuidado de doubl' $ $ '* todo *. Espero que algún día salga algo beneficioso (el' @ 'al principio es porque estoy en una definición de destino):' @ $$ (si $$ (shell if ./generate.sh $ (2)) $ (1); luego echo "puntaje"; fi),, $$ (error No se puede generar [$ (2)] desde [$ (1)])) ' – sjm324

4

se debe utilizar un plato regular para crear BuildRules.mk:

BuildRules.mk: collect_sources.py 
     python $< >[email protected] 

include BuildRules.mk 

Este es el truco estándar a utilizar al generar automáticamente las dependencias.

+0

Jesper, gracias por su aporte, pero yo no No veo cómo la regla puede solucionar mi problema. Necesito collect_sources.py para ejecutar cada vez, para poder actualizar la lista de archivos y reglas de origen, etc. ¿O me falta algo? –

+0

Agregue un ".PHONY: BuildRules. mk "en la parte superior, entonces. – JesperE

+0

Quizás me esté perdiendo algo obvio aquí, pero parece que no puedo hacer que esto funcione correctamente. BuildRules.mk se rehace todas las veces (usando .PHONY), pero la inclusión ocurre antes de esto está hecho. Esto efectivamente significa que estás siempre s utilizando el BuildRules.mk anterior. – mweerden

-1

Asegúrese de no estar invocando make/gmake con la opción -k.

+0

Su sugerencia parece lógica, pero la verdad es que la opción '-k' no tiene ningún efecto en el comportamiento de' make' sobre los comandos que fallan en la función 'shell'. –

Cuestiones relacionadas