如何加快我的CMake启用C++项目的编译时间?

Flo*_*ian 14 performance nmake compilation cmake gnu-make

我最近遇到了几个关于改善CMake启用C++项目周转时间的具体方面的问题(比如"我应该在什么级别分配我的构建过程?""cmake rebuild_cache 只是一个子目录?"),我是想知道是否有更一般的指导利用CMake提供的特定可能性.如果可能没有跨平台编译时优化,我主要对Visual Studio或基于GNU toochain的方法感兴趣.

我已经意识到并投资了一般推荐的领域来加速C++构建:

  1. 更改/优化/微调工具链

  2. 优化您的代码库/软件架构(例如,通过减少依赖关系并使用明确定义的子项目 - 单元测试)

  3. 投资更好的硬件(SSD,CPU,内存)

喜欢在这里,这里这里推荐.所以我在这个问题上的重点是第一点.

另外我知道在CMake的Wiki中可以找到的建议:

前者只处理基础(并行make),后者主要处理如何加速解析CMake文件.

为了使这更具体一点,如果我从这里使用MSYS/GNU的100个库获取我的CMake示例,我得到了以下time测量结果:

$ cmake --version
cmake version 3.5.2
CMake suite maintained and supported by Kitware (kitware.com/cmake).

$ time -p cmake -G "MSYS Makefiles" ..
-- The CXX compiler identification is GNU 4.8.1
...
-- Configuring done
-- Generating done
-- Build files have been written to: [...]
real 27.03
user 0.01
sys 0.03        

$ time -p make -j8
...
[100%] Built target CMakeTest
real 113.11
user 8.82
sys 33.08
Run Code Online (Sandbox Code Playgroud)

所以我总共需要大约140秒,而我的目标 - 对于这个非常简单的例子 - 将会降低到标准设置/工具的10-20%.

Flo*_*ian 9

这是我使用CMake和Visual Studio或GNU工具链得到的好结果:

  1. Ninja交换GNU make .它更快,自动使用所有可用的CPU内核,并具有良好的依赖关系管理.请注意

    a.)您需要正确设置CMake中的目标依赖项.如果你到达构建对另一个工件的依赖关系,它必须等到编译它们(同步点).

    $ time -p cmake -G "Ninja" ..
    -- The CXX compiler identification is GNU 4.8.1
    ...
    real 11.06
    user 0.00
    sys 0.00
    
    $ time -p ninja
    ...
    [202/202] Linking CXX executable CMakeTest.exe
    real 40.31
    user 0.01
    sys 0.01
    
    Run Code Online (Sandbox Code Playgroud)

    b.)链接总是这样一个同步点.因此,您可以更多地使用CMake的对象库来减少这些,但它会使您的CMake代码更加丑陋.

    $ time -p ninja
    ...
    [102/102] Linking CXX executable CMakeTest.exe
    real 27.62
    user 0.00
    sys 0.04
    
    Run Code Online (Sandbox Code Playgroud)
  2. 将较不频繁更改或稳定的代码部分拆分为单独的CMake项目并使用CMake ExternalProject_Add()或 - 如果您转换为某些库的二进制交付 - find_library().

  3. 为您的日常工作考虑一组不同的编译器/链接器选项(但前提是您还有一些测试时间/经验与最终版本构建选项).

    a.)跳过优化部分

    b.)尝试增量链接

  4. 如果您经常对CMake代码本身进行更改,请考虑从针对您机器架构优化的来源重建CMake.CMake正式分发的二进制文件只是对每种可能的CPU架构的一种妥协.

    当我使用MinGW64/MSYS重建CMake 3.5.2时,例如

    cmake -DCMAKE_BUILD_TYPE:STRING="Release"
          -DCMAKE_CXX_FLAGS:STRING="-march=native -m64 -Ofast -flto" 
          -DCMAKE_EXE_LINKER_FLAGS:STRING="-Wl,--allow-multiple-definition"
          -G "MSYS Makefiles" .. 
    
    Run Code Online (Sandbox Code Playgroud)

    我可以加速第一部分:

    $ time -p [...]/MSYS64/bin/cmake.exe -G "Ninja" ..
    real 6.46
    user 0.03
    sys 0.01
    
    Run Code Online (Sandbox Code Playgroud)
  5. 如果您的文件I/O非常慢,并且由于CMake使用专用二进制输出目录,请使用RAM磁盘.如果仍使用硬盘驱动器,请考虑切换到固态硬盘.

  6. 根据您的最终输出文件,将GNU标准链接器与Gold Linker交换.甚至比Gold Linker还要快于LLVM项目.您必须检查它是否已支持您平台上所需的功能.

  7. 使用Clang/c2代替Visual C++编译器.有关Visual C++编译器的性能建议,请参阅https://blogs.msdn.microsoft.com/vcblog/2016/10/26/recommendations-to-speed-c-builds-in-visual-工作室/

  8. Increadibuild可以增加编译时间.

参考