我正在为一个中等大小的C ++项目编写一个makefile,并使用特殊的.DEFAULT
目标来允许在系统特定的子makefile中存储特定于系统的路径和设置。由于我不明白的原因,依赖关系似乎与.DEFAULT
一样,与其他目标一样。例如,考虑makefile:
.DEFAULT: zed
@echo $@
bar: zed
@echo bar
zed:
@echo zed
如果我致电make bar
,我会看到
zed
bar
但如果我输入make foo
,我只会看到
foo
为什么.DEFAULT
表现不同?如何实现未命名目标的依赖关系?
答案 0 :(得分:1)
因为.DEFAULT
不像常规目标。它具有非常特殊的行为。
.DEFAULT
为.DEFAULT指定的配方用于未找到规则的任何目标(显式规则或隐式规则)。查看Last Resort。如果指定了.DEFAULT配方,则作为先决条件提及但不作为规则中的目标的每个文件都将代表其执行该配方。请参阅隐式规则搜索算法。
因此文档相当清楚地表明我现在认为我误读了上面的文档并且不清楚什么是先决条件.DEFAULT
目标的先决条件不像正常的先决条件那样运行。.DEFAULT
规则执行/如何处理。所以我查看了源代码以找出答案。
而且,在一些消息来源之后,事实证明在GNU make中.DEFAULT
的实现有点有趣。
如果查看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;
}
这里的第一位与我们无关,但我把它留在了显示此时正在执行的操作类型。
第二位是重要的一点。如果当前文件没有命令且不是目标,并且存在默认文件条目且该条目具有命令,则将默认文件的命令复制为当前文件的命令。
源中有一些其他对default_file
的引用,但它们都与当前主题无关。
注意我们还没有看到什么?对.DEFAULT
的任何特殊处理,因为它实际上是从makefile中读取的。第一次预创建只是对内部缓存进行种子处理,并允许make轻松地通过变量引用default_file
条目。它不会填写命令或先决条件或任何内容。
当make在实际操作期间实际从文件中读取.DEFAULT
规则时,它将找到预先创建的文件条目并将其填入详细信息中。但这意味着什么(以及快速测试证实了这一点)是.DEFAULT
规则的读取和处理方式与其他规则一样。
所以,这是我们故事的结束,你实际上可以运行make .DEFAULT
并且它将起作用(并运行列出的先决条件),因为.DEFAULT
的特殊情况处理仅限于填充任何非目标目标的命令,没有别的(显然)。
哦,虽然我在示例中使用了make 4.1源代码,但代码至少没有改变,因为至少3.81并且我没有检查,我认为它也没有在4.1之后改变。