cmake 不是编译器,只生成构建文件(如 makefile/.sln);cmake_minimum_required 和 project 必须开头,定义构建上下文并初始化关键变量,否则后续命令可能静默失败;add_executable 第一参数为输出名而非路径,多文件推荐用变量统一管理;必须采用 out-of-source 构建(如 mkdir build && cd build && cmake ..),避免污染源码树和缓存异常。

CMake 不是编译器,也不是构建工具本身,它只负责生成构建文件(比如 Makefile 或 .sln)。你不能跳过它直接编译源码,但可以跳过手动写 Makefile —— 这正是它的核心价值。
cmake_minimum_required 和 project 为什么必须放在开头
这两条指令定义了整个构建上下文的起点。CMake 解析 CMakeLists.txt 是顺序执行的,一旦遇到未声明的变量或未初始化的项目名,后续很多命令(比如 add_executable)会静默失败或报错如 CMake Error: PROJECT_NAME not set。
-
cmake_minimum_required(VERSION 3.10)不只是“建议版本”,它会强制拒绝低于该版本的 CMake 执行,避免语法不兼容(例如旧版不支持target_compile_features) -
project(demo)会自动设置PROJECT_NAME、CMAKE_PROJECT_NAME、PROJECT_VERSION等变量,并隐式调用enable_language(CXX);漏掉它,set(CMAKE_CXX_STANDARD 17)可能被忽略 - 常见错误:把
set(...)放在project()前 —— 此时CMAKE_CXX_STANDARD赋值无效,编译仍用默认标准(通常是 C++98)
add_executable 的路径和命名陷阱
add_executable 第一个参数是生成的可执行文件名,不是路径;第二个及之后的参数才是源文件路径,且必须相对于 CMakeLists.txt 所在目录。
- 错误写法:
add_executable(./bin/app main.cpp)→ 生成的文件名真叫./bin/app(含斜杠),在 Linux 下无法直接././bin/app运行 - 正确做法:保持名字简洁,用
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)统一控制输出位置 - 多文件时别硬编码:
add_executable(app main.cpp util.cpp logger.cpp)易遗漏;推荐先set(SOURCES main.cpp util.cpp logger.cpp)再add_executable(app ${SOURCES}) - 注意大小写:Windows 下
add_executable(App ...)生成App.exe,Linux 下生成App(无后缀),但若源码里写了#include "APP.hpp",大小写敏感系统(Linux/macOS)直接编译失败
为什么一定要用 out-of-source 构建(即单独建 build 目录)
在源码目录下直接运行 cmake . 是最常见也最危险的习惯。它会把 CMakeCache.txt、CMakeFiles/、Makefile 全塞进源码树,污染 git 工作区,还可能引发缓存残留导致配置不生效。
- 正确流程只有三步:
mkdir build && cd build && cmake .. - 这样所有中间产物都隔离在
build/内,删掉整个目录就彻底清理,不影响源码 - 如果用了 Ninja 生成器(
cmake -G Ninja ..),build/里不会出现Makefile,而是build.ninja—— 但原理一样,仍是 out-of-source - IDE(如 CLion、VS Code + CMake Tools)默认也走 out-of-source,它们的构建目录通常叫
cmake-build-debug或类似名称
常见报错:CMakeCache.txt 被锁死或内容错乱
这不是 bug,是 CMake 的缓存机制在起作用。当你改了 CMakeLists.txt 却没重新运行 cmake ..,或者中途中断了配置过程,CMakeCache.txt 可能残留旧状态,导致后续构建行为异常(比如明明加了 set(CMAKE_CXX_STANDARD 17) 却仍用 C++11 编译)。
- 最稳妥的修复方式:删掉整个
build/目录,重来 - 懒人方案:在
build/里执行cmake -U .(清除缓存)再cmake ..,但不如删目录干净 - 编辑
CMakeCache.txt手动改值风险极高 —— 某些条目(如CMAKE_BUILD_TYPE:STRING=Debug)修改后需重新运行cmake .. -DCMAKE_BUILD_TYPE=Release才真正生效,否则只是覆盖缓存值,不触发重配置 - 如果你在 CI 中看到
CMake Error: The source directory does not appear to contain CMakeLists.txt,大概率是工作目录进错了,不是build/的上一级
真正的难点不在语法,而在于理解 CMake 的“两阶段”本质:第一阶段(cmake)只读取 CMakeLists.txt 生成构建文件,不做编译;第二阶段(make/ninja/msbuild)才真正调用编译器。这两个阶段的输入输出、错误来源、调试方法完全不同,混在一起排查就会反复踩坑。











