Skip to content
Latchkey

CI/CD for a C++ Project with CMake and GitHub Actions

Configure, build, test -- and cache the compiler so rebuilds are not glacial.

C++ CI with CMake follows a configure-build-test rhythm: generate a build directory, compile, then run the test suite through CTest. C++ compiles are slow, so a compiler cache like ccache is what keeps CI fast on incremental changes. This recipe sets up a Ninja-driven build with caching.

What the pipeline does

  • Installs CMake, Ninja, and ccache.
  • Configures the project into an out-of-source build directory.
  • Compiles with Ninja using ccache.
  • Runs the test suite through CTest.

The workflow

Point CMake at ccache via the compiler-launcher variables and persist the ccache directory between runs.

.github/workflows/cpp-ci.yml
name: C++ CI
on: [push, pull_request]
jobs:
  build-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install build tools
        run: sudo apt-get update && sudo apt-get install -y cmake ninja-build ccache
      - name: Restore ccache
        uses: actions/cache@v4
        with:
          path: ~/.ccache
          key: ccache-\${{ github.sha }}
          restore-keys: ccache-
      - name: Configure
        run: |
          cmake -B build -G Ninja \
            -DCMAKE_BUILD_TYPE=Release \
            -DCMAKE_C_COMPILER_LAUNCHER=ccache \
            -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
      - name: Build
        run: cmake --build build
      - name: Test
        run: ctest --test-dir build --output-on-failure

Notes for this platform

Compilation dominates C++ CI time, so ccache (wired in via the COMPILER_LAUNCHER variables) is the key to fast feedback -- it turns most incremental rebuilds into cache hits. Use Ninja over Make for better parallelism. The build is Linux-native and belongs on your cheapest, fastest runner class; managed runners auto-retry transient apt-get and dependency-fetch failures so a mirror hiccup does not fail a clean build.

Key takeaways

  • Follow configure, build, then CTest for a complete C++ pipeline.
  • Wire ccache via CMAKE_*_COMPILER_LAUNCHER and cache ~/.ccache between runs.
  • Prefer Ninja over Make for better build parallelism in CI.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →