我仍然不明白为什么Makefiles中的“虚假”规则将“.PHONY”作为目标.作为先决条件,这将更合乎逻辑.
我需要详细说明吗?如果A依赖于B而B是假的,那么A也是假的.所以依赖图.PHONY←B→A与.PHONY→B→A相比是令人惊讶的. (另一个论点是make的实现必须处理非常特殊的.PHONY目标.)
虽然这种批评似乎相当理论化(毫无意义) – “因为制作是如此古老,它的语法就在这里”.但我不建议任何语法更改,有一个替代方案:
使用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有用吗?)
(我应该提一下,虽然我调用了其他品牌,但GNU Make是我有一些经验的实现 – 阅读和编写Makefile.)
解决方法
使用target_A:.PHONY的一个大问题是它使得使用许多make的内置变量变得更加困难.以这个常见的食谱为例:
%.a: $(OBJ_FILES) $(LD) $(LFLAGS) -o $@ $^
$^变量拉入列为先决条件的所有内容.如果.PHONY也在那里列出,那么它将被传递给命令行上的链接器,这可能不会导致任何好的事情发生.使用像.PHONY这样的元目标作为先决条件会使这些内置变量显得不那么有用,因为它们每次使用时都需要大量的额外处理,如$(filter-out .PHONY,$^).为了考虑依赖树,反转关系而不是使.PHONY成为目标有点尴尬,但它清理了makefile的其余部分.