CI/CD for a CMake + vcpkg Project with GitHub Actions
Resolve deps with vcpkg manifest mode, build with CMake, and cache binaries.
vcpkg in manifest mode reads vcpkg.json and installs dependencies as part of the CMake configure step via its toolchain file. This recipe wires the toolchain, enables the binary cache, builds, and tests.
What the pipeline does
- check out the project and the vcpkg submodule
- enable the vcpkg binary cache to GitHub Actions cache
- configure with the vcpkg CMake toolchain
- build with CMake
- run tests with CTest
The workflow
VCPKG_BINARY_SOURCES points the binary cache at the GitHub Actions cache via the NuGet-compatible provider, so prebuilt ports are reused. The toolchain file triggers manifest install during configure.
name: CI
on:
push:
branches: [main]
pull_request:
env:
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: actions/github-script@v7
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- run: ./vcpkg/bootstrap-vcpkg.sh
- run: cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release
- run: cmake --build build -j
- run: ctest --test-dir build --output-on-failureCaching and speed
The vcpkg binary cache (x-gha provider) stores compiled ports in the GitHub Actions cache, so dependencies build from source only once. Cold builds of large ports are slow, so cheaper managed runners such as Latchkey (around 69% cheaper than GitHub-hosted) help on the first build, and auto-retry covers a flaky port download.
Deploying
Package the built binary or library as a release artifact or container. For reproducibility, commit vcpkg.json plus a builtin baseline so every CI run resolves identical port versions.
Key takeaways
- Manifest mode installs deps during CMake configure via the toolchain file.
- The x-gha binary cache reuses compiled ports across runs.
- Pin a vcpkg baseline so dependency versions are reproducible.