最简可用CMakeLists.txt需三步:cmake_minimum_required(VERSION 3.10)、project(MyApp LANGUAGES CXX)、add_executable(myapp main.cpp);头文件用target_include_directories(myapp PRIVATE include)指定路径;链接库须find_package()后显式target_link_libraries();构建务必在独立build目录中执行。

直接用 CMake 编译 C++ 项目,核心不是写“教程”,而是让 CMakeLists.txt 正确描述你的源码结构、依赖和构建目标——写错一行 add_executable() 或漏掉 target_include_directories(),就会报错或链接失败。
怎么写最简可用的 CMakeLists.txt
从单个 main.cpp 开始,避免一上来就加子目录、库、测试。CMake 版本声明、项目名、可执行文件定义三步必须齐:
-
cmake_minimum_required(VERSION 3.10)—— 低于 3.10 的版本不支持target_compile_features()等常用功能,3.10 是当前安全下限 -
project(MyApp LANGUAGES CXX)—— 显式声明只用 C++,避免 CMake 自动启用 C 编译器导致奇怪警告 -
add_executable(myapp main.cpp)—— 文件名必须真实存在,路径是相对于CMakeLists.txt所在目录的;不能写成add_executable(myapp ./src/main.cpp)(除非CMakeLists.txt在项目根目录且src/是子目录)
头文件找不到?重点查 target_include_directories()
编译报错 fatal error: xxx.h: No such file or directory,90% 是没告诉 CMake 去哪找头文件。不要用全局 include_directories()(已过时且污染所有 target),改用 target 级别设置:
- 如果头文件在
include/目录下:target_include_directories(myapp PRIVATE include) -
PRIVATE表示只影响myapp自身编译,不传递给依赖它的其他 target;要用PUBLIC只有当你封装的是库且头文件需被使用者包含时 - 路径是相对路径,
include指的是CMakeLists.txt同级或子目录下的include/;若头文件在../common/include,就得写../common/include
链接第三方库(如 pthread 或 fmt)必须分两步
只写 find_package(fmt REQUIRED) 不够,也不等于自动链接——CMake 只负责找到库位置,链接动作要显式触发:
立即学习“C++免费学习笔记(深入)”;
- 系统库(如
pthread):target_link_libraries(myapp PRIVATE pthread) - CMake 包装过的库(如
fmt):find_package(fmt REQUIRED)+target_link_libraries(myapp PRIVATE fmt::fmt)(注意::和别名,不是fmt) - 静态库文件(如
libz.a):target_link_libraries(myapp PRIVATE /path/to/libz.a),但更推荐用add_library(z STATIC IMPORTED)再链接,便于跨平台
构建命令别硬记,用好 build/ 目录隔离
永远不在源码目录运行 cmake .。CMake 生成的中间文件(CMakeCache.txt、Makefile、对象文件)会污染源码树,且切换编译器或配置时极易出错:
- 正确流程:
mkdir build && cd build && cmake .. && make - 想换构建类型:
cmake -DCMAKE_BUILD_TYPE=Release ..(Debug是默认值,但显式写出来更可控) - 修改了
CMakeLists.txt后,进build/目录重新运行cmake ..即可,不用删整个目录(除非改了cmake_minimum_required或变量作用域)
真正卡住人的地方,往往不是语法,而是路径是否真实存在、target 名称是否拼错、PRIVATE/PUBLIC 是否用反、或者 find_package() 找到的库实际没安装——这些错误信息藏在 cmake .. 输出里,而不是 make 阶段。











