我无法理解官方 gmake 文档的第 3 章(从第 3.5 节开始)
https://www.gnu.org/software/make/manual/make.html#Remaking-Makefiles
文档说: ...读入所有 makefile 后,make 会将每个 makefile 视为目标并尝试更新它。如果 makefile 有一条规则说明如何更新它....,它将在必要时进行更新。检查完所有 makefile 后,如果确实有任何更改,make 将从头开始并重新读取所有 makefile。 (它还会尝试再次更新它们中的每一个,但通常这不会再次更改它们,因为它们已经是最新的。)每次重新启动都会导致特殊变量 MAKE_RESTARTS 被更新。
所以我尝试使用这个 mkfile(G.M. 建议的 -include 的存在不会改变任何内容):
all:
echo all $(MAKE_RESTARTS) aaa
#-include: mkfile
mkfile:
echo touch
touch mkfile
我希望 mkfile 第一次运行后 mkfile 修改时间发生变化,并且 make 必须一次又一次地运行它。 但什么也没发生:
$ make -f mkfile
echo all aaa
all aaa
$
此外,目标“mkfile”未按照文档中的预期进行调用:读入所有 makefile 后,make 会将每个文件视为目标并尝试更新它。
我有什么误解吗?您能否举例说明文档中“重新制作”makefile 的含义?
UPD:我尝试过 Andreas 的建议,但再次得到了奇怪的结果:
- 原始 mkfile 但使用 --always-make 运行
$ make --always-make -f mkfile
echo touch
touch
touch mkfile
echo all 1 aaa
all 1 aaa
此处目标“mkfile”运行一次,目标“all”也运行一次。结果运行的结果是可重复的。
- 如果我更改目标“mkfile”以强制运行,结果会很奇怪,并且调用之间会有所不同: MK文件:
all:
echo all $(MAKE_RESTARTS) aaa
mkfile: force
echo touch
touch mkfile
force: ;
结果:
$ make -f mkfile
echo touch
touch
touch mkfile
echo touch
touch
touch mkfile
echo touch
touch
touch mkfile
................
touch mkfile
echo touch
touch
touch mkfile
echo all 16 aaa
all 16 aaa
$ make -f mkfile
echo touch
touch
touch mkfile
echo touch
touch
touch mkfile
echo touch
touch
touch mkfile
echo all 2 aaa
all 2 aaa
$ make -f mkfile
echo touch
touch
touch mkfile
...............
touch mkfile
echo all 13 aaa
all 13 aaa
$
UPD2 - 关于 MAKE_RESTARTS
--always-make
仅当 makefile 的目标没有先决条件时才遵循 MAKE_RESTARTS。
mk文件:
all:
echo all $(MAKE_RESTARTS) aaa
mkfile:
echo touch $(MAKE_RESTARTS)
sleep 0.5
touch mkfile
结果:
$ make --always-make -f mkfile
echo touch
touch
sleep 0.5
touch mkfile
echo all 1 aaa
all 1 aaa
$
如果makefile的目标有强制先决条件,则循环是无限的(我什至尝试强制将MAKE_RESTARTS设置为大于0的值)
mk文件:
MAKE_RESTARTS := 1
all:
echo all $(MAKE_RESTARTS) aaa
mkfile: force
echo touch $(MAKE_RESTARTS)
sleep 0.5
touch mkfile
force: ;
结果:
$ make --always-make -f mkfile
echo touch 1
touch 1
sleep 0.5
touch mkfile
echo touch 1
touch 1
sleep 0.5
touch mkfile
echo touch 1
touch 1
sleep 0.5
touch mkfile
^C
最佳答案
为此:
all:
echo all $(MAKE_RESTARTS) aaa
mkfile:
echo touch
touch mkfile
当make -f mkfile
运行时,它会尝试构建mkfile
。 make 手册说,如果一个目标没有先决条件,那么如果它存在,它就被认为是最新的(当它不依赖任何东西时,它怎么会过时呢?) > 文件存在(显然),这条规则实际上是一个空操作。如果您想查看重建 makefile 的行为,那么 makefile 必须有一些先决条件,表明它已过时。
如果您使用 --always-make
运行它,您将遇到 this statement在 GNU make 手册中:
GNU
make
proceeds to consider targets and their prerequisites using the normal algorithms; however, all targets so considered are always remade regardless of the status of their prerequisites. To avoid infinite recursion, ifMAKE_RESTARTS
is set to a number greater than 0 this option is disabled when considering whether to remake makefiles.
(强调已添加)。
如果您使用 force
目标运行,那么它将如您所见进行更新。对于某些操作系统,这将永远运行。然而,对于其他人来说,在某些时候,touch
命令的运行速度足够快,以至于它实际上不会更改 mkfile
文件的修改时间;它会非常快,以至于命令运行之前和之后的修改时间将相同。当配方运行但不更改该目标的修改时间时,则该目标不会被视为已修改,并且依赖于它的任何规则都不会因为该目标而被视为过时。
当发生这种情况时,make
认为目标没有更改,并且不再重新执行自身。
关于makefile - Makefiles是如何重新制作的——看不懂官方文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65058553/