Skip to content

Initial commit

Initial commit #4

Workflow file for this run

# Eggs.Stacktrace
#
# Copyright (c) 2026 Agustin Berge
#
# Distributed under the Boost Software License, Version 1.0.
# See accompanying file LICENSE.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt
name: test
on:
push:
branches: [ main, feature/** ]
pull_request:
types: [opened, synchronize, reopened]
jobs:
build:
name: ${{ matrix.os }} / ${{ matrix.compiler }}
runs-on: ${{ matrix.os }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include:
# -- Linux / GCC -----------------------------------------------------
- { os: ubuntu-22.04, compiler: gcc-11, cxxstds: "11 14 17 20 23", preset: dev-gcc, cc: gcc-11, cxx: g++-11, packages: "gcc-11 g++-11" }
- { os: ubuntu-22.04, compiler: gcc-12, cxxstds: "11 14 17 20 23", preset: dev-gcc, cc: gcc-12, cxx: g++-12, packages: "gcc-12 g++-12" }
- { os: ubuntu-24.04, compiler: gcc-13, cxxstds: "11 14 17 20 23", preset: dev-gcc, cc: gcc-13, cxx: g++-13, packages: "gcc-13 g++-13" }
- { os: ubuntu-24.04, compiler: gcc-14, cxxstds: "11 14 17 20 23 26", preset: dev-gcc, cc: gcc-14, cxx: g++-14, packages: "gcc-14 g++-14" }
- { os: ubuntu-24.04, compiler: gcc-15, cxxstds: "11 14 17 20 23 26", preset: dev-gcc, cc: gcc-15, cxx: g++-15, packages: "gcc-15 g++-15", ppa: ubuntu-toolchain-r }
- { os: ubuntu-24.04, compiler: gcc-16, cxxstds: "11 14 17 20 23 26", preset: dev-gcc, cc: gcc-16, cxx: g++-16, packages: "gcc-16 g++-16", ppa: ubuntu-toolchain-r }
# -- Linux / Clang ----------------------------------------------------
- { os: ubuntu-24.04, compiler: clang-17, cxxstds: "11 14 17 20 23", preset: dev-clang, cc: clang-17, cxx: clang++-17, packages: "clang-17" }
- { os: ubuntu-24.04, compiler: clang-18, cxxstds: "11 14 17 20 23", preset: dev-clang, cc: clang-18, cxx: clang++-18, packages: "clang-18" }
- { os: ubuntu-24.04, compiler: clang-19, cxxstds: "11 14 17 20 23 26", preset: dev-clang, cc: clang-19, cxx: clang++-19, packages: "clang-19" }
- { os: ubuntu-24.04, compiler: clang-20, cxxstds: "11 14 17 20 23 26", preset: dev-clang, cc: clang-20, cxx: clang++-20, packages: "clang-20", llvm_ver: "20" }
- { os: ubuntu-24.04, compiler: clang-22, cxxstds: "11 14 17 20 23 26", preset: dev-clang, cc: clang-22, cxx: clang++-22, packages: "clang-22", llvm_ver: "22" }
# -- Linux / Clang + libc++ -------------------------------------------
- { os: ubuntu-24.04, compiler: clang-19-libcxx, cxxstds: "11 14 17 20 23 26", preset: dev-clang-libcxx, cc: clang-19, cxx: clang++-19, packages: "clang-19 libc++-19-dev libc++abi-19-dev" }
- { os: ubuntu-24.04, compiler: clang-22-libcxx, cxxstds: "11 14 17 20 23 26", preset: dev-clang-libcxx, cc: clang-22, cxx: clang++-22, packages: "clang-22 libc++-22-dev libc++abi-22-dev", llvm_ver: "22" }
# -- Windows / MSVC ---------------------------------------------------
# MSVC (cl.exe) has no C++26 flag in any CMake version (see cmake/Modules/Compiler/MSVC-CXX.cmake);
- { os: windows-2022, compiler: msvc-2022, cxxstds: "14 17 20 23", preset: dev-msvc }
- { os: windows-2025-vs2026, compiler: msvc-2026, cxxstds: "14 17 20 23", preset: dev-msvc }
# -- Windows / Clang-CL ------------------------------------------------
- { os: windows-2025-vs2026, compiler: clang-cl-20, cxxstds: "14 17 20 23 26", preset: dev-clang-cl }
# -- macOS / Apple Clang ----------------------------------------------
# macos-13 = Xcode 15 / Apple Clang 15 (Intel x86_64)
# macos-15 = Xcode 16 / Apple Clang 16 (Apple Silicon arm64)
- { os: macos-13, compiler: apple-clang-15, cxxstds: "11 14 17 20 23", preset: dev-clang }
- { os: macos-15, compiler: apple-clang-16, cxxstds: "11 14 17 20 23 26", preset: dev-clang }
steps:
- uses: actions/checkout@v5
- name: Install CMake
uses: lukka/get-cmake@latest
with:
cmakeVersion: "4.4.0"
# -- Windows: activate MSVC Developer Command Prompt ---------------------
- name: Set up MSVC environment
if: runner.os == 'Windows'
shell: pwsh
run: |
$vsPath = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" `
-latest -property installationPath
$vcvars = "$vsPath\VC\Auxiliary\Build\vcvars64.bat"
cmd /c "`"$vcvars`" && set" | ForEach-Object {
if ($_ -match '^([^=]+)=(.*)$') {
"$($Matches[1])=$($Matches[2])" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
}
}
# -- Linux: add optional extra APT sources before install -------------
- name: Add ubuntu-toolchain-r PPA
if: matrix.ppa == 'ubuntu-toolchain-r'
run: |
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update
- name: Add LLVM APT source
if: runner.os == 'Linux' && matrix.llvm_ver != ''
run: |
CODENAME=$(lsb_release -cs)
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key \
| sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc >/dev/null
echo "deb http://apt.llvm.org/${CODENAME}/ llvm-toolchain-${CODENAME}-${{ matrix.llvm_ver }} main" \
| sudo tee /etc/apt/sources.list.d/llvm.list
sudo apt-get update
# -- Linux: cache and install APT packages ----------------------------
- name: Set up APT package cache
if: runner.os == 'Linux'
run: |
mkdir -p ~/.cache/apt/archives/partial
echo "Dir::Cache::archives \"$HOME/.cache/apt/archives\";" \
| sudo tee /etc/apt/apt.conf.d/99user-cache
- name: Cache APT packages
if: runner.os == 'Linux'
continue-on-error: true
uses: actions/cache@v5
with:
path: ~/.cache/apt/archives
key: apt-${{ matrix.os }}-${{ matrix.compiler }}-${{ hashFiles('.github/workflows/test.yml') }}
restore-keys: apt-${{ matrix.os }}-${{ matrix.compiler }}-
- name: Install Linux tools and compiler
if: runner.os == 'Linux'
run: sudo apt-get install -y --no-install-recommends ninja-build ${{ matrix.packages }}
# gcc-N/clang-N packages don't register unversioned alternatives, so the
# presets' unversioned CMAKE_C(XX)_COMPILER wouldn't otherwise pick up
# anything but the OS default.
- name: Point default compiler at matrix version
if: runner.os == 'Linux'
run: |
cc_link="${{ matrix.cc }}"; cc_link="${cc_link%-*}"
cxx_link="${{ matrix.cxx }}"; cxx_link="${cxx_link%-*}"
sudo update-alternatives --install "/usr/bin/${cc_link}" "${cc_link}" "/usr/bin/${{ matrix.cc }}" 100
sudo update-alternatives --install "/usr/bin/${cxx_link}" "${cxx_link}" "/usr/bin/${{ matrix.cxx }}" 100
- name: Fix APT cache permissions
if: always() && runner.os == 'Linux'
run: sudo rm -rf ~/.cache/apt/archives/lock ~/.cache/apt/archives/partial
- name: Install Ninja (macOS)
if: runner.os == 'macOS'
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install ninja
# -- CMake: configure, build, test ------------------------------------
- name: Build and test
id: build_and_test
shell: bash
run: |
overall_failed=0
for std in ${{ matrix.cxxstds }}; do
std_failed=0
echo "::group::Configure C++${std}"
cmake --preset ${{ matrix.preset }} -B build/${{ matrix.preset }}-cxx${std} \
-DBUILD_EXAMPLES=ON -DBUILD_TESTING=ON \
-DCMAKE_CXX_STANDARD=${std} || std_failed=1
echo "::endgroup::"
if [ $std_failed -eq 0 ]; then
echo "::group::Build Debug C++${std}"
cmake --build build/${{ matrix.preset }}-cxx${std} --config Debug -- -k 0 || std_failed=1
echo "::endgroup::"
fi
if [ $std_failed -eq 0 ]; then
echo "::group::Test Debug C++${std}"
ctest --test-dir build/${{ matrix.preset }}-cxx${std} --build-config Debug \
--label-regex header --output-on-failure --no-compress-output \
--output-junit test-results-${{ matrix.compiler }}-cxx${std}-debug-header.xml || std_failed=1
ctest --test-dir build/${{ matrix.preset }}-cxx${std} --build-config Debug \
--label-regex unit --output-on-failure --no-compress-output \
--output-junit test-results-${{ matrix.compiler }}-cxx${std}-debug-unit.xml || std_failed=1
ctest --test-dir build/${{ matrix.preset }}-cxx${std} --build-config Debug \
--label-regex example --verbose --no-compress-output \
--output-junit test-results-${{ matrix.compiler }}-cxx${std}-debug-example.xml || std_failed=1
echo "::endgroup::"
fi
if [ $std_failed -eq 0 ]; then
echo "::group::Build Release C++${std}"
cmake --build build/${{ matrix.preset }}-cxx${std} --config Release -- -k 0 || std_failed=1
echo "::endgroup::"
fi
if [ $std_failed -eq 0 ]; then
echo "::group::Test Release C++${std}"
ctest --test-dir build/${{ matrix.preset }}-cxx${std} --build-config Release \
--label-regex header --output-on-failure --no-compress-output \
--output-junit test-results-${{ matrix.compiler }}-cxx${std}-release-header.xml || std_failed=1
ctest --test-dir build/${{ matrix.preset }}-cxx${std} --build-config Release \
--label-regex unit --output-on-failure --no-compress-output \
--output-junit test-results-${{ matrix.compiler }}-cxx${std}-release-unit.xml || std_failed=1
ctest --test-dir build/${{ matrix.preset }}-cxx${std} --build-config Release \
--label-regex example --verbose --no-compress-output \
--output-junit test-results-${{ matrix.compiler }}-cxx${std}-release-example.xml || std_failed=1
echo "::endgroup::"
fi
[ $std_failed -ne 0 ] && overall_failed=1
done
exit $overall_failed
- name: Upload test results
id: upload_test_results
continue-on-error: true
if: always()
uses: actions/upload-artifact@v6
with:
name: test-results-${{ matrix.compiler }}
path: build/${{ matrix.preset }}-cxx*/test-results-*.xml
if-no-files-found: ignore
retention-days: 30
# -- FetchContent consumer test (main only) -----------------------------
- name: Copy Preset (FetchContent)
id: fc_copy_preset
if: >-
always()
&& github.ref == 'refs/heads/main'
run: |
cp ./CMakePresets.json test/cmake-fetch_content
cp ./example/basic.cpp test/cmake-fetch_content/main.cpp
- name: Test Consumer (FetchContent) - Configure
id: fc_configure
if: >-
always()
&& github.ref == 'refs/heads/main'
&& steps.fc_copy_preset.outcome == 'success'
shell: bash
working-directory: test/cmake-fetch_content
run: |
for s in ${{ matrix.cxxstds }}; do latest_std=$s; done
cmake --preset ${{ matrix.preset }} -B build-consumer-fetch_content \
-DEGGS_STACKTRACE_SOURCE_DIR=${{ github.workspace }} \
-DCMAKE_CXX_STANDARD=${latest_std}
- name: Test Consumer (FetchContent) - Build (Debug)
id: fc_build_debug
if: >-
always()
&& github.ref == 'refs/heads/main'
&& steps.fc_configure.outcome == 'success'
working-directory: test/cmake-fetch_content
run: cmake --build build-consumer-fetch_content --config Debug
- name: Test Consumer (FetchContent) - Test (Debug)
id: fc_test_debug
if: >-
always()
&& github.ref == 'refs/heads/main'
&& steps.fc_configure.outcome == 'success'
working-directory: test/cmake-fetch_content
run: ctest --test-dir build-consumer-fetch_content --build-config Debug -V
- name: Test Consumer (FetchContent) - Build (Release)
id: fc_build_release
if: >-
always()
&& github.ref == 'refs/heads/main'
&& steps.fc_configure.outcome == 'success'
working-directory: test/cmake-fetch_content
run: cmake --build build-consumer-fetch_content --config Release
- name: Test Consumer (FetchContent) - Test (Release)
id: fc_test_release
if: >-
always()
&& github.ref == 'refs/heads/main'
&& steps.fc_configure.outcome == 'success'
working-directory: test/cmake-fetch_content
run: ctest --test-dir build-consumer-fetch_content --build-config Release -V
# -- find_package consumer test (main only) -----------------------------
# Uses the consumer's own declared floor (see test/cmake-find_package/CMakeLists.txt)
# rather than the 4.4.0 pinned above, to verify the installed package
# config still works for consumers on an older CMake.
- name: Test Install (Debug)
id: install_debug
if: >-
always()
&& github.ref == 'refs/heads/main'
shell: bash
run: |
for s in ${{ matrix.cxxstds }}; do latest_std=$s; done
cmake --install build/${{ matrix.preset }}-cxx${latest_std} \
--prefix ${{ runner.temp }}/eggs-stacktrace-install --config Debug
- name: Test Install (Release)
id: install_release
if: >-
always()
&& github.ref == 'refs/heads/main'
shell: bash
run: |
for s in ${{ matrix.cxxstds }}; do latest_std=$s; done
cmake --install build/${{ matrix.preset }}-cxx${latest_std} \
--prefix ${{ runner.temp }}/eggs-stacktrace-install --config Release
- name: Upload installed package
id: upload_installed_package
continue-on-error: true
if: >-
always()
&& github.ref == 'refs/heads/main'
&& steps.install_debug.outcome == 'success'
&& steps.install_release.outcome == 'success'
uses: actions/upload-artifact@v6
with:
name: installed-package-${{ matrix.compiler }}
path: ${{ runner.temp }}/eggs-stacktrace-install
if-no-files-found: error
retention-days: 7
- name: Clean Source and Build Tree
id: clean_source_build_tree
if: >-
always()
&& github.ref == 'refs/heads/main'
run: cmake -E rm -rf ./include ./src ./build
- name: Copy Preset (find_package)
id: fp_copy_preset
if: >-
always()
&& github.ref == 'refs/heads/main'
&& steps.clean_source_build_tree.outcome == 'success'
run: |
cp ./CMakePresets.json test/cmake-find_package
cp ./example/basic.cpp test/cmake-find_package/main.cpp
- name: Install CMake (find_package minimum)
id: fp_install_cmake_min
if: >-
always()
&& github.ref == 'refs/heads/main'
&& steps.install_debug.outcome == 'success'
&& steps.install_release.outcome == 'success'
uses: lukka/get-cmake@latest
with:
cmakeVersion: "3.21.0"
- name: Test Consumer (find_package) - Configure
id: fp_configure
if: >-
always()
&& github.ref == 'refs/heads/main'
&& steps.install_debug.outcome == 'success'
&& steps.install_release.outcome == 'success'
&& steps.fp_copy_preset.outcome == 'success'
&& steps.fp_install_cmake_min.outcome == 'success'
shell: bash
working-directory: test/cmake-find_package
run: |
# Fixed at 14, not matrix.cxxstds' latest_std: CMake didn't even
# recognize CXX_STANDARD 26 as a valid value until 3.25 (23 until
# 3.20), so pinning to 3.21.0 above and requesting a job's highest
# std here would hard-fail configure for every C++26 job. 14 has
# had a real compiler flag on GNU/Clang/MSVC since long before 3.21.
cmake --preset ${{ matrix.preset }} -B build-consumer-find_package \
-DCMAKE_PREFIX_PATH=${{ runner.temp }}/eggs-stacktrace-install \
--debug-find-pkg=Eggs.Stacktrace \
-DCMAKE_CXX_STANDARD=14
- name: Test Consumer (find_package) - Build (Debug)
id: fp_build_debug
if: >-
always()
&& github.ref == 'refs/heads/main'
&& steps.fp_configure.outcome == 'success'
working-directory: test/cmake-find_package
run: cmake --build build-consumer-find_package --config Debug
- name: Test Consumer (find_package) - Test (Debug)
id: fp_test_debug
if: >-
always()
&& github.ref == 'refs/heads/main'
&& steps.fp_configure.outcome == 'success'
working-directory: test/cmake-find_package
run: ctest --test-dir build-consumer-find_package --build-config Debug -V
- name: Test Consumer (find_package) - Build (Release)
id: fp_build_release
if: >-
always()
&& github.ref == 'refs/heads/main'
&& steps.fp_configure.outcome == 'success'
working-directory: test/cmake-find_package
run: cmake --build build-consumer-find_package --config Release
- name: Test Consumer (find_package) - Test (Release)
id: fp_test_release
if: >-
always()
&& github.ref == 'refs/heads/main'
&& steps.fp_configure.outcome == 'success'
working-directory: test/cmake-find_package
run: ctest --test-dir build-consumer-find_package --build-config Release -V
- name: Check all step outcomes
if: always()
shell: bash
run: |
failed=$(echo '${{ toJSON(steps) }}' | jq -r '[to_entries[] | select(.value.outcome == "failure") | .key] | join(", ")')
if [ -n "$failed" ]; then
echo "::error::Failed steps: $failed"
fi