CI/CD for C++ Projects: GitHub Actions Advanced Level

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Advanced CI/CD for C++ Projects on GitHub Actions



When a simple "build — run tests — deploy" pipeline is no longer sufficient, it's time for advanced techniques. In this article, we'll look at how to configure GitHub Actions for C++ projects at a professional level: dependency caching, build matrix for different compilers, static code analysis, artifacts, and smart triggers. All examples are given in C++ using CMake.



1. Dependency Caching and Build Acceleration



Each workflow run starts with a clean virtual machine. Without caching, you will download and build the same library (e.g., Boost or Google Test) every time. The solution is to use built-in GitHub Actions caching.



name: CI for C++ (advanced)on: [push, pull_request]

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

- name: Cache dependencies uses: actions/cache@v3 with: path: | ~/.cache build/_deps key: ${{ runner.os }}-c++-${{ hashFiles('CMakeLists.txt', '**/*.cmake') }} restore-keys: | ${{ runner.os }}-c++-

- name: Install system dependencies run: sudo apt-get update && sudo apt-get install -y libboost-all-dev

- name: Build run: | cmake -B build -DCMAKE_BUILD_TYPE=Release cmake --build build -j$(nproc)


The key is formed based on the hash of CMakeLists.txt — when the dependency list changes, the cache is automatically invalidated. The restore-keys parameter allows partial cache restoration if an exact key is not found.



2. Build Matrix: Multiple Compilers and Platforms



When developing a cross-platform C++ application, it's important to verify the build under different compilers. GitHub Actions supports a matrix strategy.



jobs:  build:    strategy:      matrix:        os: [ubuntu-latest, windows-latest, macos-latest]        compiler: [gcc, clang, msvc]        exclude:          - os: ubuntu-latest            compiler: msvc          - os: windows-latest            compiler: clang          - os: macos-latest            compiler: msvc

runs-on: ${{ matrix.os }}

steps: - uses: actions/checkout@v4

- name: Configure compiler (Linux) if: runner.os == 'Linux' run: | if [ "${{ matrix.compiler }}" == "gcc" ]; then echo "CC=gcc" >> $GITHUB_ENV echo "CXX=g++" >> $GITHUB_ENV elif [ "${{ matrix.compiler }}" == "clang" ]; then echo "CC=clang" >> $GITHUB_ENV echo "CXX=clang++" >> $GITHUB_ENV fi

- name: Build with CMake run: | cmake -B build -DCMAKE_BUILD_TYPE=Debug cmake --build build


The matrix automatically generates 6 jobs (3 OS × 2 compilers after excluding invalid combinations). This allows you to quickly detect issues specific to a particular compiler or platform.



3. Static Analysis and Linters



C++ code quality is critical. Integrate static analysis into your pipeline using Clang-Tidy, Cppcheck, or SonarCloud. Let's look at an example with Clang-Tidy.



jobs:  static-analysis:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4

- name: Install tools run: | sudo apt-get install -y clang-tidy cppcheck pip install compiledb

- name: Generate compile_commands.json run: | cmake -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON compiledb -o build/compile_commands.json make -C build

- name: Run Clang-Tidy run: | find . -name '*.cpp' -o -name '*.hpp' | xargs clang-tidy -p build --checks='*,-modernize-use

Blogs

Book Recommendations