为什么得到“ Makefile:1:***缺少分隔符。停止。”用“ set -e”?

时间:2019-12-17 15:02:03

标签: makefile syntax-error gnu-make

我有一个单行 Makefile,该文件抛出以下错误:Makefile:1: *** missing separator. Stop。我知道有dozens of duplicate questions带有相同的错误消息,但是大多数建议都与不使用制表符或神秘的特殊字符有关。

$ cat -e -v -t Makefile 
set -e$

$ make
Makefile:1: *** missing separator.  Stop.

据我所知,没有神秘的特殊字符。也许有些字符cat -e -v -t没有显示?

以下方法有效,因此我猜我的make安装不是问题:

$ cat -v -e -t Makefile 
foo:$
^Iecho "Foo"$

$ make
echo "Foo"
Foo

一些相关的版本和shell信息。

$ make --version
GNU Make 3.81

$ echo $0
-bash

编辑:查看@AProgrammer的评论

请注意,无论我在set -e下面有什么内容,它都会抛出相同的错误消息。

$ cat -e -v -t Makefile 
set -e$
$
foo:$
^Iecho "foo"$

$ make
Makefile:1: *** missing separator.  Stop.

编辑2:

注意添加#!/bin/bash会引发相同的错误消息。

$ cat -e -v -t Makefile 
#!/bin/bash$
set -e$
$
foo:$
^Iecho "foo"$

$ make
Makefile:2: *** missing separator.  Stop.

编辑3:

直接在我的shell上运行set -e似乎可以正常工作(它按预期退出失败的make调用)。

$ set -e
$ make
Makefile:2: *** missing separator.  Stop.
Saving session...completed.
Deleting expired sessions...11 completed.

[Process completed]

1 个答案:

答案 0 :(得分:1)

make完全没有理由能够解释规则外的任意shell命令。

如果您想在出现错误时立即退出规则,可以通过多种方式来实现,或多或少可移植。

首先,规则的每一行都由外壳程序的单独实例执行。这意味着,如果您不手动合并它们(使用\;),则如果每行只有一个命令,则会得到所需的行为。

然后,您可以将set -e用作可能的少数几个需要它的规则的一部分。例如;

foo:
        set -e; for i in a b c d; mkdir $$i; done

使用GNU Make,您可以更改用于调用Shell的标志,另外传递-e

.SHELLFLAGS=-ec

使用POSIX Make,可以更改外壳。我不知道是否支持传递标志,但是对于GNU Make来说似乎如此:

SHELL=/bin/sh -e

但是您总是可以通过一个包装器,该包装器可以根据需要设置标志:

SHELL=/path/to/mywrapper

mywrapper

#!/bin/sh
exec /bin/sh -e "$@"