如何检查shell指令的返回值

Tux*_*ude 25 shell makefile return-value gnu-make

在我的Makefile中,我需要测试当前目录是否是SVN repo,如果不是,我想在Makefile中使用$(error)指令指出错误.

所以我计划使用$(shell svn info.)的返回值,但我不确定如何从Makefile中获取此值.

注意:我不是试图在配方中获取返回值,而是在Makefile的中间.

现在我正在做这样的事情,这只是因为stdout在出错时是空白的:

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

我仍然想知道是否有可能在Makefile中获取返回值.

eri*_*ous 27

如何$?用于回显最后一个命令的退出状态?

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

  • 有没有办法做到这一点,同时保持输出而不是将其定向到“/dev/null”?如果我想调用 $(error $(SVN_INFO)),但只在返回码为“1”时怎么办? (2认同)

ste*_*nct 12

如果你想保留原始输出,那么你需要做一些技巧.如果您有幸拥有GNU Make 4.2(2016-05-22发布)或更高版本,您可以.SHELLSTATUS按如下方式使用该变量.

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)
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用临时文件或使用Make eval来将字符串和/或退出代码存储到Make变量中.下面的例子完成了这个,但我肯定希望看到比这个令人尴尬的复杂版本更好的实现.

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)\"
Run Code Online (Sandbox Code Playgroud)


Tux*_*ude 11

这对我来说很好 - 基于@eriktous的回答,重新定向stdout的一个小修改,以及在有效的svn repo上跳过svn info的输出.

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

  • 我认为@eriktous可能应该得到答案的功劳. (7认同)

Rol*_*lig 6

也许是这样的?

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
Run Code Online (Sandbox Code Playgroud)


Bri*_*rin 6

我使用 .NOTPARALLEL 和 make 函数:

.NOTPARALLEL:   

# 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.
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)))
Run Code Online (Sandbox Code Playgroud)