如何在 CMake 中配置可移植的并行构建?

不管使用哪种构建工具,都可以进行并行构建吗?

在 Unix 下,我们可以添加 make -jN,其中 N 是线程数,在 Windows 下,我添加到 CXX_FLAG "/MP",然后在 Visual Studio 中使用它来并行构建... (?)我如何使我的版本,使 CMAKE_MAKE_PROGRAM不总是扩展当我运行 CMake?

What is a general solution?

我想到了这个:

# Add some multithreaded build support
MARK_AS_ADVANCED(MULTITHREADED_BUILD)
set(MULTITHREADED_BUILD 12 CACHE STRING "How many threads are used to build the project")
if(MULTITHREADED_BUILD)
if(${CMAKE_GENERATOR} MATCHES "Unix Makefiles")
message(STATUS ${CMAKE_BUILD_TOOL})
set(CMAKE_MAKE_PROGRAM "${CMAKE_MAKE_PROGRAM} -j${MULTITHREADED_BUILD}")
message(STATUS "Added arguments to CMAKE_BUILD_TOOL: ${CMAKE_MAKE_PROGRAM}")
elseif(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
message(STATUS "Added parallel build arguments to CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
endif()
endif()
83892 次浏览

你不能跨站台。JN 选项是要创建的参数,而不是生成的 Makefile 的一部分。但是,您可以让 CMake 生成一个 Bash 脚本,该脚本使用-jN 运行您的项目 make (该脚本查找您拥有的核心数量)。

如果您使用的是 CMake v2.8.8或更高版本,则可以使用 Ninja作为 GNU < strong > make 的替代品:

mkdir build
cd    build
cmake -G Ninja ..
ninja              # Parallel build (no need -j12)

or

mkdir build
cd    build
cmake -G Ninja ..
cmake --build .    # Parallel build using Ninja

如您所见,不需要使用 CMAKE_MAKE_PROGRAM,默认情况下构建是并行运行的,根据可用的 CPU 内核优化作业的数量。

Ninja 基于一个低级别的 JSON 配置来加速启动阶段。因此,它的 JSON 配置并不容易手工编写,我总是使用高级工具/IDE 生成它:

由于 C + + 构建通常需要大量内存,因此计算机必须提供与 CPU 内核数量同样多的内存。

正如 鲁斯兰所指出的,CMake 3.12(2018)有一个 新选择 cmake --build -j <N>来限制构建到 <N>核心(作业) ,从而限制内存消耗(另见 文件)。如果使用较旧的 CMake 版本,仍然可以使用 cmake --build -- -j <N>。选项 --告诉 CMake 将其余部分直接传递给底层构建工具,这里是 Ninja。

I have settled down to writing a parallelmake.sh script for Unix Makefiles-based generators. This is done here: https://github.com/gabyx/ApproxMVBB

以及 CMake 文件中的相关部分:

https://github.com/gabyx/ApproxMVBB/blob/master/CMakeLists.txt#L89

# Add some multithreaded build support =====================================================================================================
MARK_AS_ADVANCED(MULTITHREADED_BUILD)
SET(MULTITHREADED_BUILD ON CACHE BOOL "Parallel build with as many threads as possible!")
if(MULTITHREADED_BUILD)
if(${CMAKE_GENERATOR} MATCHES "Unix Makefiles")
file(COPY ${ApproxMVBB_ROOT_DIR}/cmake/parallelmake.sh DESTINATION ${PROJECT_BINARY_DIR}
FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
NO_SOURCE_PERMISSIONS
)
SET(CMAKE_MAKE_PROGRAM "${PROJECT_BINARY_DIR}/parallelmake.sh")
MESSAGE(STATUS "Set make program to ${PROJECT_BINARY_DIR}/parallelmake.sh")
elseif(MSVC)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" "/MP")
MESSAGE(STATUS "Added parallel build arguments to CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
endif()
endif()
# ========================================================================================================================================

使用 CMake 3.12,这是可能的:

cmake(1)构建项目(cmake --build)获得了指定并行构建级别的 --parallel [<jobs>]-j [<jobs>]选项。它们映射到本机生成工具的相应选项。

正如 dkg 所提到的,你也可以设置环境变量 CMAKE_BUILD_PARALLEL_LEVEL

Links to CMake's documentation:

Now it is very simple to parallel build with cmake. You can add "-j jobs_number" when using "cmake --build". For example:

cmake --build . -j 24

更多细节可以在 CMAKE 手册中找到: https://cmake.org/cmake/help/latest/manual/cmake.1.html#build-tool-mode

在构建时要使用的最大并发进程数。如果省略了本机构建 tool’s default number is used.

如果设置了 CMAKE _ BUILD _ PARALLEL _ LEVEL 环境变量,则指定 当没有给出此选项时,默认的并行级别。

一些本地构建工具总是并行构建 值1可用于限制为单个作业。

如上所述,可以使用 CMake 的 --parallel [<jobs>](或 -j [<jobs>])选项并行构建解决方案。

但是我想指出的是,在 Windows 中有一个命令

cmake.exe --build --parallel <jobs>

使用以下参数启动根 MSBuild 进程:

msbuild.exe /m:<jobs> /p:CL_MPCount=1 <another-useful-arguments...>

这意味着由于 /m:<jobs>(或 /maxcpucount:<jobs>) ,根 MSBuild 进程将启动多个子 MSBuild 进程。但是由于 /p:CL_MPCount=1参数的原因,每个子 MSBuild 最多运行一个编译器进程(有关更多详细信息,请参阅 这个链接)。换句话说,每个 MSBuild 最多只能同时编译一个源文件。

为了克服这个限制,可以用以下方式调用 CMake:

cmake.exe --build --parallel <n_msbuild> -- /p:CL_MPcount=<n_cl>

这种方法设置 /MP选项,从而允许在每个 MSBuild 实例下有多个编译器进程。


要在 Visual Studio GUI 上配置构建,需要转到 设定:

  • 选项 “项目和解决方案→建立和运行→最大数量的并行项目建立”maxcpucount的影响。
  • 选项 “项目和解决方案→ VC + + 项目设置→构建→最大并发 C + + 编译”表示到 /MP的默认边界。