2011-09-12 7 views
18

En mi archivo Makefile, necesito comprobar si el directorio actual es un repositorio SVN o no, y si no lo está, quiero indicar un error usando la directiva $ (error) en Makefile .Cómo verificar el valor devuelto por la directiva de shell

Así que planeo usar el valor de retorno de $ (shell svn info.) Pero no estoy seguro de cómo obtener este valor dentro del Makefile.

Nota: No estoy tratando de obtener el valor de retorno en una receta, sino en el medio del Makefile.

En este momento estoy haciendo algo como esto, que trabaja sólo por la salida estándar está en blanco cuando se trata de un error:

SVN_INFO := $(shell svn info . 2> /dev/null) 
ifeq ($(SVN_INFO),) 
    $(error "Not an SVN repo...") 
endif 

Todavía gustaría saber si es posible obtener la devolución valor en su lugar dentro del Makefile.

+3

Curiosamente, nunca fue capaz de conseguir GNU Make de [ '.SHELLSTATUS' variable] (https://www.gnu.org/software/make/manual/html_node/Shell-Function.html) para que funcione como se esperaba. Siempre estaba vacío. Tuve que usar los métodos a continuación. – jww

Respuesta

11

Esto funcionó bien para mí - sobre la base de la respuesta @eriktous' con una modificación menor de redirigir la salida estándar, así que no tome la salida de información de SVN en un repositorio SVN válida.

SVN_INFO := $(shell svn info . 1>&2 2> /dev/null; echo $$?) 
ifneq ($(SVN_INFO),0) 
    $(error "Not an SVN repo...") 
endif 
+2

Creo que @eriktous probablemente debería haber recibido el crédito por la respuesta. – jww

4

Tal vez algo como esto?

IS_SVN_CHECKED_OUT := $(shell svn info . 1>/dev/null 2>&1 && echo "yes" || echo "no") 
ifne ($(IS_SVN_CHECKED_OUT),yes) 
    $(error "The current directory must be checked out from SVN.") 
endif 
+0

Gracias Roland - Tengo la idea general para mi solución final tanto de tuya como de la de Eriktous :) – Tuxdude

22

Cómo sobre el uso $? a hacerse eco del estado de salida de la última orden?

 
SVN_INFO := $(shell svn info . 2> /dev/null; echo $$?) 
ifeq ($(SVN_INFO),1) 
    $(error "Not an SVN repo...") 
endif 
+0

Gracias @eriktous - Buen truco - no pensé en eso ... Tuve que hacer algunas modificaciones menores para que funcionara - He publicado mi respuesta en función de su entrada :) – Tuxdude

+1

¿Hay alguna manera de hacerlo, manteniendo la salida en lugar de dirigirla a '/ dev/null'? ¿Qué sucede si deseo llamar $ (error $ (SVN_INFO)), pero solo cuando el código de retorno es "1"? – jeremfg

2

Si desea conservar la salida original, entonces necesita hacer algunos trucos. Si tiene la suerte de tener GNU Make 4.2 (lanzado el 22-05-2016) o más tarde a su disposición, puede usar la variable .SHELLSTATUS de la siguiente manera.

var := $(shell echo "blabla" ; false) 

ifneq ($(.SHELLSTATUS),0) 
    $(error shell command failed! output was $(var)) 
endif 

all: 
    @echo Never reached but output would have been $(var) 

Como alternativa puede usar un archivo temporal o jugar con Make de eval para almacenar la cadena y/o el código de salida en una variable Make. El siguiente ejemplo lo hace, pero ciertamente me gustaría ver una mejor implementación que esta versión embarazosamente complicada.

ret := $(shell echo "blabla"; false; echo " $$?") 
rc := $(lastword $(ret)) 
# Remove the last word by calculating <word count - 1> and 
# using it as the second parameter of wordlist. 
string:=$(wordlist 1,$(shell echo $$(($(words $(ret))-1))),$(ret)) 

ifneq ($(rc),0) 
    $(error shell command failed with $(rc)! output was "$(string)") 
endif 

all: 
    @echo Never reached but output would have been \"$(string)\" 
+0

Cuando trato de usar '$ (. SHELLSTATUS)' en GNUmake en Solaris, está vacío. '$ (info" estado: $ (. SHELLSTATUS) ")' imprime nada. – jww

+0

@jww: ¿has comprobado la versión? 4.2 es relativamente nuevo (para distribuciones estables) y puede que no se haya propagado a donde sea que tengas el tuyo :) 'make -v' No conozco otras razones que no sean para tu problema. – stefanct

0

utilizo un par hacen funciones:

# This function works almost exactly like the builtin shell command, except it 
# stops everything with an error if the shell command given as its argument 
# returns non-zero when executed. The other difference is that the output 
# is passed through the strip make function (the shell function strips only 
# the last trailing newline). In practice this doesn't matter much since 
# the output is usually collapsed by the surroundeing make context to the 
# same result produced by strip. WARNING: don't try to nest calls to this 
# function, take a look at OSHELL_CHECKED instead. 
SHELL_CHECKED =              \ 
    $(strip               \ 
    $(if $(shell (($1) 1>/tmp/SC_so) || echo nonempty),    \ 
     $(error shell command '$1' failed. Its stderr should be above \ 
       somewhere. Its stdout is in '/tmp/SC_so'),   \ 
     $(shell cat /tmp/SC_so))) 

# "Other" SHELL_CHECKED. Like SHELL_CHECKED, but uses different file names 
# and so may be used with arguments that themselves use SHELL_CHECKED 
# or vice versa. In other words, a hack to allow two-level nesting of 
# checked shell calls by hardwiring the call points involved to not both 
# use SHELL_CHECKED or OSHELL_CHECKED. 
OSHELL_CHECKED =              \ 
    $(strip               \ 
    $(if $(shell (($1) 1>/tmp/OSC_so) || echo nonempty),    \ 
     $(error shell command '$1' failed. Its stderr should be above \ 
       somewhere. Its stdout is in '/tmp/OSC_so'),   \ 
     $(shell cat /tmp/OSC_so))) 

Estos pueden ser llamados de este modo:

$(call SHELL_CHECKED,some_command $(call OSHELL_CHECKED,other_command some_arg)) 
Cuestiones relacionadas