“仅限订单”先决条件的顺序未保留在多线程 makefile 中

问题描述 投票:0回答:1

让我们考虑一下这个

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
指示)时,代码才会刷新到某些设备。正如您所看到的,只有在
build
规则在之前
flash
求值时,此makefile才有效,因为
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

但我仍然感兴趣为什么 order-only 不能在多线程 makefile 中可靠地使用

makefile gnu-make
1个回答
1
投票

当你并行运行

make
时,这意味着它可以安排多个目标同时执行。由于目标
build
flash
之间没有定义依赖关系,因此
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

© www.soinside.com 2019 - 2024. All rights reserved.