问题背景
在使用 Visual Studio 2022 开发跨平台 C++ 项目时,许多开发者会选择通过 WSL (Windows Subsystem for Linux) 直接在本地调试 Linux 环境下的程序。然而,近期在配置一个 CMake 项目时,遇到了以下报错:
CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage
CMake Error: CMake was unable to find a build program corresponding to "Ninja"
经排查发现,VS2022 默认在 Linux Debug 配置下使用 Ninja 作为构建工具,但 WSL 中的 Ubuntu 未安装 Ninja,导致配置失败。本文将记录如何通过修改 CMakePresets.json
切换至 Unix Makefiles 并显式指定编译器,最终解决问题。
根本原因分析
1. 为什么 VS2022 默认使用 Ninja?
Ninja 是一个轻量级构建工具,以构建速度快著称,许多现代 C++ 项目(如 Chromium、LLVM)推荐使用它。VS2022 的 CMake 集成默认会优先选择 Ninja,但需要系统环境中已安装该工具。
2. 为什么 WSL 中缺少 Ninja 会导致失败?
- CMake 生成器(Generator) 负责生成构建系统文件(如 Makefile 或 Ninja 文件)。
- 当预设配置中指定了
Ninja
,但系统中未安装时,CMake 无法生成构建规则,直接报错。 - 同时,未正确设置编译器路径(如
CMAKE_CXX_COMPILER
)会导致 CMake 无法找到编译器。
解决方案:切换至 Unix Makefiles
步骤 1:修改 CMakePresets.json
VS2022 的 CMake 项目通过 CMakePresets.json
管理不同环境的构建配置。找到项目根目录下的该文件,修改 Linux Debug 配置:
{
"name": "linux-debug",
"displayName": "Linux Debug",
"generator": "Unix Makefiles", // 关键修改:从 Ninja 改为 Unix Makefiles
"binaryDir": "${sourceDir}/out/build/${presetName}",
"installDir": "${sourceDir}/out/install/${presetName}",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_CXX_COMPILER": "/usr/bin/g++" // 显式指定编译器路径
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Linux"
},
"vendor": {
"microsoft.com/VisualStudioRemoteSettings/CMake/1.0": {
"sourceDir": "$env{HOME}/.vs/$ms{projectDirName}"
}
}
}
关键修改说明
-
generator
字段:从"Ninja"
改为"Unix Makefiles"
,这是 Linux 下标准的 Makefile 生成器。 -
CMAKE_CXX_COMPILER
字段:显式指定编译器路径(如/usr/bin/g++
或/usr/bin/clang++
),避免 CMake 自动检测失败。
步骤 2:确保 WSL 中安装必要的工具
在 WSL 的 Ubuntu 中运行以下命令,安装 Make 和 GCC/G++:
sudo apt-get update
sudo apt-get install build-essential # 包含 make、gcc、g++
步骤 3:清理并重新生成构建目录
为避免旧配置残留,删除原有的构建目录,在wsl里面的ubuntu系统里面,进入到相应的项目路径下,执行删除操作
rm -rf out/build/linux-debug
在 VS2022 中重新配置项目:
- 右键点击
CMakeLists.txt
,选择 “删除缓存并重新配置”。 - 选择 “Linux-Debug” 作为活动配置。
步骤 4:验证构建系统生成
进入构建目录 out/build/linux-debug
,检查是否生成以下文件:
- Makefile:CMake 生成的构建规则。
- CMakeCache.txt:确认编译器路径是否正确:
grep CMAKE_CXX_COMPILER CMakeCache.txt
CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++
步骤 5:编译并运行项目
在 VS2022 中直接点击 “生成” 按钮,或通过命令行编译:
cmake --build out/build/linux-debug
结果验证
- 编译成功:输出日志显示生成可执行文件,无报错。
- 程序运行:通过 VS2022 的 “启动调试” 或命令行启动程序,确认功能正常。
延伸讨论:Ninja vs. Makefile
特性 | Ninja | Unix Makefiles |
---|---|---|
构建速度 | 极快(适合大型项目) | 较慢(但稳定通用) |
依赖管理 | 简洁高效 | 基于时间戳,可靠性高 |
跨平台支持 | 需要额外安装 | 默认集成在 Linux 环境中 |
与 IDE 集成 | 需要配置 | 开箱即用 |
何时选择 Makefile?
- 项目规模较小,无需极致构建速度。
- 希望减少环境依赖(尤其是团队协作时)。
- 需要直接调试生成的 Makefile 规则。
总结
通过修改 CMakePresets.json
切换至 Unix Makefiles,开发者可以避免因缺失 Ninja 导致的构建失败问题,同时显式指定编译器路径能进一步降低环境差异带来的风险。对于跨平台 C++ 项目,理解 CMake 生成器的工作原理和工具链配置至关重要。如果未来需要高性能构建,只需安装 Ninja 并恢复生成器配置即可灵活切换。