使用"make -jN"进行cmake和并行构建

Rom*_*nko 15 makefile build cmake parallel-builds

我正在尝试为源代码树设置基于CMake的并行构建,但是当我发布时

$ cmake .
$ make -j2
Run Code Online (Sandbox Code Playgroud)

我明白了:

jobserver unavailable: using -j1.  Add '+' to parent make rule
Run Code Online (Sandbox Code Playgroud)

作为警告.有没有人知道是否有可能以某种方式修复它?

ape*_*arr 23

在生成的Makefile中,当调用子make时,它需要使用$(MAKE)(不仅仅是'make')或者在行前面加上+.也就是说,规则应如下所示:

mysubdir:
    $(MAKE) -C mysubdir
Run Code Online (Sandbox Code Playgroud)

或者像这样:

mysubdir:
    +make -C mysubdir
Run Code Online (Sandbox Code Playgroud)

如果你不这样做,那么make会给你那个警告.

我对cmake一无所知,所以也许它会生成不正确的Makefile.或者你可能在你的方面做错了什么.

  • 即使我使用了`$(MAKE) -C mysubdir`,我也收到了上述错误。这里有什么问题? (2认同)

uli*_*tko 8

在我的情况下(使用CMake 3.5.2),琐碎的cd build && cmake .. && make -j5工作就好了.

但是,当通过习语构建自定义目标(作为其他目标的依赖关系)时,我确实得到了jobserver不可用的错误cmake --build . --target foo.

像这样:

add_custom_target(buildroot
   COMMAND ${CMAKE_COMMAND} --build . --target install
   COMMENT "Populating buildroot..."
)
add_dependencies(deb buildroot)
add_dependencies(rpm buildroot) #... etc
Run Code Online (Sandbox Code Playgroud)

- 这样用户可以make deb和它一起工作.如果需要,CMake将重新生成makefile,运行编译,install完全一样make install,然后运行我的自定义脚本将填充的buildroot打包成我需要的任何形状或形式.

果然,我想make -j15 deb- 但那失败了.


现在,正如CMake开发人员在邮件列表中所解释的那样,根本原因在于GNU Make中令人惊讶(或不是); 有一个解决方法.

根本原因是它make不会将其作业服务器环境传递给它认为不是的子进程make.

为了说明,这是一个进程树(ps -A f)分支: … \_ bash \_ make -j15 deb \_ make -f CMakeFiles/Makefile2 deb \_ make -f CMakeFiles/buildroot.dir/build.make CMakeFiles/buildroot.dir/build \_ /usr/bin/cmake --build . --target install ? \_ /usr/bin/gmake install …

在⦿点,make删除jobserver环境,最终导致单线程编译.


解决方法这对我来说,真是棒极了作为送人的链接的电子邮件,是前缀与所有的自定义命令+env.像这样:

add_custom_target(buildroot
   #-- this ??? here -- https://stackoverflow.com/a/41268443/531179
   COMMAND +env ${CMAKE_COMMAND} --build . --target install
   COMMENT "Populating buildroot..."
)
add_dependencies(deb buildroot)
add_dependencies(rpm buildroot) #... etc
Run Code Online (Sandbox Code Playgroud)

最后,这出现在buildroot相应makefile 中的规则中(CMake生成一堆它们),并使GNU Make正常运行并尊重-j.

希望这可以帮助.

  • 需要的是在生成的 Makefile 规则前面添加“+”。在 Windows 上,使用的生成器不是 Makefile 生成器,因此 + 不会出现在 Makefile 中,而是按照我们想要的方式进行解释。此外,在某些情况下,cmake 通常不会将 COMMAND 后面的字符串作为规则放入 Makefile 中,而是执行例如: `cdworking/directory && +env ...` ,这显然也会失败。真正需要的是一种方法来告诉 cmake 在 makefile 规则的*开头*添加这个“+”,前提是生成器是具有作业服务器支持的 Makefiles 生成器。 (2认同)