Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

warning: jobserver unavailable: using -j1. Add '+' to parent make rule

Tags:

makefile

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.

like image 628
anton_rh Avatar asked Mar 16 '20 08:03

anton_rh


1 Answers

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:

  1. One should use $(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)
    
  2. Using $(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.

  3. Magic happens only if you explicitly type 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.

like image 101
oshverdas Avatar answered Nov 16 '22 03:11

oshverdas