没有目标的 Makefile 规则

Makefile rule with no target

我正在调试一个 makefile,在宏扩展中它创建了一个没有目标的规则(如此:)

: | directoryA
    @echo running $@
    ...

我在网上查了一下,makefile 文档似乎暗示(但没有明确说明)应该至少有一个目标。

使用我当前的 make 版本(gnu Make 4.2.1),它并没有杀死我,但我只是想知道这是否被认为是未定义的行为或者是否支持它,如果是,它应该做什么.

规则确实需要一个或多个目标,文档中确实没有两种方法。例如 GNU make docs notation:

targets : prerequisites
        recipe

1p部分联机帮助页:

target [target...]: [prerequisite...][;command]

插图:

target [:|::] [dependency] ... [; command] ...
               [command]
               ...

毕竟你会如何指代一个没有名字的目标呢?我认为没有目标规则应该是一个错误...

但是,我已经尝试过不同风格的 make(BSD、Illumos、GNU)并且有不同程度的宽容(例如 GNU make 似乎也不再关心先决条件的语法)或缺少它们似乎已经处理了该行并且可能遵循制表符缩进块作为规则(带有配方)......然后被忽略(也是为了确定默认目标)。

我想这实际上被认为是有效的理由 Makefile...你也可能会遇到这种情况:

$(VAR):
        @echo foobar

other:
        @echo barbaz

如果 VAR 未定义或为空,您最终也会得到一个这样的空目标。

I've looked it up online, and the makefile documentation seems to hint (but not explicitly state) that there should be at least one target.

不同的 make 行为可能不同。它们甚至可能根据 makefile 的内容展示对特定 makefile 语法问题的不同处理——例如,如果 makefile 以 .POSIX: 特殊目标的规则开头,那么它可能会被不同地解释该规则被解释。

但是,总的来说,如果您想对什么应该被认为是正确的有某种一般性的想法,那么 the POSIX standard's defintion of make 是一个相当不错的基准。它说:

Target rules are formatted as follows:

target [target...]: [prerequisite...][;command]
[<tab>command<tab>command...]

line that does not begin with <tab>

Target entries are specified by a <blank>-separated, non-null list of targets, then a <colon>, [...]

(强调)。它进一步说

Applications shall select target names from the set of characters consisting solely of periods, underscores, digits, and alphabetics from the portable character set

,从中我们可以推断语法描述是在讨论规则文本 after 宏扩展,因为宏引用可以出现在规则的目标列表中(或字面上的任何地方)在 makefile 中,根据规范),但出现在宏引用中的字符 $(){} 不在其中可以出现在目标中。

makefile 预期内容的 规范确实明确指出目标列表是非空的,并且在您的特定 make 中将其视为权威是合理的的文档不会覆盖它。

I'm just wondering whether [an empty target list] is considered undefined behavior or whether this is supported

您的 makefile 和运行时宏值的组合不符合 POSIX make 的要求。规范没有定义在这种情况下应该发生什么,所以从这个意义上说,行为是未定义的,但“未定义的行为”在这个领域并不是一个像 C 和 C++ 语言规范中那样强大的概念。

鉴于此,我认为任何规则的目标列表为空(在宏展开后)都是一个 makefile 缺陷。尽管您目前正在使用的 make 可能会毫无怨言地接受它,但其他 make 可能会拒绝它或更糟,包括您现在使用的 make 的未来版本。