【问题标题】:Why "make all" works as expected without adding "all" to .PHONY target?为什么“全部”按预期工作而不将“全部”添加到 .PHONY 目标?
【发布时间】:2018-07-07 18:15:51
【问题描述】:

我知道 .PHONY 的作用。

如果在我的 Makefile 所在的文件夹中,我添加一个名为 clean 的空文件,并且在我运行 make clean 后,所有的 clean 目标都不会被执行,因为文件中没有任何更改,所以目标不会运行,这是正确的。 如果我添加 .PHONY: clean,则 clean 被视为命令,这也是正确的。

我的问题是为什么这种行为不会发生在 all 目标上,因为我在文件夹中添加了一个 all 文件。所以基本上 all 目标仍然像这样执行如果是 .PHONY: all

我有闲置的 makefile 代码。

all: test1 test2

test1: test1.o
test1.o: test1.c

test2: test2.o
test2.o: test2.c

clean:
        rm -rf *.o test1 test2

【问题讨论】:

标签: makefile gnu-make


【解决方案1】:

您怎么知道all 规则“仍在执行”?该规则没有配方,因此无法“执行”。

如果您的意思是即使 all 文件存在于本地目录中,make 仍在构建目标 test1test2,这就是 make 的工作方式(这没有任何需要处理虚假目标与非虚假目标)。当 make 决定是否首先构建特定目标时,它会尝试构建该目标的所有先决条件,以及 那些 目标的所有先决条件等。只有在完成所有这些之后,make知道是否构建第一个目标(在本例中为all)。

【讨论】:

    【解决方案2】:

    make clean 此处没有任何依赖关系,因此将一个名为 clean 的文件放在那里足以让目标被视为已构建。

    make all 另一方面有依赖关系。即使你把一个名为all 的文件放在那里,Make 也必须检查all 文件是否比test1test2 更新。这个过程会触发test1test2 的构建,它的效果恰好与all 是一个虚假目标的效果相同。


    基础是all: test1 test2 是构建名为all文件 的配方,它依赖于test1test2文件

    如果你运行make all,Make 会做这样的事情:

    1. 分析Makefile
    2. 发现all 依赖于test1test2
    3. 检查all 的时间戳,看看它是否是“最新的”。
      • 如果没有任何依赖项比其自身更新,则它是“最新的”。
        • 换句话说,如果文件比它的所有依赖项都新,Make 可以跳过构建文件。
    4. 构建过时或丢失的文件。

    现在,如果您想阻止 Make 将目标视为文件,您可以将它们指定为 phony targets。这是all 等非文件目标的最佳实践。

    【讨论】:

      【解决方案3】:

      (此答案与现有答案中的任何一个都没有异议,而是提出了另一种思考方式)。

      当你有这样的规则时

      dst: src
          action
      

      你在说两件事(如你所知):

      1. 如果dst 不存在,或者早于src,则执行action;和
      2. action 完成时,文件dst 将存在。

      对于allclean 等目标,第二个陈述当然不正确。 Make 不会让你遵守 (2) 中的承诺,所以当你说 make all 时,它会计算并生成所需的依赖项,而不是抱怨之后没有文件 all。你在撒谎,但它并不介意(这很酷......)。也就是说,这基本上是一个makefile hack

      问题出在哪里,当然,如果由于某种原因恰好有一个名为allclean 的文件。然后Make会在计算依赖关系时考虑文件all的修改日期,可能会得出你没想到的结论。

      所以.PHONY: all 所做的就是使黑客合法化,并告诉 Make '即使文件 all 存在,假装它不存在';你基本上是在取消承诺(2)。

      因此,正如其他答案所述,没有必要提及.PHONY。当意外创建与虚假目标匹配的文件时,它只是防止错误 - 容易制造但容易错过。

      【讨论】:

        猜你喜欢
        • 2021-12-27
        • 2021-07-14
        • 1970-01-01
        • 2015-02-14
        • 1970-01-01
        • 1970-01-01
        • 2021-12-27
        • 2021-05-30
        • 2020-03-05
        相关资源
        最近更新 更多