【GiraKoo】CMake 构建系统

47 阅读3分钟

CMake是辅助生成编译所需文件的工具。 基于写好的CMakeLists.txt文件,可以生成可以被Visual Studio,Ninja,Unix Makefile等等使用的编译配置。

🎯 为什么需要 CMake?

传统方式CMake 方式
Makefile(Unix)+ Visual Studio(Windows)一份配置,到处构建
手动管理依赖自动化依赖解析
平台特定代码条件编译,优雅处理

🚀 5分钟快速上手

📋 最小可运行示例

项目结构:

hello-cmake/
├── CMakeLists.txt
└── main.cpp

main.cpp

#include <iostream>
int main() {
    std::cout << "🎉 Hello, Modern CMake!" << std::endl;
    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
project(HelloCMake VERSION 1.0.0)

set(CMAKE_CXX_STANDARD 17)
add_executable(hello main.cpp)

一键构建:

# 配置项目
cmake -B build -S .
# 构建项目  
cmake --build build
# 运行程序
./build/hello

🏛️ 核心概念图解

graph TD
    A[CMakeLists.txt] --> B[CMake Generator]
    B --> C[构建系统]
    C --> D[可执行文件]
    C --> E[库文件]
    
    style A fill:#f9f,stroke:#333
    style B fill:#bbf,stroke:#333
    style C fill:#9f9,stroke:#333

🔧 现代 CMake 语法精髓

1. 目标导向编程

# ✅ 现代方式:精确控制每个目标
add_library(mathlib STATIC
    src/math/add.cpp
    src/math/multiply.cpp
)

target_include_directories(mathlib
    PUBLIC include           # 对外暴露的头文件
    PRIVATE src              # 内部实现文件
)

target_compile_features(mathlib PRIVATE cxx_std_17)

2. 依赖管理艺术

🎭 三种依赖获取方式对比

方式适用场景示例
系统包稳定库find_package(Boost REQUIRED)
源码引入最新版本FetchContent_Declare(googletest GIT_REPOSITORY ...)
子模块内部项目add_subdirectory(external/lib)

🎯 FetchContent 实战

include(FetchContent)

# 获取 Google Test(现代推荐方式)
FetchContent_Declare(
  googletest
  GIT_REPOSITORY https://github.com/google/googletest.git
  GIT_TAG        v1.14.0
)
FetchContent_MakeAvailable(googletest)

# 使用获取的库
target_link_libraries(mytests PRIVATE gtest_main)

🎪 高级特性展示

条件编译魔法

# 智能平台检测
if(WIN32)
    target_compile_definitions(app PRIVATE PLATFORM_WINDOWS)
elseif(APPLE)
    target_compile_definitions(app PRIVATE PLATFORM_APPLE)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
    target_compile_definitions(app PRIVATE PLATFORM_LINUX)
endif()

# 编译器特性检测
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    target_compile_options(app PRIVATE -Wall -Wextra -Wpedantic)
endif()

测试集成

# 启用测试框架
enable_testing()

# 添加测试目标
add_executable(test_runner tests/main.cpp tests/test_math.cpp)
target_link_libraries(test_runner PRIVATE mathlib gtest_main)

# 注册测试
add_test(NAME MathTests COMMAND test_runner)

📦 完整项目模板

🏗️ 标准项目结构

my-awesome-project/
├── CMakeLists.txt          # 根配置
├── src/
│   ├── CMakeLists.txt      # 主程序配置
│   └── main.cpp
├── include/
│   └── mylib.hpp
├── lib/
│   ├── CMakeLists.txt      # 库配置
│   └── mylib.cpp
├── tests/
│   ├── CMakeLists.txt      # 测试配置
│   └── test_main.cpp
└── external/               # 第三方依赖

📋 根 CMakeLists.txt 模板

cmake_minimum_required(VERSION 3.16)
project(MyAwesomeProject VERSION 1.0.0 LANGUAGES CXX)

# 🎯 全局设置
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# ⚙️ 构建选项
option(BUILD_TESTS "Build test programs" ON)
option(BUILD_EXAMPLES "Build example programs" OFF)

# 📦 第三方依赖
include(FetchContent)
FetchContent_Declare(
    fmt
    GIT_REPOSITORY https://github.com/fmtlib/fmt.git
    GIT_TAG 10.1.1
)
FetchContent_MakeAvailable(fmt)

# 🏗️ 构建目标
add_subdirectory(src)
add_subdirectory(lib)

if(BUILD_TESTS)
    enable_testing()
    add_subdirectory(tests)
endif()

🎨 现代 CMake 最佳实践

✅ 推荐做法

  • 目标导向:使用 target_* 而非全局命令
  • 可见性控制:合理使用 PUBLIC/PRIVATE/INTERFACE
  • 现代语法:使用 target_compile_features 而非手动设置标志
  • 依赖管理:优先使用 FetchContentfind_package

❌ 避免做法

# ❌ 过时方式
include_directories(include/)
add_definitions(-DMY_DEFINE)

# ✅ 现代方式
target_include_directories(mytarget PRIVATE include/)
target_compile_definitions(mytarget PRIVATE MY_DEFINE)

🚀 常用命令速查表

任务命令
配置项目cmake -B build -S . -DCMAKE_BUILD_TYPE=Release
构建项目cmake --build build --parallel 8
运行测试ctest --test-dir build --verbose
安装项目cmake --install build --prefix /usr/local
生成IDE文件cmake -B build -G "Xcode"

🎓 学习路径建议

  1. 入门阶段:掌握基本语法和项目配置
  2. 进阶阶段:理解目标导向编程和依赖管理
  3. 高级阶段:掌握条件编译和跨平台开发
  4. 专家阶段:自定义模块和工具链配置

🌟 一句话总结

CMake 的核心价值:让 C++ 项目像 JavaScript 项目一样易于构建和分发!


💡 小贴士:在 VS Code 中安装 "CMake Tools" 扩展,享受图形化配置体验!