“的顺序”;“仅限订购”;未保存在多线程makefile中的先决条件 让我们考虑一下这个代码> MaFixFix< /C>:< /P> .PHONY: flash_bin flash_bin: | build flash CODE_CHANGED=0 .PHONY: build build: @echo "Run Build Process" @if [ ! -f build_process ] || [ $(CODE_CHANGED) -eq 1 ]; then \ touch build_process; \ fi; flash: tmp_config_file build_process @echo "Flash to ESP" @touch flash tmp_config_file: @echo "Config flashed" @touch $@
乍一看,这段代码可能没有意义,但这只是一个简化版本,说明了以下问题: 运行“的顺序”;“仅限订购”;未保存在多线程makefile中的先决条件 让我们考虑一下这个代码> MaFixFix< /C>:< /P> .PHONY: flash_bin flash_bin: | build flash CODE_CHANGED=0 .PHONY: build build: @echo "Run Build Process" @if [ ! -f build_process ] || [ $(CODE_CHANGED) -eq 1 ]; then \ touch build_process; \ fi; flash: tmp_config_file build_process @echo "Flash to ESP" @touch flash tmp_config_file: @echo "Config flashed" @touch $@,makefile,gnu-make,Makefile,Gnu Make,乍一看,这段代码可能没有意义,但这只是一个简化版本,说明了以下问题: 运行make时,输出与预期一致。首先,执行build规则。它可能会重新生成一些代码,如文件build\u过程所示之后,将触发闪烁规则。只有在配置文件已提前刷新(通过tmp\u config\u file指示)或已提前重建(通过build\u process指示)的情况下,才会将代码闪存到某些设备。如您所见,此生成文件仅在build规则在flash之前进行评估时有效,因为flash取决于build的结果 到目前为止,一切顺利。现
make
时,输出与预期一致。首先,执行build
规则。它可能会重新生成一些代码,如文件build\u过程所示之后,将触发闪烁
规则。只有在配置文件已提前刷新(通过tmp\u config\u file
指示)或已提前重建(通过build\u process
指示)的情况下,才会将代码闪存到某些设备。如您所见,此生成文件仅在build
规则在flash
之前进行评估时有效,因为flash
取决于build
的结果
到目前为止,一切顺利。现在我运行了make-j8,得到了一个make:**“flash”所需的目标“构建过程”没有规则。停止。
显然,仅订单先决条件的顺序不再保留,make不会等到构建
完成
这是否意味着只有订单的先决条件只能在单线程的makefile中工作?若然,原因为何?是否可以保持顺序,但以多线程方式执行单个规则
编辑:我知道,您可以通过以下方式强制执行预期行为:
.PHONY: flash_bin
flash_bin:
$(MAKE) build; \
$(MAKE) flash
但我仍然感兴趣的是,为什么order only不能在多线程makefile中可靠地使用当您并行运行make
时,这意味着它可以同时调度多个目标的执行。由于目标build
和flash
之间没有定义依赖关系,make
假设它们可以同时运行。它碰巧在单线程中意外工作,因为Makefile
创建了一个它没有声明的文件,flash
依赖于这个意外创建的文件
它甚至不需要多线程来使其失败,只需运行targetflash
,而无需事先运行build
,例如:
$ make flash
Config flashed
make: *** No rule to make target 'build_process', needed by 'flash'. Stop.
我认为你应该让flash
依赖于build
,或者将targetbuild
重命名为build\u-process
我认为真正的问题是你的flash
目标确实应该依赖于build
配方的副作用……或者,将build
目标重命名为build\u process
(因为它实际生成的是),并删除.PHONY
指令。这会稍微改变行为。必须始终执行build
的配方,以确定代码是否已重建。如果我将build
目标重命名为build\u进程
,则只会执行一次。您指出build
和flash
应在flash\u bin
之前生成。你从来没有告诉make在flash之前也应该编译build
。而且您没有告诉make是build
生成build\u过程的flash
的先决条件。试着尽可能地消除所有这些非文件目标,并专注于真正的文件。提示:即使是非常大的生成文件集也可以用作先决条件,并且可以使用$(shell find…
或$(通配符…
创建文件列表。如果您在order only dependency(| build flash
->| flash build
)中更改生成和闪存的顺序,对于单线程make,您将获得相同的行为。