【问题标题】:Dependencies for special make target .DEFAULT not firing特殊制作目标的依赖项.DEFAULT未触发
【发布时间】:2014-11-11 21:38:50
【问题描述】:

我正在为一个中型 C++ 项目编写一个 makefile,并使用特殊的 .DEFAULT 目标来允许在系统特定的子 makefile 中存储系统特定的路径和设置。由于我不明白的原因,依赖项似乎不适用于.DEFAULT,就像它们与其他目标一样。例如,考虑 makefile:

.DEFAULT: zed
    @echo $@
bar: zed
    @echo bar
zed:
    @echo zed

如果我打电话给make bar,我明白了

zed
bar

但如果我输入make foo,我只会看到

foo

为什么.DEFAULT 的行为不同?如何实现未命名目标的依赖关系?

【问题讨论】:

    标签: unix makefile gnu-make


    【解决方案1】:

    因为.DEFAULT 不像常规目标。它有非常具体的行为。

    来自GNU Make Manual

    .默认

    为 .DEFAULT 指定的配方用于未找到任何规则(显式规则或隐式规则)的任何目标。见最后的手段。如果指定了 .DEFAULT 配方,则作为先决条件提到的每个文件,但不是作为规则中的目标,将代表它执行该配方。请参阅隐式规则搜索算法。

    所以文档相当清楚地表明.DEFAULT 目标的先决条件不像正常的先决条件那样运行。我现在认为我误读了上面的文档并且不清楚@ 的先决条件是什么987654328@ 规则做/如何处理。于是我就去查了源码。

    而且,经过一些源代码挖掘后,事实证明.DEFAULT 在 GNU make 中的实现有点有趣。

    如果您查看 main.c 的 line 1859,您可以看到 make 在哪里手动为 .DEFAULT 规则创建(内部)文件条目。

    default_file = enter_file (strcache_add (".DEFAULT"));
    

    这是任何makefile被读取/等之前。 (发生在line 1895)。

    如果您从 remake.c 的 Line 502 开始查看,您会看到 make 试图为它还没有任何文件的文件提出规则。

    /* If file was specified as a target with no commands,
       come up with some default commands.  */
    
    if (!file->phony && file->cmds == 0 && !file->tried_implicit)
      {
        if (try_implicit_rule (file, depth))
          DBF (DB_IMPLICIT, _("Found an implicit rule for '%s'.\n"));
        else
          DBF (DB_IMPLICIT, _("No implicit rule found for '%s'.\n"));
        file->tried_implicit = 1;
      }
    if (file->cmds == 0 && !file->is_target
        && default_file != 0 && default_file->cmds != 0)
      {
        DBF (DB_IMPLICIT, _("Using default recipe for '%s'.\n"));
        file->cmds = default_file->cmds;
      }
    

    这里的第一位与我们无关,但我将其保留以显示此时 make 正在执行的操作类型。

    第二点很重要。如果当前文件没有命令并且不是目标,并且有一个默认文件条目并且该条目有命令,则将默认文件的命令复制为当前文件的命令。

    源中还有几个对default_file 的其他引用,但它们都与当前主题无关。

    注意我们还没有看到什么?对.DEFAULT 的任何特殊处理,因为它实际上是从生成文件中读取的。第一个预创建只是为内部缓存提供种子,并允许 make 轻松地通过变量引用 default_file 条目。它不填写命令或先决条件或任何内容。

    当 make 在正常操作期间实际从文件中读取 .DEFAULT 规则时,它会找到预先创建的文件条目并填写详细信息。但这意味着(快速测试证实了这一点).DEFAULT 规则的读取和处理方式与其他规则一样。

    所以,我们的故事到此结束,您实际上可以运行make .DEFAULT,它会工作(并运行列出的先决条件),因为.DEFAULT 的特殊情况处理仅限于填充任何非-target 目标,仅此而已(显然)。

    哦,虽然我在示例中使用了 make 4.1 源代码,但至少自 3.81 以来代码没有改变,虽然我没有检查,但我认为它在 4.1 之后也没有改变。

    【讨论】:

    • 谢谢!我仍然不确定我是否理解这如何描述处理.DEFAULT 的先决条件。在我阅读时,文档状态 .DEFAULT 将匹配不存在规则的其他规则的先决条件,但没有讨论 .DEFAULT 本身的先决条件。
    • @user1590768 我要说“如果 .DEFAULT 配方”这句话是在谈论 .DEFUALT. 目标本身的先决条件,但我不确定这是否属实。所以你是对的,它没有清楚地表明这些是如何工作的。这意味着我关于明确的评论是不正确的。我们可能需要等待并希望@MadScientist 能在此处发出提示(或者让我去源头潜水)。
    • 这种行为看起来肯定会忽略任何明确的目标,而是按照文档中的说明进行操作。
    • @tripleee 它显然似乎忽略了明确的先决条件,但我实际上看不到讨论该行为的文档(至少在我摘录的部分中没有)。可能有另一个部分讨论这个问题,或者它可能没有记录。稍后我可能会去寻找源代码,看看是否能找到任何东西。
    • 感谢您非常完整的回答!我发现没有从.DEFAULT 复制先决条件有点令人惊讶,但是您已经非常清楚这是预期的行为。我一定会在获得 15 声望后投票。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-30
    • 1970-01-01
    • 2013-10-14
    • 2016-05-28
    • 2019-01-27
    • 2018-11-02
    • 1970-01-01
    相关资源
    最近更新 更多