【问题标题】:Why .PHONY:target and not target:.PHONY?为什么 .PHONY:target 而不是 target:.PHONY?
【发布时间】:2012-07-20 04:04:07
【问题描述】:

我仍然不明白为什么 Makefile 中的“假”规则将“.PHONY”作为它们的目标。作为先决条件,它会更合乎逻辑。

我需要详细说明吗?如果A 依赖于BB 是假的,那么A 也是假的。所以依赖图.PHONYBA.PHONYBA 相比是非常令人惊讶的。 (另一个论点是make 的实现必须非常特殊地处理.PHONY 目标。)

虽然这种批评可能看起来相当理论化(毫无意义) - “既然 make 是如此古老,它的语法就在这里留下来”。但我不建议任何语法更改,有一个替代方案:

使用 GNU Make(至少),以下 Makefile 声明了一个虚假的 target_A

target_A: _PHONY
        touch target_A

_PHONY:
        #noop

问题 1这太简单了,我肯定不是它的第一个发明者。事实上,考虑到这个替代方案,为什么make 需要特殊语法?

在我看来,这也可以很好地解决有关wildcards in phony targets 的问题,甚至可以在初学者有疑问时解决shed some light on .PHONY's meaning

问题 2你能想到这种方法在哪些情况下是劣等的吗? (调用make .PHONY 有什么用吗?)

(我应该提到,虽然我调用了其他 makes,但 GNU Make 是我唯一有经验的实现 - 读取和编写 Makefile。)

【问题讨论】:

  • (应该是 RTFM)GNU Make 手册实际上 mentions this recipe 效率较低,但更便携。我猜想速度增益可以忽略不计。这表明对问题 2 的回答是否定的。(?)

标签: makefile gnu-make target


【解决方案1】:

使用target_A: .PHONY 的一个大问题是它使得使用许多make 的内置变量变得更加困难。以这个常见的食谱为例:

%.a: $(OBJ_FILES)
    $(LD) $(LFLAGS) -o $@ $^

$^ 变量引入了作为先决条件列出的所有内容。如果.PHONY 也列在那里,那么它将被传递给命令行上的链接器,这可能不会导致任何好的事情发生。使用像.PHONY 这样的元目标作为先决条件会使这些内置变量的用处大大降低,因为每次使用它们时都需要像$(filter-out .PHONY,$^) 这样的大量额外处理。为了考虑依赖树,颠倒关系并将.PHONY作为目标有点尴尬,但它清理了makefile的其余部分。

【讨论】:

  • 哦,我明白了。 other "special" targets 的存在——包括一些根本不适合(语义上)进入依赖关系图的东西——似乎减轻了“为什么这么特别”的反对意见。