当前位置: 首页 > news >正文

CMake 完全实战指南:从入门到精通

CMake 完全实战指南:从入门到精通

一、CMake 核心概念

1. CMake 是什么?

  • 构建系统生成器:生成各种平台的构建文件(Makefile、VS项目等)
  • 跨平台解决方案:同一份配置适配不同操作系统
  • 现代C/C++标准:推荐用于新项目开发

2. 核心工作流程

CMakeLists.txt
CMake生成器
目标平台
Linux/macOS
生成 Makefile
Windows
生成 VS项目
Ninja
生成 build.ninja
使用 make 构建
使用 MSBuild 构建
使用 ninja 构建

二、快速入门:5分钟上手

1. 基础项目结构

myapp/
├── CMakeLists.txt   # CMake配置文件
├── main.cpp         # 源代码
└── build/           # 构建目录(建议创建)

2. 最小 CMakeLists.txt

# 指定CMake最低版本
cmake_minimum_required(VERSION 3.10)# 设置项目名称
project(MyApp)# 添加可执行文件
add_executable(myapp main.cpp)

3. 构建命令序列

# 创建构建目录
mkdir build && cd build# 生成构建系统(默认生成Makefile)
cmake ..# 编译程序
make# 运行程序
./myapp

三、核心语法详解

1. 项目设置

cmake_minimum_required(VERSION 3.20)  # 最低版本要求
project(MyApp                         # 项目名称VERSION 1.0.0                     # 项目版本DESCRIPTION "My Awesome App"      # 项目描述LANGUAGES CXX                     # 使用语言(CXX=C++)
)

2. 添加可执行文件

# 添加单个源文件
add_executable(app_single main.cpp)# 添加多个源文件
add_executable(app_multi main.cpputils.cppgraphics.cpp
)# 使用变量管理源文件
set(APP_SOURCESsrc/main.cppsrc/utils.cppsrc/graphics.cpp
)
add_executable(myapp ${APP_SOURCES})

3. 添加库文件

# 创建静态库
add_library(math_static STATIC math.cpp)# 创建动态库(共享库)
add_library(math_shared SHARED math.cpp)# 头文件接口库(无源文件)
add_library(math_interface INTERFACE)
target_include_directories(math_interface INTERFACE include)

4. 链接库文件

# 链接库到可执行文件
target_link_libraries(myapp PRIVATE math_static)# 不同链接范围:
# PRIVATE   - 仅当前目标使用
# INTERFACE - 仅依赖者使用
# PUBLIC    - 当前目标和依赖者都使用

5. 包含头文件目录

# 全局包含(旧式)
include_directories(include)# 目标级包含(推荐)
target_include_directories(myappPRIVATE src${CMAKE_CURRENT_SOURCE_DIR}/includePUBLIC$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>$<INSTALL_INTERFACE:include>
)

四、生成 Makefile 实战

1. 基础生成命令

# 生成标准Makefile
cmake -S . -B build -G "Unix Makefiles"# 指定构建类型
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release# 设置安装前缀
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr/local

2. 高级生成选项

# 设置编译器
cmake -S . -B build -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++# 交叉编译配置
cmake -S . -B build \-DCMAKE_SYSTEM_NAME=Linux \-DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc \-DCMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++# 生成编译数据库(用于工具链)
cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON

3. 构建与安装

# 使用生成的Makefile构建
cd build
make -j$(nproc)       # 并行编译# 运行测试
make test# 安装程序
sudo make install# 清理构建
make clean

五、项目结构最佳实践

1. 标准项目布局

myproject/
├── CMakeLists.txt            # 根配置文件
├── cmake/                    # CMake模块
│   ├── FindMyLib.cmake
│   └── Config.cmake.in
├── include/                  # 公共头文件
│   └── myproject/
│       └── utils.h
├── src/                      # 源代码
│   ├── CMakeLists.txt
│   ├── main.cpp
│   └── utils.cpp
├── tests/                    # 测试代码
│   ├── CMakeLists.txt
│   └── test_utils.cpp
└── build/                    # 构建目录

2. 模块化配置示例

根 CMakeLists.txt:

cmake_minimum_required(VERSION 3.20)
project(MyProject VERSION 1.0)# 包含子目录
add_subdirectory(src)
add_subdirectory(tests)# 安装配置
include(GNUInstallDirs)
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

src/CMakeLists.txt:

# 添加库
add_library(myproject_lib STATIC utils.cpp)# 包含目录
target_include_directories(myproject_libPUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>$<INSTALL_INTERFACE:include>
)# 添加可执行文件
add_executable(myproject_main main.cpp)
target_link_libraries(myproject_main PRIVATE myproject_lib)# 安装规则
install(TARGETS myproject_lib myproject_mainARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

六、高级技巧

1. 条件编译

option(ENABLE_GPU "Enable GPU acceleration" OFF)if(ENABLE_GPU)find_package(CUDA REQUIRED)target_sources(myapp PRIVATE gpu_kernels.cu)target_link_libraries(myapp PRIVATE CUDA::cudart)
endif()# 命令行启用:cmake -DENABLE_GPU=ON ..

2. 第三方库集成

# 查找系统库
find_package(OpenSSL REQUIRED)# 使用FetchContent下载
include(FetchContent)
FetchContent_Declare(jsonGIT_REPOSITORY https://github.com/nlohmann/jsonGIT_TAG v3.11.2
)
FetchContent_MakeAvailable(json)# 链接库
target_link_libraries(myapp PRIVATE OpenSSL::SSLnlohmann_json::nlohmann_json
)

3. 自定义构建命令

# 生成配置文件
configure_file(config.h.in${CMAKE_CURRENT_BINARY_DIR}/config.h
)# 添加自定义目标
add_custom_target(DocumentationCOMMAND doxygen DoxyfileWORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}COMMENT "Generating API documentation"
)# 文件操作
file(GLOB_RECURSE SOURCES "src/*.cpp")
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/generated)

七、与 Makefile 混用场景

1. 逐步迁移策略

# 在CMake中调用遗留Makefile
add_custom_target(build_legacyCOMMAND make -j4 -C legacy_codeWORKING_DIRECTORY ${CMAKE_SOURCE_DIR}COMMENT "Building legacy components"
)# 主目标依赖
add_executable(myapp main.cpp)
add_dependencies(myapp build_legacy)# 包含生成的头文件
target_include_directories(myapp PRIVATE legacy_code/output)

2. Makefile 调用 CMake

# Makefile 封装 CMake
BUILD_DIR = build
CMAKE = cmake
MAKE = makeall: configure buildconfigure:mkdir -p $(BUILD_DIR)cd $(BUILD_DIR) && $(CMAKE) ..build:cd $(BUILD_DIR) && $(MAKE)clean:rm -rf $(BUILD_DIR).PHONY: all configure build clean

八、最佳实践总结

  1. 源码与构建分离:始终在 build 目录构建

    cmake -S . -B build
    
  2. 目标级别配置:使用 target_* 命令替代全局命令

  3. 现代 CMake 特性

    • 使用 target_link_libraries 传递依赖
    • 使用生成器表达式 $<...>
    • 使用 PUBLIC/PRIVATE/INTERFACE 作用域
  4. 版本管理

    # 在根 CMakeLists.txt 中设置
    set(CMAKE_CXX_STANDARD 17)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    
  5. 工具集成

    # 启用测试
    enable_testing()
    add_test(NAME MyTest COMMAND test_executable)
    

九、常见问题解决

问题解决方案
“Could NOT find package”添加 find_package 路径:-DCMAKE_PREFIX_PATH=/path/to/lib
头文件找不到检查 target_include_directories 路径
链接错误确认 target_link_libraries 包含所需库
CMake版本过低升级CMake或调整 cmake_minimum_required
跨平台问题使用平台检测:if(WIN32) ... elseif(UNIX) ...
构建缓慢使用 ccache-DCMAKE_CXX_COMPILER_LAUNCHER=ccache

十、学习资源推荐

  1. 官方文档:https://cmake.org/cmake/help/latest/
  2. 现代CMake教程
    • https://modern-cmake-cn.github.io/ (中文)
    • https://cliutils.gitlab.io/modern-cmake/ (英文)
  3. 实战项目参考
    • https://github.com/ttroy50/cmake-examples
    • https://github.com/onqtam/awesome-cmake
  4. 在线练习:https://cmake.org/cmake/help/latest/guide/tutorial/index.html

掌握CMake是C/C++开发的必备技能。从简单项目开始实践,逐步应用高级特性,你将大大提升项目构建效率!

http://www.lryc.cn/news/603945.html

相关文章:

  • MySQL的JDBC编程
  • Seq2Seq学习笔记
  • 【绘制图像轮廓】——图像预处理(OpenCV)
  • idea运行tomcat日志乱码问题
  • CentOS安装ffmpeg并转码视频为mp4
  • 编程算法在金融、医疗、教育、制造业等领域的落地案例
  • 单片机(STM32-WIFI模块)
  • windows电脑如何截屏 windows电脑截屏教程汇总
  • 【机器学习深度学习】DeepSpeed框架:高效分布式训练的开源利器
  • Python Flask: Windows 2022 server SMB账户(共享盘账户)密码修改
  • 影刀RPA_初级课程_玩转影刀自动化_EXCEL操作自动化
  • 数据结构(5)单链表算法题(中)
  • 第二十二天(数据结构,无头节点的单项链表)
  • 期刊基础学习
  • 抵御酒店管理系统收银终端篡改攻击 API 加密的好处及实现——仙盟创梦IDE
  • 携全双工语音通话大模型亮相WAIC,Soul重塑人机互动新范式
  • BitMart 启动中文品牌“币市”:引领加密资产本地化发展新篇章
  • 【Linux】批量处理多个用户的 sudo 权限问题
  • 01背包问题:Python动态规划深度解析与工程实践
  • napping-1.0.1靶机练习
  • MySQL(配置)——MariaDB使用
  • 2025年Solar应急响应公益月赛-7月笔记ing
  • Java 10 新特性解析
  • 机器学习笔记(四)——聚类算法KNN、Kmeans、Dbscan
  • 域名常见问题集(九)——域名市场介绍
  • 基于JavaWeb的兼职发布平台的设计与实现
  • LangChain和LangGraph 里面的 `create_react_agent`有什么不同
  • 从0到1理解大语言模型:读《大语言模型:从理论到实践(第2版)》笔记
  • Marin说PCB之POC电路layout设计仿真案例---10
  • AI 对话玩具的语音芯片模块方案设计与应用场景​