为什么.PHONY:目标而不是目标:.PHONY?
我仍然不明白为什么Makefiles中的“假冒”规则有“.PHONY”作为他们的目标。 作为一个先决条件,这会更合乎逻辑。
我必须详细说明吗? 如果A
依赖于B
而B
是假的,那么A
也是假的。 因此,与.PHONY
→ B
→ A
相比,依赖关系图.PHONY
← B
→ A
是令人惊讶A
。 (另一个说法是make
的实现必须处理.PHONY
目标非常特殊。)
虽然这种批评看起来可能相当理论化(毫无意义) - “既然make是如此古老,它的语法就是留在这里”。 但我不提议任何语法变化,还有一个选择:
使用GNU Make(至少),下面的Makefile声明了一个伪造的target_A
:
target_A: _PHONY
touch target_A
_PHONY:
#noop
问题1 :这是如此简单和干净,我当然不是它的第一个发明者。 事实上,由于这种替代,为什么make
以往任何时候都需要特殊的语法?
在我看来,这样做也可以很好地解决虚假目标中通配符的问题,甚至可以在初学者怀疑时提供.PHONY的含义。
问题2 :你能想到这种方法较差的情况吗? (正在调用make .PHONY
的任何用途?)
(我应该提到,虽然我已经调用了其他make
,但是GNU Make是我有一些经验的唯一实现 - 读写Makefiles。)
使用target_A: .PHONY
一个大问题是,它使得使用许多make的内置变量要困难得多。 以这个通用配方为例:
%.a: $(OBJ_FILES)
$(LD) $(LFLAGS) -o $@ $^
$^
变量引入了作为先决条件列出的所有内容。 如果.PHONY
也列在那里,那么它将被传递给命令行上的链接器,这可能不会导致任何事情发生。 使用像.PHONY
这样的元目标作为先决条件会使这些内置变量的用处大大减少,因为每次使用它们时都需要进行大量额外处理,如$(filter-out .PHONY,$^)
。 为了考虑依赖关系树,反转关系并改为创建.PHONY
目标有点尴尬,但它清除了makefile的其余部分。