0%

解决Windows下VSCode+CMake的C++项目编译慢的问题

摘要

  • 在Windows开发环境下,使用VSCode+CMake的C++项目,默认编译速度比较慢,找出原因并解决。

背景

  • 公司项目是在Windows开发环境,使用Microsoft Visual Studio 2017集成开发环境,VC14编译器。而我更习惯使用VSCode,所以接收代码后还是在VSCode编辑器下进行日常开发,通过CMake构建项目。
  • 但一直出现一个问题,无论是在CLion还是在Visual Studio 2017,项目编译速度都比在VSCode下快
  • 个人猜测,是某个编译开关,或者编译参数未设置。

未解决前

  • VSCode-CMake编译时CPU占用率:
    VSCode-CMake编译时CPU占用率

  • VSCode-CMake编译耗时:
    VSCode-CMake编译耗时

解决方法

  • 从编译时输出日志上来看,默认构建方式为串行构建。串行构建是指在构建过程中,任务按顺序一个接一个地执行。每个任务必须在前一个任务完成后才能开始。
  • 那解决方法就是开启并行构建。并行构建是指构建任务分解成多个子任务,并在多核或多处理器系统上同时执行这些任务。多个文件可以同时编译,编译完成后进行链接。
    1. 明确当前使用的编译器:cl.exe
    2. 增加并行编译选项: /MP
    3. 在CMake中配置:
      1
      2
      3
      if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
      add_compile_options(/MP)
      endif()

解决后

  • VSCode-CMake解决后–编译时CPU占用率:
    VSCode-CMake解决后--编译时CPU占用率

  • VSCode-CMake解决后–编译耗时:
    VSCode-CMake解决后--编译耗时

总结

在 C++ 开发中,构建的效率对项目开发和部署至关重要。并行构建和串行构建是两种主要的构建方式,它们各有适用场景和优化方法。以下是详细解析:


1. 串行构建

定义

串行构建是指按照依赖关系顺序,一个编译任务接一个地运行,所有任务都在单一线程中依次执行。

特点

  • 执行顺序:每次只编译一个文件或模块。
  • 时间开销:时间复杂度较高,尤其是大型项目中,编译时间可能会很长。
  • 资源利用:通常只使用单一 CPU 核心,其他核心处于空闲状态。
  • 稳定性:依赖明确,不会出现任务调度或资源竞争问题。

适用场景

  • 小型项目:代码文件少、依赖简单。
  • 调试依赖问题:确保编译按顺序执行,有助于分析构建流程中的错误。
  • 硬件限制:在单核 CPU 或资源受限环境下运行。

2. 并行构建

定义

并行构建是指通过多线程或多进程方式,同时编译多个文件或模块,从而提高构建效率。

特点

  • 执行顺序:任务调度器根据依赖关系,尽可能同时运行多个任务。
  • 时间开销:显著减少构建时间,尤其在多核 CPU 上表现更佳。
  • 资源利用:充分利用多核 CPU 和内存带宽,提升构建效率。
  • 复杂性:需要解决任务调度和资源争用的问题,可能引入构建冲突。

适用场景

  • 大型项目:模块化良好,文件数目多,编译时间长。
  • 多核系统:现代多核 CPU 可以显著加速并行编译。
  • 自动化构建:如 CI/CD 系统,要求快速完成构建任务。

3. 并行构建的实现方式

在 MSVC(cl.exe)中

  • 使用 /MP 参数
    启用并行编译,具体线程数根据 CPU 核心数自动调整。

    1
    cl.exe /MP source.cpp
  • 设置线程数
    通过 /MPn 指定最大线程数,例如:

    1
    cl.exe /MP8 source.cpp
  • 在 CMake 中配置

    1
    2
    3
    if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
    add_compile_options(/MP)
    endif()

在 GCC 和 Clang 中

  • 使用 -j 参数
    配合 makeninja 构建系统,指定并行任务数量。

    1
    make -j8
  • 自动选择线程数
    不指定具体数量时,通常根据 CPU 核心数自动调整。

    1
    make -j
  • 在 CMake 中配置
    生成 Ninja 构建文件(支持并行):

    1
    2
    cmake -G Ninja .
    cmake --build . -j8

在 MSBuild 中

  • 使用 /m 参数
    启用多线程构建。

    1
    msbuild MySolution.sln /m
  • 指定线程数
    设置具体线程数量:

    1
    msbuild MySolution.sln /m:8

在 Xcode 中

  • 并行构建开关
    默认情况下,Xcode 使用多线程进行构建。

  • 调整并行任务数
    可通过 xcodebuild 配置 -parallelizeTargets


4. 并行构建的优势与挑战

优势

  • 显著加速:在多核环境下,构建速度可以提升数倍。
  • 资源高效:充分利用 CPU 和内存资源,降低硬件浪费。
  • 现代硬件支持:适配当前主流硬件性能。

挑战

  • 依赖关系管理:需要正确分析模块间的依赖,避免并行任务冲突。
  • 资源竞争:过多的线程可能导致内存不足或 I/O 瓶颈。
  • 调试难度增加:并行构建中的错误可能更难定位。

5. 并行和串行的对比

特性 串行构建 并行构建
构建速度
资源利用
依赖处理 简单 复杂
硬件需求 适合单核系统 适合多核系统
调试 简单 较难
适用场景 小型项目、简单依赖 大型项目、复杂依赖

6. 性能优化建议

  • 增量构建:避免每次全量构建,只构建发生变更的模块。
  • 依赖优化:减少模块间的循环依赖。
  • 使用高效工具链:如 Ninja,其调度机制比 Make 更高效。
  • 硬件优化:在 SSD 上构建或提升 CPU 核心数。

通过合理使用并行构建和优化工具链,可以显著提升 C++ 项目的开发效率。

感谢老板支持!敬礼(^^ゞ