【问题标题】:From CMake setup 'make' to use '-j' option by default从 CMake setup 'make' 到默认使用 '-j' 选项
【发布时间】:2017-01-16 20:51:13
【问题描述】:

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

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

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

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

这是我在CMakeList.txt中使用的代码的sn-p:

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})

非常感谢。

【问题讨论】:

  • 你的代码没有任何部分运行任何东西。那么,你想加速什么?请注意,cmake 阶段不能并行化:CMake 脚本是按顺序逐行处理的,就像在其他脚本语言(如 python)中一样。相反,构建阶段可以并行化,make -j 正是这样做的。
  • 关于 CMake / 构建性能的一些建议:stackoverflow.com/q/37327526/2799037
  • 我知道它没有运行,它是 CMakeList.txt 的一部分,我只是想设置 CMAKE_MAKE_PROGRAM 并想在每次调用 make 时调用“make -j N”终端,而不是每次都在终端中显式设置,
  • 我建议使用ninja 代替make。它速度更快,并且默认使用所有可用的内核进行编译/链接。
  • @DrJ:我已将您的评论添加到问题帖子中,因为它澄清了很多问题。将来,倾向于通过您的双手来做到这一点。在 Stack Overflow 上,描述问题的所有信息都应在问题帖子中。评论是临时的

标签: cmake parallel-builds


【解决方案1】:

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

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

export MAKEFLAGS=-j8

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

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

【讨论】:

  • 请注意,扩展 glob 模式下的某些 shell (zsh) 将 ^processor 扩展为 glob 模式,请务必使用 grep -c "^processor" /proc/cpuinfo
【解决方案2】:

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

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

    CMAKE_MAKE_PROGRAM 变量设置为供项目代码使用。 cmake(1) --build 和 ctest(1) --build-and-test 工具也使用该值来启动本机构建过程。

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

    这些生成器将 CMAKE_MAKE_PROGRAM 存储在 CMake 缓存中,以便用户对其进行编辑。

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

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

    该值可能是可执行文件的完整路径,或者如果预期位于 PATH 中,则只是工具名称。

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

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

    也无济于事)。

总之,您可以通过将CMAKE_MAKE_PROGRAM 变量设置为脚本 来重新定义cmake --build 调用的行为,该脚本使用并行选项调用make。但是您可能不会影响直接make 调用的行为

【讨论】:

  • 感谢您的详细解答
  • 你可以为“make -jN”创建一个别名
【解决方案3】:

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

export MAKEFLAGS=-j$(nproc)

【讨论】:

  • @sanmai 在 4.1 中对我来说很好。
【解决方案4】:

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

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

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

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

case "$1" 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 是不明智的。另外,它可能会破坏一个不期望奇怪的脚本的构建过程。最后,正如我所提到的,我的脚本允许我根据情况改变选项。

【讨论】:

    【解决方案5】:

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

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

    然后使用cm 在单个命令中生成。

    【讨论】:

    • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
    猜你喜欢
    • 1970-01-01
    • 2010-12-06
    • 1970-01-01
    • 1970-01-01
    • 2011-04-15
    • 2015-09-27
    • 2021-11-11
    相关资源
    最近更新 更多