为啥 Makefile 目标依赖于两个目标,但只运行一次?

Posted

技术标签:

【中文标题】为啥 Makefile 目标依赖于两个目标,但只运行一次?【英文标题】:Why the Makefile target is dependent on two targets, but only run once?为什么 Makefile 目标依赖于两个目标,但只运行一次? 【发布时间】:2021-10-09 07:33:45 【问题描述】:
write:
    @echo `date`

file_1: write file_2
    @echo "file_1 begin"
    $(shell sleep 3)
    @echo "file_1 end"

file_3: write file_4
    @echo "file_3 begin"
    $(shell sleep 3)
    @echo "file_3 end"

all: file_1 file_3

.PHONY: write

当我运行 make 时,它​​会输出:

Sat Oct 9 15:22:45 CST 2021
file_1 begin
file_3 begin
file_1 end
file_3 end

target write 只运行一次。

我的最终目标是通过写目标write的开始时间来计算file_1file_3的执行时间。在测试是否会覆盖的过程中,发现了以上问题。如果有更好的计算时间的方法,请告诉我。

【问题讨论】:

它按预期工作。我不认为一个目标可以多次执行。要测量时间,请考虑使用time 命令。 Makefile 目标不类似于函数,表达对目标的依赖也不类似于调用函数。 make 确定需要构建哪些目标,以什么顺序,以便请求的目标目标在其依赖关系方面是最新的。在给定的运行中,没有任何目标被构建超过一次。 另外,依赖任何目标的依赖列表的顺序是不明智的。您发现与此类排序相关的任何行为模式都来自make 实现细节,而不是make 实用程序的规范。 【参考方案1】:

首先,在配方中使用$(shell ...) 函数几乎总是错误的。配方已经在 shell 中运行,因此不需要它,并且它具有意外行为。为什么不在这里直接使用@sleep 3

没有办法在一次 make 调用中多次构建单个目标。那将是非常糟糕的:考虑如果您有多个程序都依赖于一个.o 文件,例如:您想多次重新编译该.o 文件吗?

无论如何,这不会真正做到你想要的:

file_1: write file_2

这并没有测量file_1 的执行时间,因为写入了开始日期,然后构建了file_2,然后构建了file_1。所以你也包括了file_2 的执行时间。

当然,如果您启用了并行构建,那么所有的赌注都没有了。

如果您想测量某些东西,请将启动/停止操作放在配方中,而不是使用先决条件。您可以将其隐藏在变量中以减少输入的繁琐。

【讨论】:

感谢您的回答。关于 $(shell...) 的使用,已更正。因为以前不知道`不能在'中使用。 Put the start/stop operation in the recipe without using prerequisites. 配方中的执行时间是否忽略了先决条件? 我不太明白需要shell 的问题,但无论如何,这并不重要。在完成所有先决条件后,将作为一个单元调用配方。因此,如果您将开始时间作为配方中的第一个命令,它将显示该配方开始的时间,而不包括其任何先决条件。您可以轻松地对此进行试验。

以上是关于为啥 Makefile 目标依赖于两个目标,但只运行一次?的主要内容,如果未能解决你的问题,请参考以下文章

如何在目标依赖于多个 linux 构建的地方布局 Makefile

makefile

初识makefile

从stem中的文件名生成makefile目标依赖项

Makefile:如何写目标依赖

在LINUX中Makefile中的依赖文件放在啥地方? 生成的目标文件在啥地方?makefile 是啥类型的文件?