Skip to content

C++ 工程化全景

现代 C++ 工程化已经有了完整的工具链:CMake 构建、Conan/vcpkg 包管理、Clang-Tidy 静态分析、ASan 内存检测、perf 性能分析。

工具链全景

C++ 工程化工具链
├── 构建系统
│   ├── CMake(事实标准)
│   ├── Ninja(快速构建后端)
│   └── Meson(现代替代)

├── 包管理
│   ├── vcpkg(Microsoft,与 CMake 深度集成)
│   ├── Conan(功能最全,支持二进制缓存)
│   └── CPM.cmake(轻量,基于 FetchContent)

├── 编译器
│   ├── GCC(Linux 主流)
│   ├── Clang(更好的错误信息,工具链完整)
│   └── MSVC(Windows)

├── 代码质量
│   ├── clang-tidy(静态分析)
│   ├── clang-format(代码格式化)
│   ├── cppcheck(静态分析)
│   └── include-what-you-use(头文件优化)

├── 内存与安全
│   ├── AddressSanitizer(内存错误)
│   ├── ThreadSanitizer(数据竞争)
│   ├── UndefinedBehaviorSanitizer(UB)
│   └── Valgrind(内存泄漏)

└── 性能分析
    ├── perf(Linux 性能计数器)
    ├── gprof(函数级性能分析)
    ├── Valgrind/Callgrind(调用图)
    └── Google Benchmark(微基准测试)

标准项目结构

my-project/
├── CMakeLists.txt          # 根 CMake
├── CMakePresets.json       # 构建预设(C++23)
├── conanfile.txt           # Conan 依赖(或 vcpkg.json)
├── .clang-format           # 代码格式配置
├── .clang-tidy             # 静态分析配置
├── .github/
│   └── workflows/
│       └── ci.yml          # GitHub Actions CI
├── cmake/
│   ├── CompilerOptions.cmake
│   └── FindDependencies.cmake
├── include/
│   └── mylib/
│       └── api.h           # 公共头文件
├── src/
│   ├── CMakeLists.txt
│   ├── main.cpp
│   └── core/
│       ├── engine.h
│       └── engine.cpp
├── tests/
│   ├── CMakeLists.txt
│   └── test_engine.cpp
├── benchmarks/
│   └── bench_engine.cpp
└── docs/
    └── README.md

CMake 现代实践

cmake
# CMakeLists.txt
cmake_minimum_required(VERSION 3.25)
project(MyProject VERSION 1.0.0 LANGUAGES CXX)

# C++ 标准
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# 导出编译命令(供 clang-tidy 使用)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# 编译选项
add_library(project_options INTERFACE)
target_compile_options(project_options INTERFACE
    $<$<CXX_COMPILER_ID:GNU,Clang>:
        -Wall -Wextra -Wpedantic -Werror
        -Wno-unused-parameter
    >
    $<$<CXX_COMPILER_ID:MSVC>:
        /W4 /WX
    >
)

# Sanitizers(Debug 模式)
option(ENABLE_ASAN "启用 AddressSanitizer" OFF)
if(ENABLE_ASAN)
    target_compile_options(project_options INTERFACE -fsanitize=address,undefined)
    target_link_options(project_options INTERFACE -fsanitize=address,undefined)
endif()

# 主库
add_library(mylib STATIC src/engine.cpp)
target_include_directories(mylib PUBLIC include)
target_link_libraries(mylib PUBLIC project_options)

# 可执行文件
add_executable(myapp src/main.cpp)
target_link_libraries(myapp PRIVATE mylib)

# 测试
enable_testing()
add_subdirectory(tests)

CMakePresets.json

json
{
    "version": 6,
    "configurePresets": [
        {
            "name": "debug",
            "displayName": "Debug",
            "generator": "Ninja",
            "binaryDir": "${sourceDir}/build/debug",
            "cacheVariables": {
                "CMAKE_BUILD_TYPE": "Debug",
                "ENABLE_ASAN": "ON"
            }
        },
        {
            "name": "release",
            "displayName": "Release",
            "generator": "Ninja",
            "binaryDir": "${sourceDir}/build/release",
            "cacheVariables": {
                "CMAKE_BUILD_TYPE": "Release",
                "CMAKE_INTERPROCEDURAL_OPTIMIZATION": "ON"
            }
        }
    ],
    "buildPresets": [
        {"name": "debug",   "configurePreset": "debug"},
        {"name": "release", "configurePreset": "release"}
    ],
    "testPresets": [
        {"name": "debug", "configurePreset": "debug", "output": {"outputOnFailure": true}}
    ]
}
bash
# 使用预设
cmake --preset debug
cmake --build --preset debug
ctest --preset debug

代码格式化(.clang-format)

yaml
# .clang-format
BasedOnStyle: Google
IndentWidth: 4
ColumnLimit: 100
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: Never
BreakBeforeBraces: Attach
PointerAlignment: Left
IncludeBlocks: Regroup
bash
# 格式化所有文件
find src include -name "*.cpp" -o -name "*.h" | xargs clang-format -i

# 检查格式(CI 中使用)
clang-format --dry-run --Werror src/*.cpp

静态分析(.clang-tidy)

yaml
# .clang-tidy
Checks: >
    clang-diagnostic-*,
    clang-analyzer-*,
    cppcoreguidelines-*,
    modernize-*,
    performance-*,
    readability-*,
    -modernize-use-trailing-return-type,
    -readability-magic-numbers

WarningsAsErrors: '*'
HeaderFilterRegex: '.*'
bash
# 运行 clang-tidy
clang-tidy src/*.cpp -- -std=c++20 -Iinclude

# 或者用 run-clang-tidy(并行)
run-clang-tidy -p build/debug

GitHub Actions CI

yaml
# .github/workflows/ci.yml
name: CI

on: [push, pull_request]

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: 安装依赖
        run: |
          sudo apt-get update
          sudo apt-get install -y cmake ninja-build clang clang-tidy

      - name: 配置(Debug + ASan)
        run: cmake --preset debug

      - name: 构建
        run: cmake --build --preset debug

      - name: 运行测试
        run: ctest --preset debug

      - name: 静态分析
        run: run-clang-tidy -p build/debug

  release-build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: cmake --preset release
      - run: cmake --build --preset release

关键认知

现代 C++ 工程化的核心是:CMake + vcpkg/Conan + Sanitizers + CI。Debug 构建开启 ASan/UBSan,Release 构建开启 LTO(链接时优化)。compile_commands.json 是所有工具(clang-tidy、clangd)的基础,必须生成。

系统学习 C++ 生态,深入底层架构