目录

  1. vcpkg 使用
  2. Conanfile
  3. CMake Presets
  4. 交叉编译
  5. CI/CD 集成

1. vcpkg 使用

vcpkg 是微软开源的 C++ 包管理工具,目前已成为 C++ 生态中最流行的依赖管理方案之一。它与 CMake 的深度集成使得三方库管理变得简单可靠。

1.1 安装与基础使用

# 1. 克隆 vcpkg
git clone https://github.com/microsoft/vcpkg.git
cd vcpkg

# 2. 安装(Windows)
.\bootstrap-vcpkg.bat

# 2. 安装(Linux/macOS)
./bootstrap-vcpkg.sh

# 3. 安装依赖
# 单库安装
vcpkg install spdlog:x64-linux
# 多库同时安装
vcpkg install boost filesystem curl:x64-linux

# 4. 使用(CMake 集成)
# 在 CMakeLists.txt 中
find_package(fmt CONFIG REQUIRED)
target_link_libraries(my_app PRIVATE fmt::fmt)

1.2 triplet 配置

vcpkg 使用 triplet 来定义目标平台和构建类型:

# 常用 triplets
# x86-windows         - x86 Windows
# x64-windows         - x64 Windows
# x64-windows-md      - x64 Windows with MD runtime
# x64-linux           - x64 Linux
# x64-osx             - x64 macOS
# arm64-uwp           - ARM64 UWP
# x64-linux-static    - x64 Linux 静态链接

# 自定义 triplet 示例:
# vcpkg/triplets/x64-myconfig.cmake
set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_CRT_LINKAGE static)
set(VCPKG_LIBRARY_LINKAGE static)
set(VCPKG_BUILD_TYPE release)

1.3 manifest 模式(推荐)

vcpkg 2021.04 版本引入了 manifest 模式,允许在项目中声明依赖:

# vcpkg.json - 项目根目录
{
    "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json",
    "name": "my-awesome-project",
    "version": "1.0.0",
    "dependencies": [
        "fmt",
        "spdlog",
        "boost-filesystem",
        "boost-asio",
        "nlohmann-json",
        {
            "name": "opencv",
            "features": ["dnn", "png", "jpeg"]
        }
    ],
    "features": {
        "gpu": {
            "description": "Enable GPU support",
            "dependencies": ["cuda", "cudnn"]
        }
    },
    "overrides": [
        {
            "name": "openssl",
            "version": "1.1.1t"
        }
    ]
}

💡 manifest 模式的优势

  • 依赖声明与项目源码在一起,版本可追溯
  • 支持 feature 条件依赖
  • 支持版本覆盖锁定
  • 支持锁文件(vcpkg-lock.json)

2. Conanfile

2.1 Conan 基础

Conan 是另一个流行的 C++ 包管理器,与 vcpkg 相比更专注于企业场景:

# conanfile.txt 示例
[requires]
    fmt/9.1.0
    spdlog/1.12.0
    boost/1.84.0

[generators]
    cmake_find_package
    CMakeToolchain

[options]
    fmt:shared = False
    boost/*:shared = False

[imports]
    bin, *.dll -> ./bin
    lib, *.lib -> ./lib

2.2 Conan vs vcpkg 对比

vcpkg 优势

  • 与 CMake 原生集成
  • 无需额外运行时
  • Windows 一致体验
  • 活跃的社区

Conan 优势

  • 更成熟的企业特性
  • ConanCenter 质量保证
  • 更好的版本语义支持
  • 完整的 CI/CD 集成

2.3 版本锁定

# vcpkg lock 文件(vckg.lock.json)
# 自动生成,记录精确版本
{
    "version": 1,
    "requirements": [
        {
            "name": "fmt",
            "version": "10.2.1"
        },
        {
            "name": "spdlog",
            "version": "1.12.0"
        }
    ],
    "patches": []
}

# 强制使用锁文件版本
vcpkg install --x-experimental-lockfile
# 或者手动编辑 vcpkg.json overrides

3. CMake Presets

3.1 CMakePresets.json 基础

CMake 3.21+ 引入了 CMakePresets.json,使得构建配置可共享:

// CMakePresets.json
{
    "version": 4,
    "cmakeMinimumRequired": {
        "major": 3,
        "minor": 21
    },
    "presets": [
        {
            "name": "release-linux",
            "inherits": ["base"],
            "binaryDir": "${sourceDir}/build/release-linux",
            "cacheVariables": {
                "CMAKE_BUILD_TYPE": "Release",
                "ENABLE_TESTS": "ON",
                "VCPKG_MANIFEST_MODE": "ON",
                "VCPKG_TARGET_TRIPLET": "x64-linux"
            }
        },
        {
            "name": "debug-windows",
            "inherits": ["base"],
            "binaryDir": "${sourceDir}/build/debug-windows",
            "cacheVariables": {
                "CMAKE_BUILD_TYPE": "Debug",
                "VCPKG_TARGET_TRIPLET": "x64-windows"
            }
        }
    ]
}

3.2 CMakeUserPresets.json

用户可以通过 CMakeUserPresets.json 覆盖或添加个人配置:

// CMakeUserPresets.json(不提交到版本控制)
{
    "version": 4,
    "include": "../CMakePresets.json",
    "presets": [
        {
            "name": "local-dev",
            "inherits": ["release-linux"],
            "cacheVariables": {
                "CMAKE_PREFIX_PATH": "/home/dev/custom-libs"
            }
        }
    ]
}

3.3 与 vcpkg 集成

// 在 CMakeLists.txt 中启用 vcpkg
cmake_minimum_required(VERSION 3.21)
project(my_app)

// 方式1:使用 vcpkg toolchain(推荐)
set(VCPKG_MANIFEST_MODE ON)
set(VCPKG_TARGET_TRIPLET x64-linux)
include(${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake)

// 方式2:使用 vcpkg CMake Toolchain(更灵活)
# CMakePresets.json 中
{
    "cacheVariables": {
        "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
    }
}

4. 交叉编译

4.1 ARM 交叉编译

# vcpkg triplet for ARM64 Linux
# vcpkg/triplets/arm64-linux.cmake
set(VCPKG_TARGET_ARCHITECTURE arm64)
set(VCPKG_CRT_LINKAGE static)
set(VCPKG_LIBRARY_LINKAGE static)
set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/toolchain-arm64.cmake)

# toolchain-arm64.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm64)
set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)

# 使用
vcpkg install --triplet arm64-linux
cmake --preset=release-arm64

4.2 Windows 到 Linux 交叉编译

# Windows 上交叉编译 Linux
# 1. 安装 MinGW-w64 或 LLVM
# 2. 使用对应 triplet
vcpkg install --triplet=x64-linux

# CMakePresets.json
{
    "name": "linux-from-windows",
    "cacheVariables": {
        "CMAKE_SYSTEM_NAME": "Linux",
        "CMAKE_C_COMPILER": "x86_64-linux-gnu-gcc",
        "CMAKE_CXX_COMPILER": "x86_64-linux-gnu-g++"
    }
}

4.3 平台特定依赖

// 根据平台选择依赖
if (WIN32)
    list(APPEND DEPS "windows-sdk")
    find_package(windows-sdk CONFIG REQUIRED)
elseif (UNIX AND NOT APPLE)
    list(APPEND DEPS "linux-headers")
elseif (APPLE)
    list(APPEND DEPS "apple-framework")
endif()

5. CI/CD 集成

5.1 GitHub Actions 流水线

# .github/workflows/cmake.yml
name: CMake CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    strategy:
      matrix:
        config:
          - {name: "Linux Release", os: ubuntu-latest, triplet: x64-linux, buildtype: Release}
          - {name: "Windows Debug", os: windows-latest, triplet: x64-windows, buildtype: Debug}
          - {name: "macOS", os: macos-latest, triplet: arm64-osx, buildtype: Release}
    
    runs-on: ${{ matrix.config.os }}
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup vcpkg
        uses: lukka/run-vcpkg@v11
        with:
          vcpkggitrepository: https://github.com/microsoft/vcpkg
          vcpkgtriplet: ${{ matrix.config.triplet }}
          vcpkginstalledpath: ${{ github.workspace }}/vcpkg_installed
      
      - name: Configure CMake
        run: |
          cmake -B build -S . \
            -DCMAKE_BUILD_TYPE=${{ matrix.config.buildtype }} \
            -DVCPKG_MANIFEST_MODE=ON \
            -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake
      
      - name: Build
        run: cmake --build build --parallel
      
      - name: Test
        run: ctest --output-on-failure -C ${{ matrix.config.buildtype }}

5.2 缓存优化

# GitHub Actions 缓存 vcpkg 编译结果
      - name: Cache vcpkg
        uses: actions/cache@v3
        with:
          path: |
            ${{ github.workspace }}/vcpkg_installed
            ~/.cache/vcpkg
          key: vcpkg-${{ matrix.config.triplet }}-${{ hashFiles('vcpkg.json') }}
          restore-keys: |
            vcpkg-${{ matrix.config.triplet }}-

5.3 完整流水线检查表

# CI/CD 流水线检查表

## 构建矩阵
□ Linux (GCC + Clang)
□ Windows (MSVC)
□ macOS (Apple Clang)
□ Debug + Release 组合
□ 静态 + 动态链接(如需要)

## 依赖管理
□ vcpkg.json 提交到仓库
□ vcpkg-lock.json 提交(版本锁定)
□ overrides 配置审核
□ triplet 自定义配置

## 性能优化
□ ccache 启用
□ Unity Build(如支持)
□ 并行编译优化
□ 构建缓存(ccache 或 sccache)

## 质量门禁
□ 编译警告视为错误(-Werror)
□ Clang-Tidy 静态分析
□ CMake Format 检查
□ 依赖漏洞扫描

✅ 快速决策

  • ✓ 新项目使用 vcpkg + CMake Presets
  • ✓ 跨平台项目使用 manifest 模式
  • ✓ 企业项目考虑 Conan(更成熟的生态)
  • ✓ 所有项目都应锁定依赖版本
  • ✓ CI/CD 必须包含所有目标平台
  • ✓ 使用 ccache/sccache 加速编译

总结

C++ 包管理已经进入成熟期。vcpkg + CMake Presets 的组合提供了简洁、跨平台的依赖管理方案,Conan 则更适合需要企业级支持的项目。无论选择哪种方案,关键在于:依赖版本锁定、跨平台验证、以及与 CI/CD 的深度集成。

在实践中,建议从 vcpkg 开始,它与 CMake 的原生集成可以快速启动项目。对于需要更严格依赖控制的企业场景,可以逐步引入 Conan 作为补充。