Reputation: 1433
Let's consider this 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 $@
At first glance, this piece of code may not make sense, but this is only a simplified version, which illustrates the following problem:
When runing make
, the output is as expected. At first, the build
rule is executed. It may rebuild some code, indicated through the file build_process
. After that, the flash
rule is triggered. The code is only flashed to some devices if a configuration file has been flashed earlier (indicated through tmp_config_file
) or if it has been rebuilt earlier (indicated through build_process
). As you can see, this makefile only works if the build
rule is evaluated before flash
, because flash
depends on the result of build
.
So far, so good. Now I run make -j8 and I get a make: *** No rule to make target 'build_process', needed by 'flash'. Stop.
Apparently, the order of the order-only prerequisites is not kept anymore and make does not wait until build
has finished.
Does this mean that order-only prerequisites only work in a single threaded makefile? If so, why? Is it possible to keep the order, but to execute the individual rules in a multithreaded fashion?
EDIT: I know, you can force the expected behavior this way:
.PHONY: flash_bin
flash_bin:
$(MAKE) build; \
$(MAKE) flash
But still I am interested why order-only cannot be used reliably in a multithreaded makefile
Upvotes: 0
Views: 665
Reputation: 4261
When you run make
in parallel, it means that it can schedule many targets for execution at the same time. Since there is no dependency defined between targets build
and flash
, make
assumes that they can both be run at the same time. It happens to work in single thread accidentally, since the Makefile
creates a file which it does not declare, and flash
depends on this accidentally created file.
It does not even require multithreading to make it fail, just run target flash
without prior running build
, e.g.:
$ make flash
Config flashed
make: *** No rule to make target 'build_process', needed by 'flash'. Stop.
I believe you should either make flash
depend on build
, or rename target build
to build_process
.
Upvotes: 1