警告:作业服务器不可用:使用-j1。在父级make规则中添加“+”。

19

这是我的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 是包含另一个 Makefile(子 make)的子目录。

当我运行 test1 规则时:

$ make -j8 test1
make -C sub
make[1]: warning: jobserver unavailable: using -j1.  Add '+' to parent make rule.

我收到了“jobserv不可用”的警告,sub/Makefile只使用单线程运行(就像使用-j1一样)。
他们说我应该添加+,然后在make命令之前运行一个包含+test2目标。现在我没有看到警告,并且sub/Makefile真正地并行运行。但是根据这个答案+符号不是用于并行运行,而是用于强制运行命令,即使使用-n-t-q标志运行make。但为什么+会启用jobserv呢?
当我运行不使用+但使用$(MAKE)来运行sub/Makefiletest3目标时,它也不会给出jobserv警告(并行执行有效)。那么make$(MAKE)之间有什么区别呢?我认为这只是允许将默认的make替换为用户定义的make。当我不覆盖MAKE变量时,我看到的make命令与我在test1目标中看到的相同。但是为什么$(MAKE)会启用jobserv而make不会呢?
运行test4目标也不会给出jobserv警告(并行工作)。
请注意,我的问题不同于这个问题。它涉及到cmake,而我的问题涉及到make。还有一个相关问题,但它没有回答我的问题。
1个回答

27

GNU make手册对这个错误有很好的解释。关键是:除非确定被调用的进程也是'make',否则'make'不会向该进程传递关于jobserver的信息。

“警告:jobserver不可用:使用-j1。在父make规则中添加“+”。”

为了让make进程进行通信,父进程将向子进程传递信息。由于如果子进程实际上不是make,则可能导致问题,因此只有在父进程认为子进程是make时,父进程才会这样做。父进程使用正常的算法来确定这一点(请参见MAKE变量的工作方式)。如果makefile构造使得父进程不知道子进程是make进程,则子进程将仅接收到部分必要的信息。在这种情况下,子进程将生成此警告消息,并以顺序方式进行构建。

在错误描述中引用的MAKE变量的工作方式一节指定了两种告诉'make'调用进程是另一个'make'实例的方法:使用$(MAKE)+。它指出:

  1. 在配方中调用'make'时应使用$(MAKE)变量。

    递归make命令应始终使用变量MAKE,而不是显式命令名称“make”,如下所示:

    subsystem:
            cd subdir && $(MAKE)
    
  2. 使用$(MAKE)和在配方中调用“make”行之前放置+符号具有相同的效果。

    使用MAKE变量与在配方行开头使用“+”字符有相同的效果。

  3. 只有在配方中显式键入MAKE时才会发生特殊情况。如果不是这种情况,请使用+

    只有在配方中直接出现MAKE变量时才启用此特殊功能:如果通过扩展另一个变量来引用MAKE变量,则不适用。在后一种情况下,您必须使用“+”标记才能获得这些特殊效果。


谢谢。在我的情况下,这很有帮助,因为我正在将一个Makefile包装在一个cmake目标中,该项目旨在使用Ninja作为make后端。 - Patrizio Bertoni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接