c++如何使用cmake编译项目_c++ cmake编写入门【教程】

最简可用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

链接第三方库(如 pthreadfmt)必须分两步

只写 find_package(fmt REQUIRED) 不够,也不等于自动链接——CMake 只负责找到库位置,链接动作要显式触发:

  • 系统库(如 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.txtMakefile、对象文件)会污染源码树,且切换编译器或配置时极易出错:

  • 正确流程: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 阶段。