CMake最低版本应设为3.20以稳定支持Ninja跨平台特性;add_executable禁用变量展开生成文件;必须显式链接Threads::Threads;统一设置CMAKE_CXX_STANDARD及REQUIRED选项。

cmake_minimum_required 版本设太低会导致 Ninja 生成失败
很多项目盲目照抄旧教程写 cmake_minimum_required(VERSION 3.10),结果在 macOS 或 Windows 上用 Ninja 生成器时突然报错:CMake Error: Generator: Ninja does not support toolset specification。这不是 Ninja 本身的问题,而是旧版 CMake 对 Ninja 的 toolset、architecture 等跨平台特性支持不全。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 新项目统一从
cmake_minimum_required(VERSION 3.20)起步——它稳定支持 Ninja + MSVC toolset / Xcode architecture / Clang cross-compilation - 若必须兼容老环境(如某些 CI 的 CentOS 7),最低不要低于
3.16,且需显式禁用toolset和architecture参数 - 检查当前 CMake 版本:终端运行
cmake --version,别只看 IDE 内置的版本提示
add_executable 里混用源码路径和生成文件会破坏跨平台构建缓存
常见错误是把 add_executable(myapp src/main.cpp ${GENERATED_HEADERS}) 这样写,其中 ${GENERATED_HEADERS} 是通过 configure_file 或自定义命令生成的头文件。在 Windows 上可能暂时正常,但 Linux/macOS 下 Ninja 构建时会跳过依赖检查,导致修改模板后不重新生成头文件,程序静默编译失败。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 所有生成文件必须用
add_custom_command显式声明输出,并用DEPENDS绑定输入;再通过add_custom_target将其纳入构建图 -
add_executable只接收物理存在的源文件或target_sources添加的生成物,禁止直接展开变量列表 - 跨平台时优先用
file(GENERATE)替代 shell 脚本生成头文件,它由 CMake 原生处理,不依赖/bin/sh或cmd.exe
find_package(Threads) 后不调用 target_link_libraries 就链接失败
Windows 上用 MSVC 编译时,find_package(Threads) 成功返回,但 target_link_libraries(myapp PRIVATE Threads::Threads) 没写,结果链接阶段报 unresolved external symbol _beginthreadex;Linux/macOS 则可能悄无声息地用上默认 pthread,但一旦开启 -pthread 标志或使用 std::jthread 就暴露问题。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 只要用了
std::thread、std::mutex或任何 POSIX/Win32 线程 API,就必须显式链接Threads::Threads - 不要用
find_library(THREADS_LIBRARIES)手动拼接,CMake 3.1+ 的Threads::Threads是 IMPORTED INTERFACE TARGET,能自动处理-pthread、/MT等编译器差异 - 检查是否生效:构建后查看
build/CMakeFiles/myapp.dir/link.txt,确认里面有-lpthread(Linux/macOS)或对应 MSVC 的线程库标记
Windows 下用 MSVC 时 CMAKE_CXX_STANDARD 默认值陷阱
新建工程没设 set(CMAKE_CXX_STANDARD 17),CMake 会按 MSVC 版本回退:VS 2019 默认 C++14,VS 2022 默认 C++17——但 Linux/macOS 的 GCC/Clang 却按 CMake 版本走(3.1+ 默认 C++11)。结果同一份代码,在 Windows 上能编译 std::optional,Linux 上却报错说未声明。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 所有
add_executable/add_library之前,强制加一行set(CMAKE_CXX_STANDARD 17)或更高(如 20),并追加set(CMAKE_CXX_STANDARD_REQUIRED ON) - 避免用
set(CMAKE_CXX_EXTENSIONS OFF),它在 MSVC 下无效,反而让 Clang/GCC 禁用 GNU 扩展,引发更多兼容问题 - 如果项目要支持 C++20 模块,必须搭配
set(CMAKE_CXX_STANDARD 20)+set(CMAKE_CXX_EXTENSIONS OFF),且仅限 CMake 3.25+ 和 VS 2022 17.5+
find_package、每个 target_link_libraries、甚至每行 set() 都可能在某个平台悄悄失效——没有报错,只是行为不对。盯住构建日志里的 link.txt 和 CMakeCache.txt,比反复改 CMakeLists.txt 更有效。











