Here is my Makefile:
.PHONY: test%
test1:
# jobserver is UNavailable
make -C sub
test2:
# jobserver is available, ok
+make -C sub
test3:
# jobserver is available, ok
$(MAKE) -C sub
test4:
# jobserver is available, ok
+$(MAKE) -C sub
sub
is sub-directory that contains another Makefile (sub-make).
When I run test1
rule:
$ make -j8 test1
make -C sub
make[1]: warning: jobserver unavailable: using -j1. Add '+' to parent make rule.
I get warning that jobserver is unavailable and sub/Makefile
is really run in single thread (as if -j1
).
They say I should add +
and so I run a test2
target which contains +
before make
command. And now I don't see the warning and sub/Makefile
is really run in parallel. But according to this answer, the +
sign is not for running in parallel but for forcing running commands even if make
is run with -n
, -t
, -q
flags. But why does +
enables jobserver?
When I run test3
target that doesn't use +
but uses $(MAKE)
for running sub/Makefile
, it doesn't give jobserver warning as well (parallel execution works). So what is difference between make
and $(MAKE)
? I thought it is just for allowing to substitute default make with user-defined make. When I don't override MAKE
variable, I see the same make
command as I see in the test1
target. But why does the $(MAKE)
enables jobserver and make
does not?
Running test4
target does not give jobserver warning also (works in parallel).
Please note my question is different from this one. It is about cmake, my question is about make. There is also related question, but it doesn't answer my questions.
The GNU make manual have decent explanation for this error. The point is: 'make' won't pass information about jobserver to the called process unless it is sure that called process is 'make' too.
‘warning: jobserver unavailable: using -j1. Add `+' to parent make rule.’
In order for make processes to communicate, the parent will pass information to the child. Since this could result in problems if the child process isn’t actually a make, the parent will only do this if it thinks the child is a make. The parent uses the normal algorithms to determine this (see How the MAKE Variable Works). If the makefile is constructed such that the parent doesn’t know the child is a make process, then the child will receive only part of the information necessary. In this case, the child will generate this warning message and proceed with its build in a sequential manner.
Section How the MAKE Variable Works referenced in error description specifies two ways of telling 'make' that the invoked process is another instance of 'make': using $(MAKE)
or +
.
It states that:
$(MAKE)
variable when calling 'make' in the recipe.
Recursive make commands should always use the variable MAKE, not the explicit command name ‘make’, as shown here:
subsystem: cd subdir && $(MAKE)
$(MAKE)
and placing a +
before the line that invokes 'make' in the recipe have same effect.
Using the MAKE variable has the same effect as using a ‘+’ character at the beginning of the recipe line.
MAKE
in the recipe. If this is not the case, use +
.
This special feature is only enabled if the MAKE variable appears directly in the recipe: it does not apply if the MAKE variable is referenced through expansion of another variable. In the latter case you must use the ‘+’ token to get these special effects.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With