【问题标题】:Assign shell output to variable or exit ( terminate makefile )将 shell 输出分配给变量或退出(终止 makefile)
【发布时间】:2018-06-21 00:18:38
【问题描述】:

如果 shell 命令输出 $$,我如何终止 Makefile 并出现错误? -ne 0 ?

HELPER := $(shell dirname $(abspath $(lastword 
VERSION ?= $(shell . $(HELPER); getVersion) ||  (echo "getVersion failed '$$?' status"; exit 1)

test:
        @echo "What is going on?$(VERSION) ?"

helper.sh:

#!/bin/bash
printError() {
    echo "[MAKE] $1" 2>/dev/stderr
}
getVersion() {
    version=$(git describe --exact-match --tags $(git log -n1 --pretty='%h') 2>/dev/null)
    if [ $? -ne 0 ]; then
        printError "Getting git tag for version failed. Checkout existing tag or"
        printError "provide your own version 'make <action> VERSION=<your-version>'"
        exit 1
    fi
    echo "${version}"
    exit 0
}

输出:

$ make test
What is going on?[MAKE] Getting git tag for version failed. Checkout existing tag or [MAKE] provide your own version 'make <action> VERSION=<your-version>' ||  (echo getVersion failed $? status; exit 1) ?

我无法在出错时终止它( getVersion 返回 1 ),但通过管道传送到 /dev/stderr 的错误消息也正在到达 VERSION 变量

【问题讨论】:

  • Makefile 问题应该标记为 make,而不是 shell。 Make 语法不是 shell 语法——它用于生成 shell 命令,但它本身就是非常不同的东西。
  • 另见stackoverflow.com/a/59392005/491884,您可以使用hack(使用|| kill $$PPID杀死父制作过程。

标签: bash makefile


【解决方案1】:

首先,回答额外的问题。这条线显然是错误的;我假设您只是遇到了剪切/粘贴错误:

HELPER := $(shell dirname $(abspath $(lastword 

我不知道你为什么要在这里闯入 shell 并运行它的 dirname 但无论如何。

其次,这来自您的帮助脚本:

echo "[MAKE] $1" 2>/dev/stderr

根本不做你想做的事:它说“将输出带到文件描述符2(stderr)并将其通过管道传输到/dev/stderr。由于echo不会向stderr打印任何内容,这基本上是一个否-op. 您似乎想将 stdout(文件描述符 1)重定向到 stderr;应该是这样的:

echo "[MAKE] $1" >/dev/stderr

虽然写这个更正确和便携的方式是:

echo "[MAKE] $1" 1>&2

将 fd1 设置为写入 fd2 正在写入的任何位置。

现在谈谈你真正的问题:make 没有像 ||&amp;&amp; 这样的 shell 运算符的概念,所以在这里:

VERSION ?= $(shell . $(HELPER); getVersion) ||  (echo "getVersion failed '$$?' status"; exit 1)

|| 等被简单地视为文本;它将VERSION 设置为字符串:

 <whatever `shell`prints> ||  (echo "getVersion failed '$$?' status"; exit 1)

这正是你所看到的。

如果你有足够新的 GNU make 版本(4.2 或更高版本),你可以使用.SHELLSTATUS 变量来找出最后一个 shell 的退出状态。然后你可以这样做:

.SHELLSTATUS = 0
VERSION ?= $(shell . $(HELPER); getVersion)
$(if $(filter-out 0,$(.SHELLSTATUS)),$(error getVersion failed '$(.SHELLSTATUS)' status))

(你必须先设置它,因为你在这里使用?=,所以有时不会调用shell函数)。

如果您需要移植到早期版本的 GNU make,或者您只是希望使用更清晰的东西,您可以检查 VARIABLE 的值。如果您更改脚本,以便将错误写入 stderr 并且在失败时不向 stdout 写入任何内容,您可以使用:

VERSION ?= $(shell . $(HELPER); getVersion)
$(if $(VERSION),,$(error getVersion failed))

【讨论】:

  • 我已将我的 printError 重定向到 1>&2 但现在 VERSION 变量包含错误消息。每次我使用 $(VERSION) 时,我认为它是空的,我都会在终端上打印出错误消息。
  • 你一定是做错了什么或者不同。我运行了这个:echo 'VER := $(shell echo hi 1&gt;&amp;2) | make -f- 并打印了hi,如果在VER 变量中捕获输出,它就不会这样做。
猜你喜欢
  • 2012-02-23
  • 1970-01-01
  • 1970-01-01
  • 2011-01-02
  • 1970-01-01
  • 2013-04-10
  • 2012-01-27
  • 2016-09-08
  • 2017-07-21
相关资源
最近更新 更多