Makefile中的错误处理

这个 Makefile 有什么问题?

我想编译一些 lua 文件以检查是否有任何意外定义的全局变量。我通过 grep luac -l 的输出,然后忽略已知的全局变量来实现这一点。

因此,对于给定的 lua 文件,只要 grep 找不到任何东西并忽略了已知的 lua 全局变量,就说明一切都正常。

由于 grep 的返回状态码为 0(如果它找到了东西)和 1(如果没有),我想要在 grep 的状态码为 0 时强制引发错误,在它不是 0 时允许一切继续。

Makefile 如下所示

IGNORE_GLOBALS = "dofile\|string\|tostring\|tonumber\|math\|io\|type\|os\|table\|pairs\|next\|require"

all: $(patsubst src/common/%.lua, %.lua, $(wildcard src/common/*.lua))

%.lua:
    @echo check $@
    @luac -l src/common/$@  | grep '.ETGLOBAL' | grep -v $(IGNORE_GLOBALS) && $(error Unexpected globals in $@) || echo "No unexpected globals in $@"

但是,当我运行它时,它会立即退出第一个文件,这个文件恰好没有意外的全局变量,出现以下错误:

Makefile:10: *** Unexpected globals in chat-cmd.lua. Stop.

第 10 行令人惊讶地是前一行,即

@echo check $@

有趣的是,如果我将 $(error ...) 替换为 echo ...,如下所示:

@luac -l src/common/$@  | grep '.ETGLOBAL' | grep -v $(IGNORE_GLOBALS) && echo "Unexpected globals in $@" || echo "No unexpected globals in $@"

它就按预期行事。

点赞
用户258523
用户258523

正如 @siffiejoe 在评论中所说。$(error) 是 make 函数,并且在整个配方被评估时运行(如果这有助于理解,可以将其视为提升)。

因此,一旦需要运行配方(并执行第一行),$(error) 调用将被评估。

注意:在 shell 中,X && Y || Z 不是三元操作。如果 X 成功且 Y 失败,以及当 X 失败时,将运行 Z。这在这里并不重要,因为 echo 实际上不能失败,但通常值得注意。

你想用类似这样的东西 @! lua ... | grep -v $(IGNORE_GLOBALS) || { echo 'Unexpected globals in $@'; exit 1; }。这不会输出“一切正常”的消息,但会消除 X && Y || Z 三元问题。

如果想要保留该消息,最简单的方法是转移到实际的 if 语句。

2014-11-11 15:33:43