这是我的 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
Run Code Online (Sandbox Code Playgroud)
sub 是包含另一个Makefile(子make)的子目录。
当我运行test1规则时:
$ make -j8 test1
make -C sub
make[1]: warning: jobserver unavailable: using -j1. Add '+' to parent make rule.
Run Code Online (Sandbox Code Playgroud)
我收到警告说 jobserver 不可用并且sub/Makefile确实在单线程中运行(就像-j1)。
他们说我应该添加+,所以我运行了一个test2包含+beforemake命令的目标。现在我没有看到警告并且sub/Makefile实际上是并行运行的。但是根据this answer,该+标志不是用于并行运行,而是用于强制运行命令,即使make使用-n, -t,-q标志运行。但是为什么+启用 jobserver 呢?
当我运行test3不使用+但$(MAKE)用于运行的目标时sub/Makefile,它也不会发出作业服务器警告(并行执行有效)。那么make和之间有什么区别$(MAKE)?我认为这仅仅是允许替代默认的化妆与用户定义的补充。当我不覆盖MAKE变量时,我看到的make命令与我在test1目标中看到的命令相同。但是为什么$(MAKE)启用 jobserver 而make没有呢?
运行test4目标也不会发出作业服务器警告(并行工作)。
osh*_*das 16
GNU make 手册对这个错误有很好的解释。关键是:'make' 不会将有关 jobserver 的信息传递给被调用的进程,除非确定被调用的进程也是 'make'。
'警告:作业服务器不可用:使用 -j1。将“+”添加到父生成规则。
为了使进程进行通信,父进程将信息传递给子进程。因为如果子进程实际上不是一个 make,这可能会导致问题,所以父进程只有在它认为子进程是一个 make 时才会这样做。父级使用普通算法来确定这一点(请参阅MAKE 变量的工作原理)。如果 makefile 的构造使得父进程不知道子进程是一个 make 进程,那么子进程将只收到部分必要的信息。在这种情况下,子进程将生成此警告消息并按顺序进行构建。
错误描述中引用的 MAKE 变量如何工作部分指定了两种告诉 'make' 调用的进程是 'make' 的另一个实例的方法:使用$(MAKE)或+。它指出:
$(MAKE)在配方中调用“make”时应该使用变量。
递归 make 命令应始终使用变量 MAKE,而不是显式命令名称“make”,如下所示:
Run Code Online (Sandbox Code Playgroud)subsystem: cd subdir && $(MAKE)
$(MAKE)和放置 a+具有相同的效果。
使用 MAKE 变量与在配方行的开头使用“+”字符具有相同的效果。
MAKE配方时,魔法才会发生。如果不是这种情况,请使用+.
仅当 MAKE 变量直接出现在配方中时才启用此特殊功能:如果 MAKE 变量是通过扩展另一个变量引用的,则它不适用。在后一种情况下,您必须使用“+”标记来获得这些特殊效果。