第六章:高级场景
本章介绍 vcpkg 的高级功能和使用场景,包括二进制缓存、自定义三元组、跨平台开发和性能优化。掌握这些技巧可以让你更高效地使用 vcpkg。
6.1 vcpkg 二进制缓存
配置缓存服务器
二进制缓存可以大幅减少重复构建的时间,特别适合 CI/CD 环境。
使用 Azure Blob Storage
配置文件:
bash
# 设置环境变量
export VCPKG_BINARY_SOURCES="clear;default,readwrite"
export VCPKG_DEFAULT_BINARY_CACHE=clear;default,readwrite
# 使用 Azure Blob Storage
export VCPKG_BINARY_SOURCES="clear;default,readwrite,https://myaccount.blob.core.windows.net/vcpkg"完整配置示例:
bash
#!/bin/bash
# setup-binary-cache.sh
# Azure Blob Storage
AZURE_CONNECTION_STRING="DefaultEndpointsProtocol=https;AccountName=myaccount;..."
# 配置二进制缓存
export VCPKG_BINARY_SOURCES="clear;default,readwrite"
export VCPKG_DOWNLOADS=/mnt/cache/vcpkg-downloads
# 如果有 Azure 存储,配置它
if [ -n "$AZURE_CONNECTION_STRING" ]; then
export VCPKG_BINARY_SOURCES="clear;default,readwrite,azure,$AZURE_CONNECTION_STRING"
fi
echo "Binary cache configured"
echo "VCPKG_BINARY_SOURCES: $VCPKG_BINARY_SOURCES"使用本地文件系统缓存
bash
# 设置本地缓存目录
export VCPKG_BINARY_SOURCES="clear;files,/mnt/vcpkg-cache,readwrite"
# 或使用相对路径
export VCPKG_BINARY_SOURCES="clear;files,./vcpkg-cache,readwrite"目录结构:
vcpkg-cache/
├── x64-linux/
│ ├── fmt/
│ ├── spdlog/
│ └── ...
├── x64-windows/
│ ├── fmt/
│ └── ...
└── arm64-osx/
└── ...使用 NuGet 源
bash
# 配置 NuGet 源
nuget sources add -name vcpkg-cache -source https://nuget.pkg.github.com/my-org/index.json
# 设置 vcpkg 使用 NuGet
export VCPKG_BINARY_SOURCES="clear;nuget,https://nuget.pkg.github.com/my-org/index.json,readwrite"CI/CD 环境中的缓存优化
GitHub Actions 示例
yaml
name: Build with Binary Cache
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Setup vcpkg
run: |
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
- name: Setup binary cache
env:
VCPKG_BINARY_SOURCES: "clear;files,$HOME/.vcpkg-cache,readwrite"
run: |
echo "VCPKG_BINARY_SOURCES=$VCPKG_BINARY_SOURCES" >> $GITHUB_ENV
- name: Restore cache
uses: actions/cache@v3
with:
path: ~/.vcpkg-cache
key: vcpkg-${{ runner.os }}-${{ hashFiles('vcpkg.json') }}
- name: Configure and build
env:
VCPKG_BINARY_SOURCES: ${{ env.VCPKG_BINARY_SOURCES }}
run: |
cmake -B build -S . \
-DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake
cmake --build build --config ReleaseGitLab CI 示例
yaml
stages:
- build
variables:
VCPKG_BINARY_SOURCES: "clear;files,/cache/vcpkg,readwrite"
cache:
paths:
- /cache/vcpkg/
build:
stage: build
image: ubuntu:22.04
before_script:
- apt-get update && apt-get install -y cmake git g++
- git clone https://github.com/Microsoft/vcpkg.git
- cd vcpkg && ./bootstrap-vcpkg.sh
script:
- cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=vcpkg/scripts/buildsystems/vcpkg.cmake
- cmake --build build --config ReleaseJenkins Pipeline 示例
groovy
pipeline {
agent any
environment {
VCPKG_BINARY_SOURCES = "clear;files,/mnt/vcpkg-cache,readwrite"
}
stages {
stage('Setup') {
steps {
sh '''
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg && ./bootstrap-vcpkg.sh
'''
}
}
stage('Build') {
steps {
sh '''
cmake -B build -S . \
-DCMAKE_TOOLCHAIN_FILE=${WORKSPACE}/vcpkg/scripts/buildsystems/vcpkg.cmake
cmake --build build --config Release
'''
}
}
}
post {
always {
archiveArtifacts artifacts: 'build/bin/*', allowEmptyArchive: true
}
}
}6.2 自定义三元组
何时需要自定义三元组
需要自定义三元组的场景:
- 使用非标准编译器
- 需要特定的编译选项
- 使用交叉编译
- 平台特定的配置
三元组文件编写
创建自定义三元组文件
bash
# 创建三元组目录
mkdir -p /path/to/vcpkg/triplets/community
# 创建自定义三元组文件
vim /path/to/vcpkg/triplets/community/x64-linux-gcc11.cmake三元组文件结构
cmake
# x64-linux-gcc11.cmake
set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE static)
set(VCPKG_CMAKE_SYSTEM_NAME Linux)
set(VCPKG_CMAKE_SYSTEM_VERSION 1)
# 编译器配置
set(VCPKG_CMAKE_C_COMPILER gcc-11)
set(VCPKG_CMAKE_CXX_COMPILER g++-11)
# 编译选项
set(VCPKG_CMAKE_FLAGS "-march=native -mtune=native")
set(VCPKG_CXX_FLAGS "-fvisibility=hidden")
# 其他选项
set(VCPKG_BUILD_TYPE release)完整示例:交叉编译三元组
cmake
# arm-linux-gnueabihf.cmake
set(VCPKG_TARGET_ARCHITECTURE arm)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE static)
set(VCPKG_CMAKE_SYSTEM_NAME Linux)
set(VCPKG_CMAKE_SYSTEM_VERSION 1)
# 交叉编译工具链
set(VCPKG_CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(VCPKG_CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
set(VCPKG_CMAKE_AR arm-linux-gnueabihf-ar)
set(VCPKG_CMAKE_RANLIB arm-linux-gnueabihf-ranlib)
set(VCPKG_CMAKE_STRIP arm-linux-gnueabihf-strip)
# 根文件系统
set(VCPKG_CMAKE_SYSROOT /opt/arm-sysroot)
# 链接选项
set(VCPKG_CMAKE_LINKER_FLAGS "--sysroot=/opt/arm-sysroot")
# 其他配置
set(VCPKG_BUILD_TYPE release)
set(VCPKG_FIND_LIBRARY_SUFFIXES .a .so)使用自定义三元组
bash
# 方法 1:命令行指定
vcpkg install fmt --triplet=x64-linux-gcc11
# 方法 2:环境变量
export VCPKG_DEFAULT_TRIPLET=x64-linux-gcc11
vcpkg install fmt
# 方法 3:CMake 配置
cmake -B build -S . \
-DCMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake \
-DVCPKG_TARGET_TRIPLET=x64-linux-gcc11常见自定义场景
场景 1:使用 Clang 编译器
cmake
# x64-linux-clang.cmake
set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE static)
set(VCPKG_CMAKE_SYSTEM_NAME Linux)
set(VCPKG_CMAKE_SYSTEM_VERSION 1)
set(VCPKG_CMAKE_C_COMPILER clang)
set(VCPKG_CMAKE_CXX_COMPILER clang++)
set(VCPKG_CMAKE_FLAGS "-stdlib=libc++")
set(VCPKG_CXX_FLAGS "-stdlib=libc++")场景 2:启用 LTO 优化
cmake
# x64-linux-lto.cmake
set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE static)
set(VCPKG_CMAKE_SYSTEM_NAME Linux)
set(VCPKG_CMAKE_SYSTEM_VERSION 1)
set(VCPKG_CMAKE_C_COMPILER gcc)
set(VCPKG_CMAKE_CXX_COMPILER g++)
set(VCPKG_CMAKE_FLAGS "-flto -fuse-linker-plugin")
set(VCPKG_CXX_FLAGS "-flto -fuse-linker-plugin")场景 3:调试版本
cmake
# x64-linux-debug.cmake
set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE static)
set(VCPKG_CMAKE_SYSTEM_NAME Linux)
set(VCPKG_CMAKE_SYSTEM_VERSION 1)
set(VCPKG_BUILD_TYPE debug)
set(VCPKG_CMAKE_FLAGS "-g -O0")
set(VCPKG_CXX_FLAGS "-g -O0")
set(VCPKG_CMAKE_DEBUG_POSTFIX d)6.3 跨平台开发
多平台依赖管理
方法 1:使用 vcpkg.json 的平台约束
json
{
"name": "cross-platform-project",
"version": "1.0.0",
"dependencies": [
{
"name": "fmt",
"platform": "!windows"
},
{
"name": "spdlog",
"platform": "windows|linux"
},
{
"name": "openssl",
"platform": "!android"
}
]
}方法 2:使用 CMake 条件依赖
cmake
# CMakeLists.txt
if(WIN32)
find_package(fmt CONFIG REQUIRED)
elseif(APPLE)
find_package(fmt CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)
elseif(UNIX)
find_package(fmt CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)
endif()条件依赖配置
vcpkg.json 中的条件依赖
json
{
"name": "my-project",
"version": "1.0.0",
"dependencies": [
{
"name": "fmt",
"platform": "!windows"
}
],
"overrides": [
{
"name": "spdlog",
"version": "1.12.0",
"platform": "linux"
}
]
}使用 $<platform> 表达式
json
{
"name": "my-project",
"version": "1.0.0",
"dependencies": [
{
"name": "fmt",
"platform": "!$<platform:windows>"
},
{
"name": "openssl",
"platform": "$<platform:windows>|$<platform:linux>"
}
]
}跨平台构建脚本
完整的跨平台构建脚本
bash
#!/bin/bash
# build-all-platforms.sh
set -e
# 平台配置
PLATFORMS=(
"x64-linux:ubuntu-latest"
"x64-windows:windows-latest"
"arm64-osx:macos-latest"
)
# 构建函数
build_platform() {
local triplet=$1
local runner=$2
echo "Building for $triplet ($runner)"
# 配置 CMake
cmake -B build-${triplet} -S . \
-DCMAKE_TOOLCHAIN_FILE=${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake \
-DVCPKG_TARGET_TRIPLET=${triplet}
# 构建
cmake --build build-${triplet} --config Release
# 运行测试
ctest --test-dir build-${triplet} --config Release
}
# 遍历所有平台
for platform in "${PLATFORMS[@]}"; do
IFS=':' read -r triplet runner <<< "$platform"
build_platform "$triplet" "$runner"
done
echo "All platforms built successfully"6.4 性能优化
并行安装
方法 1:使用 vcpkg 的并行功能
bash
# 启用并行安装(默认已启用)
vcpkg install fmt spdlog nlohmann-json
# 设置并行度
export VCPKG_MAX_CONCURRENCY=8
vcpkg install fmt spdlog nlohmann-json方法 2:使用 GNU Parallel
bash
# 安装 GNU Parallel
sudo apt-get install parallel # Ubuntu
brew install parallel # macOS
# 并行安装多个包
cat packages.txt | parallel -j 4 vcpkg install {}packages.txt:
fmt
spdlog
nlohmann-json
openssl
boost减少构建时间
方法 1:使用二进制缓存
bash
# 配置二进制缓存
export VCPKG_BINARY_SOURCES="clear;files,./vcpkg-cache,readwrite"
# 安装包(会优先使用缓存)
vcpkg install fmt方法 2:使用编译缓存(ccache)
bash
# 安装 ccache
sudo apt-get install ccache # Ubuntu
brew install ccache # macOS
# 配置环境变量
export CC="ccache gcc"
export CXX="ccache g++"
export CCACHE_DIR=/mnt/ccache
# 安装包
vcpkg install openssl方法 3:跳过不必要的构建
bash
# 只下载不安装
vcpkg download fmt
# 只配置不构建
vcpkg install fmt --overlay-ports=/path/to/overlay --no-binarycaching
# 使用预编译的二进制文件
vcpkg install fmt --binarysource=default,readwrite优化网络下载
方法 1:使用代理
bash
# 设置 HTTP 代理
export http_proxy=http://proxy.example.com:8080
export https_proxy=http://proxy.example.com:8080
# 设置 Git 代理
git config --global http.proxy http://proxy.example.com:8080
git config --global https.proxy http://proxy.example.com:8080
# 安装包
vcpkg install openssl方法 2:使用镜像
bash
# 使用 GitHub 镜像
git clone https://github.com.cnpmjs.org/microsoft/vcpkg.git
# 或使用代理脚本
cat > vcpkg-proxy.sh << 'EOF'
#!/bin/bash
# 将 GitHub URL 替换为镜像 URL
URL=$(echo $1 | sed 's|https://github.com/|https://github.com.cnpmjs.org/|')
curl -L "$URL" -o "$2"
EOF
chmod +x vcpkg-proxy.sh
export VCPKG_DOWNLOADS=/path/to/vcpkg-proxy.sh方法 3:预下载依赖
bash
#!/bin/bash
# pre-download.sh
# 下载所有依赖
vcpkg download --all
# 或指定包
vcpkg download fmt spdlog nlohmann-json
# 验证下载
ls -lh /path/to/vcpkg/downloads/6.5 实战案例
案例:大型项目的跨平台构建
场景: 一个大型 C++ 项目需要在 Windows、Linux 和 macOS 上构建,使用 vcpkg 管理依赖。
项目结构:
my-project/
├── CMakeLists.txt
├── vcpkg.json
├── scripts/
│ ├── build-all.sh
│ └── setup-env.sh
└── src/vcpkg.json:
json
{
"name": "my-project",
"version": "2.0.0",
"description": "A cross-platform C++ application",
"dependencies": [
"fmt",
"spdlog",
"nlohmann-json",
{
"name": "openssl",
"platform": "!windows"
}
]
}scripts/setup-env.sh:
bash
#!/bin/bash
# 设置环境变量
# 检测平台
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
export TRIPLET="x64-linux"
elif [[ "$OSTYPE" == "darwin"* ]]; then
export TRIPLET="arm64-osx"
elif [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then
export TRIPLET="x64-windows"
fi
# 设置 vcpkg 路径
export VCPKG_ROOT=$(cd "$(dirname "$0")/../vcpkg" && pwd)
export PATH="$VCPKG_ROOT:$PATH"
# 设置二进制缓存
export VCPKG_BINARY_SOURCES="clear;files,$HOME/.vcpkg-cache,readwrite"
# 设置并行度
export VCPKG_MAX_CONCURRENCY=4
echo "Environment setup for $TRIPLET"scripts/build-all.sh:
bash
#!/bin/bash
set -e
# 设置环境
source scripts/setup-env.sh
# 平台列表
PLATFORMS=(
"x64-linux"
"x64-windows"
"arm64-osx"
)
# 构建函数
build() {
local triplet=$1
echo "Building for $triplet..."
# 清理旧的构建
rm -rf build-$triplet
# 配置
cmake -B build-$triplet -S . \
-DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake \
-DVCPKG_TARGET_TRIPLET=$triplet
# 构建
cmake --build build-$triplet --config Release -j4
# 测试
ctest --test-dir build-$triplet --config Release
# 打包
cpack -C Release -B build-$triplet/package
}
# 遍历平台
for platform in "${PLATFORMS[@]}"; do
build "$platform"
done
echo "All builds completed successfully"构建脚本:
bash
# 设置环境
source scripts/setup-env.sh
# 构建当前平台
cmake -B build -S . \
-DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake \
-DVCPKG_TARGET_TRIPLET=$TRIPLET
cmake --build build --config Release
# 运行
./build/my-app小结
本章介绍了 vcpkg 的高级功能和使用场景:
- 二进制缓存的配置(Azure、本地文件、NuGet)
- CI/CD 环境中的缓存优化
- 自定义三元组的创建和使用
- 跨平台开发技巧
- 性能优化方法(并行安装、编译缓存、网络优化)
- 大型项目的跨平台构建实战案例
掌握这些高级技巧可以让你更高效地使用 vcpkg,特别是在大型项目和 CI/CD 环境中。下一章将介绍故障排查,帮助你解决使用过程中遇到的各种问题。