从 CMake 设置 'make' 默认使用 '-j' 选项

From CMake setup 'make' to use '-j' option by default

我希望我的 CMake 项目在我从终端调用 make 时由 make -j N 构建。我不想每次都手动设置 -j 选项。

为此,我将 CMAKE_MAKE_PROGRAM 变量设置为特定的命令行。我使用 ProcessorCount() 函数,它给出并行执行构建的处理器数量。

当我执行 make 时,我没有看到任何加速。但是,如果我这样做 make -j N,那么它的构建速度肯定会更快。

你能帮我解决这个问题吗? (我正在 Linux 上开发这个。)

这是我在 CMakeList.txt 中使用的代码片段:

include(ProcessorCount)
ProcessorCount(N)
message("number of processors: "  ${N})
if(NOT N EQUAL 0)
  set(CTEST_BUILD_FLAGS -j${N})
  set(ctest_test_args ${ctest_test_args} PARALLEL_LEVEL ${N})
  set(CMAKE_MAKE_PROGRAM "${CMAKE_MAKE_PROGRAM} -j ${N}")      
endif()
message("cmake make program" ${CMAKE_MAKE_PROGRAM})

非常感谢。

如果您想加快构建速度,您可以 运行 并行执行多个 make 进程,但不能使用 cmake。 要使用预定义数量的并行进程执行每个构建,您可以在 MAKEFLAGS.

中定义它

在您的环境脚本中设置 MAKEFLAGS,例如~/.bashrc 随心所欲:

export MAKEFLAGS=-j8

在 Linux 上,以下将 MAKEFLAGS 设置为 CPU - 1 的数量:(在构建时保留一个 CPU 用于其他任务)并且在具有动态资源的环境中很有用,例如VMware:

export MAKEFLAGS=-j$(($(grep -c "^processor" /proc/cpuinfo) - 1))

通过设置您想要影响构建过程的 CMAKE_MAKE_PROGRAM 变量。但是:

  1. 此变量仅影响通过 cmake --build 构建,而不影响 原生工具 (make) 调用:

    The CMAKE_MAKE_PROGRAM variable is set for use by project code. The value is also used by the cmake(1) --build and ctest(1) --build-and-test tools to launch the native build process.

  2. 这个变量应该是一个CACHEd。 make-like 生成器以这种方式使用它:

    These generators store CMAKE_MAKE_PROGRAM in the CMake cache so that it may be edited by the user.

    也就是说,你需要设置这个变量为

    set(CMAKE_MAKE_PROGRAM <program> CACHE PATH "Path to build tool" FORCE)
    
  3. 这个变量应该引用 可执行文件 本身,而不是带有参数的程序:

    The value may be the full path to an executable or just the tool name if it is expected to be in the PATH.

    也就是说,值 "make -j 2" 不能用于该变量(将参数拆分为列表

    set(CMAKE_MAKE_PROGRAM make -j 2 CACHE PATH "Path to build tool" FORCE)
    

    也无济于事。

总而言之,您可以通过将 CMAKE_MAKE_PROGRAM 变量设置为 script[=56 来重新定义 cmake --build 调用的行为=],它使用并行选项调用 make。但是您 可能不会影响直接 make 调用 .

的行为

您可以使用此命令设置环境变量 MAKEFLAGS

export MAKEFLAGS=-j$(nproc)

我的解决方案是编写一个小脚本,该脚本将 运行 包含各种其他功能,而不仅仅是 CPU 数量。

我调用我的脚本 mk 并执行 chmod 755 mk 这样我就可以 运行 它与 ./mk 在我的项目的根目录中。我还有一些标志,可以通过简单的命令行 运行 进行各种操作。例如,在编写代码时遇到很多错误,我喜欢将输出通过管道传输到 less。我可以用 ./mk -l 做到这一点,而不必重新输入所有繁重的 Unix 内容...

如您所见,我在几个有意义的地方使用了 -j4。对于 -l 选项,我不想要它,因为在这种情况下它最终会导致同时打印多个错误(我之前试过!)

#!/bin/sh -e
#
# Execute make

case "" in
"-l")
    make -C ../BUILD/Debug 2>&1 | less -R
    ;;

"-r")
    make -j4 -C ../BUILD/Release
    ;;

"-d")
    rm -rf ../BUILD/Debug/doc/lpp-doc-?.*.tar.gz \
           ../BUILD/Debug/doc/lpp-doc-?.*
    make -C ../BUILD/Debug
    ;;

"-t")
    make -C ../BUILD/Debug
    ../BUILD/Debug/src/lpp tests/suite/syntax-print.logo
    g++ -std=c++14 -I rt l.cpp rt/*.cpp
    ;;

*)
    make -j4 -C ../BUILD/Debug
    ;;

esac

# From the https://github.com/m2osw/lpp project

使用 CMake,除非如 Tsyvarev 所述,您创建自己的脚本,否则它不会工作。但我个人认为从您的 make 脚本 调用 make 是不明智的。此外,它可能会破坏构建过程,而构建过程不会期望 奇怪的脚本 。最后,正如我提到的,我的脚本允许我根据情况改变选项。

我通常在 linux 中使用别名来设置 cm 等于 cmake .. && make -j12。或者写一个 shell 来指定 make 和 clean progress ...

alias cm='cmake .. && make -j12'

然后使用cm在单个命令中制作。