【CMake】概述

CMake 是一个跨平台的自动化构建系统 ,用于管理软件构建过程。它使用独立于编译器的配置文件 (CMakeLists.txt)来定义构建规则,然后生成对应平台的本地构建文件(如 Makefile、Visual Studio 项目等)。

核心特性

1. 跨平台支持

  • Windows: 生成 Visual Studio 项目
  • Linux/Unix: 生成 Makefile
  • macOS: 生成 Xcode 项目
  • 其他:Ninja、MinGW 等

2. 主要功能模块

  • CMake: 核心配置和生成工具
  • CTest: 测试驱动工具
  • CPack: 打包工具

基本工作流程

text 复制代码
编写 CMakeLists.txt 
    → cmake 配置(生成构建系统文件) 
    → 原生构建工具编译(如 make/ninja/msbuild)

简单示例

cmake 复制代码
# CMakeLists.txt 最小示例
cmake_minimum_required(VERSION 3.10)
project(MyProject VERSION 1.0)

add_executable(myapp main.cpp)

关键概念

目标(Targets)

cmake 复制代码
# 创建可执行文件
add_executable(myapp main.cpp)

# 创建库
add_library(mylib STATIC lib.cpp)  # 静态库
add_library(mylib SHARED lib.cpp)  # 动态库
add_library(mylib INTERFACE)       # 接口库(仅头文件库)

变量

cmake 复制代码
# 设置变量
set(MY_VARIABLE "value")

# 缓存变量(可在 GUI 中修改)
set(USE_FEATURE ON CACHE BOOL "启用特性")

# 环境变量
set(ENV{PATH} "/usr/local/bin:$ENV{PATH}")

# 预定义变量
message("项目源目录: ${CMAKE_SOURCE_DIR}")
message("构建目录: ${CMAKE_BINARY_DIR}")

条件判断

cmake 复制代码
if(WIN32)
    message("Windows 平台")
elseif(APPLE)
    message("macOS 平台")
elseif(UNIX)
    message("Linux/Unix 平台")
endif()

if(CMAKE_BUILD_TYPE STREQUAL "Debug")
    set(DEBUG_FLAGS "-g -O0")
endif()

循环

cmake 复制代码
# foreach 循环
foreach(item IN ITEMS a b c)
    message("项目: ${item}")
endforeach()

# 遍历文件列表
file(GLOB SOURCE_FILES "src/*.cpp")
foreach(src_file IN LISTS SOURCE_FILES)
    message("源文件: ${src_file}")
endforeach()

现代 CMake 最佳实践

1. 使用目标属性而非全局设置

cmake 复制代码
# 推荐做法(现代 CMake)
add_library(mylib src/lib.cpp)
target_include_directories(mylib
    PUBLIC 
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
        $<INSTALL_INTERFACE:include>
)
target_compile_features(mylib PUBLIC cxx_std_17)
target_link_libraries(mylib PUBLIC Threads::Threads)

# 避免使用(传统方式)
include_directories(include)      # 不推荐
link_directories(lib)            # 不推荐

2. 依赖管理

cmake 复制代码
# 查找系统库
find_package(OpenCV REQUIRED COMPONENTS core imgproc)

# 使用 FetchContent 获取外部项目
include(FetchContent)
FetchContent_Declare(
    googletest
    GIT_REPOSITORY https://github.com/google/googletest.git
    GIT_TAG release-1.11.0
)
FetchContent_MakeAvailable(googletest)

# 链接库
target_link_libraries(myapp PRIVATE OpenCV::opencv GTest::gtest)

常用命令速查

项目配置命令

cmake 复制代码
cmake_minimum_required(VERSION 3.10)      # 指定 CMake 最低版本
project(MyProject                         # 定义项目
    VERSION 1.0.0
    DESCRIPTION "我的项目"
    LANGUAGES C CXX
)

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

文件操作命令

cmake 复制代码
# 收集源文件
file(GLOB SOURCES "src/*.cpp" "src/*.c")
file(GLOB_RECURSE ALL_SOURCES "src/**/*.cpp")

# 复制文件
configure_file(config.h.in config.h)     # 配置头文件
file(COPY data/ DESTINATION ${CMAKE_BINARY_DIR}/data)

测试支持

cmake 复制代码
enable_testing()                          # 启用测试

add_test(
    NAME MyTest
    COMMAND mytest_exe arg1 arg2
)

# 添加测试用例
include(CTest)
add_test(NAME FeatureTest COMMAND myapp --test-feature)

典型项目结构

text 复制代码
myproject/
├── CMakeLists.txt                    # 根 CMake 文件
├── README.md
├── LICENSE
├── cmake/                           # CMake 模块文件
│   ├── FindMyLib.cmake
│   └── Config.cmake.in
├── include/                         # 公共头文件
│   └── myproject/
│       └── mylib.h
├── src/                            # 源代码
│   ├── CMakeLists.txt
│   ├── main.cpp
│   └── mylib.cpp
├── tests/                          # 测试代码
│   ├── CMakeLists.txt
│   └── test_mylib.cpp
├── examples/                       # 示例代码
│   ├── CMakeLists.txt
│   └── example1.cpp
└── external/                       # 外部依赖(可选)
    └── CMakeLists.txt

构建步骤示例

bash 复制代码
# 1. 创建构建目录并进入
mkdir build && cd build

# 2. 配置项目(生成构建文件)
cmake .. -DCMAKE_BUILD_TYPE=Release -DUSE_FEATURE=ON

# 3. 编译项目
cmake --build . --config Release

# 4. 运行测试
ctest -C Release --verbose

# 5. 安装(可选)
cmake --install . --prefix /usr/local

CMake 的优势

  1. 真正的跨平台:同一配置支持 Windows、Linux、macOS 等
  2. 构建系统生成器:不直接构建,而是生成 Makefile、.sln 等
  3. 依赖管理:强大的 find_package 和现代 FetchContent
  4. 模块化:支持大型项目的模块化组织
  5. IDE 集成:与 VS、CLion、VS Code 等完美集成
  6. 活跃社区:丰富的第三方模块和文档

学习路径建议

  1. 初级阶段:掌握基本语法,创建简单可执行文件
  2. 中级阶段:学习库的创建和链接,理解 PUBLIC/PRIVATE/INTERFACE
  3. 高级阶段:掌握安装和打包,编写 Find 模块,使用生成器表达式
  4. 专家阶段:深入理解 CMake 内部机制,编写复杂项目配置

常用生成器表达式

cmake 复制代码
# 条件表达式
target_compile_definitions(mylib
    PRIVATE
        $<$<CONFIG:Debug>:DEBUG_MODE=1>
        $<$<PLATFORM_ID:Windows>:WINDOWS_PLATFORM>
)

# 安装路径相关
$<INSTALL_INTERFACE:include>      # 安装时的接口路径
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>  # 构建时的接口路径

调试 CMake

cmake 复制代码
# 打印变量值
message(STATUS "CMAKE_VERSION: ${CMAKE_VERSION}")
message(DEBUG "调试信息")

# 变量追踪
variable_watch(CMAKE_PREFIX_PATH)

# 打印所有变量
get_cmake_property(vars VARIABLES)
foreach(var ${vars})
    message("${var} = ${${var}}")
endforeach()

提示:CMake 3.0+ 版本引入了现代 CMake 概念,建议使用 CMake 3.10 或更高版本开始新项目,并遵循基于目标的编程模式。

相关推荐
charlee441 天前
CMake构建学习笔记32-CMake版本切换
cmake·版本管理·构建·update·alternatives
阳洞洞2 天前
cmake中如何从include_directories中移除某个特定的头文件
c++·cmake
Mr_WangAndy2 天前
cmake_CMake内置属性解决头文件包含/CMake定义C/C++标准/include_directories()/宏定义
cmake·宏定义·c++标准·头文件包含
番茄灭世神3 天前
使用VScode开发ARM核芯片通用配置
arm开发·vscode·mcu·cmake·clangd·llvm·ninja
charlee444 天前
CMake构建学习笔记31-构建前执行可执行程序
sqlite·cmake·构建·构建前脚本
Mr_WangAndy5 天前
cmake_file(GLOB)详解
cmake·cmake file·cmake文件操作
Tipriest_5 天前
CMake 常用预设命令说明
cmake
加成BUFF5 天前
Qt开发核心工具:CMake与qmake全面解析
开发语言·qt·cmake·qmake
青山是哪个青山6 天前
第二节:CMake 命令行工具与工程生命周期
c++·cmake