GNU make出现“commands commence before first target”错误

65

在我的makefile中,我想检查一个库是否存在,并给出有用的错误信息。我创建了一个条件语句,当文件未找到时应退出make过程:

 9: ifeq ($(${JSONLIBPATH}),)
10:    JSONLIBPATH = ${ALTJSONLIBDIR}/${LIBJSON}
11: endif
12: ifeq ($(${JSONLIBPATH}),)
13:    $(error JSON library is not found. Please install libjson before building)
14: endif 

我的Makefile卡在第13行:

Makefile:13: *** commands commence before first target.  Stop.

在第13行之后,我的Makefile有了它的目标。

我尝试将这个条件块放入一个目标中(例如一个名为isJSONLibraryInstalled的目标),但是这样不会正确执行。

我应该如何在处理目标之前检查文件是否存在并处理错误情况?如果这是一个愚蠢的问题,请原谅我。

4个回答

95

首先,您正在查看以当前路径命名的变量的内容,这可能不是您想要的。一个简单的环境变量引用是$(name)${name},而不是$(${name})。因此,第13行始终被评估。

其次,我认为它卡在了$(error ...)表达式的缩进上。虽然该表达式解析为空字符串,但该行开头仍有一个制表符,表示一个命令,而该命令不能存在于规则之外。

我认为使用空格而不是制表符来缩进会起作用。


18
更好的表述: 我曾经陷入这个问题很久,因为我使用了制表符而不是空格,导致出现了“*** commands commence before first target”错误。你解决了我的难题,非常感谢... :) - NeonGlow
4
非常敏锐的观察..禁止地方的选项卡 :) - hesham_EE
1
我收到了“missing separator. Stop.”的错误信息。有可能的原因是什么? - Kuldeep Yadav
如果你遇到了“missing operator”错误,很可能是你使用了空格而不是制表符。 - undefined

8
当你遇到Make错误信息时,请始终检查错误信息文档
在GNU Make 3.81中(error似乎已从更新版本中删除),它说:

这意味着makefile中的第一件事似乎是命令脚本的一部分:它以TAB字符开头,并且似乎不是合法的make命令(例如变量赋值)。命令脚本必须始终与目标相关联。

更令人困惑的是"似乎不是合法的make命令"部分。这就解释了为什么在以下情况下:
    a := b
    $(error a)

错误发生在第2行而不是第1行:make 只接受可以解析的语句,比如赋值语句,因此下面的代码可以工作:
    a := b
a:
    echo $a

注意: Stack Overflow 目前将制表符转换为空格, 因此您不能直接将上面的代码复制到编辑器中。

error 函数在 GNU Make 4.2.1 版本仍然可用。 - Johannes Bittner

1
您可以使用 VSCode [查看 > 渲染空格] 来检查空格空格制表符
如下图所示:
  • 命令1 在结尾处有一个 制表符 (->) 和 空格
  • 命令2 在开头有一个 空格
  • 命令3/4 有一个制表符+空格

enter image description here

因此,您应该删除结尾处的空格并使用相同的操作添加相同数量的空格,例如:像以下这样的制表符

enter image description here


1
对我来说,连接符前面的不必要的空白是导致这个问题的原因。 在SlickEdit中,我选择了查看所有特殊字符的选项,并注意到了这个黑羊。

关闭,是在$(error ...替换之前不必要的制表符引起了错误。删除它或用空格替换它会使错误消失。 - Ross Ridge

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接