未保留在多线程生成文件中的"order-only"先决条件的顺序



让我们考虑一下这个makefile:

.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 $@

乍一看,这段代码可能没有意义,但这只是一个简化版本,说明了以下问题:

运行make时,输出与预期一样。首先,执行build规则。它可以重建一些代码,通过文件build_process指示之后将触发flash规则。仅当配置文件已提前闪存(通过tmp_config_file指示(或已提前重建(通过build_process指示(时,代码才会闪存到某些设备。如您所见,只有在flash之前评估build规则时,此生成文件才有效,因为flash取决于build的结果。

到目前为止,一切都很好。现在我运行make-j8,得到了一个make: *** No rule to make target 'build_process', needed by 'flash'. Stop.。显然,仅限订单的先决条件的顺序不再保留,make不会等到build完成。

这是否意味着只有订单的先决条件只能在单线程的makefile中工作?如果是,为什么?是否可以保持顺序,但以多线程方式执行单个规则?

编辑:我知道,你可以通过以下方式强制执行预期行为:

.PHONY: flash_bin
flash_bin: 
$(MAKE) build; 
$(MAKE) flash

但我仍然感兴趣的是,为什么订单不能在多线程makefile 中可靠地使用

当并行运行make时,意味着它可以同时调度多个目标执行。由于目标buildflash之间没有定义依赖关系,因此make假设它们可以同时运行。它碰巧意外地在单线程中工作,因为Makefile创建了一个它没有声明的文件,而flash依赖于这个意外创建的文件。

它甚至不需要多线程来使其失败,只需运行目标flash,而无需事先运行build,例如:

$ make flash
Config flashed
make: *** No rule to make target 'build_process', needed by 'flash'.  Stop.

我认为您应该使flash依赖于build,或者将目标build重命名为build_process