Skip to content

Refactor CI

Refactor CI #2260

Workflow file for this run

name: snmalloc CI
# The following should ensure that the workflow only runs a single set of actions
# for each PR. But it will not apply this to pushes to the main branch.
concurrency:
group: ${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
on:
push:
branches: [ main ]
pull_request:
branches: [ main, snmalloc1 ]
workflow_dispatch:
jobs:
# ============================================================================
# Ubuntu builds - using reusable workflow
# ============================================================================
ubuntu:
strategy:
fail-fast: false
matrix:
os: [ "ubuntu-24.04", "ubuntu-22.04", "ubuntu-24.04-arm" ]
build-type: [ "Release", "Debug" ]
cmake-flags: [ "" ]
self-host: [ false ]
build-only: [ false ]
cxx-compiler: [ "" ]
c-compiler: [ "" ]
variant: [ "" ]
include:
# C++17 build
- os: "ubuntu-22.04"
build-type: Debug
cmake-flags: "-DSNMALLOC_USE_CXX17=ON"
variant: "C++17"
# Self-host with bounds-checked memcpy in paranoid mode
- os: "ubuntu-24.04"
build-type: Debug
cmake-flags: "-DSNMALLOC_MEMCPY_BOUNDS=ON -DSNMALLOC_CHECK_LOADS=ON"
self-host: true
variant: "Paranoid self-host"
# pthread destructors
- os: "ubuntu-24.04"
build-type: Debug
cmake-flags: "-DSNMALLOC_USE_PTHREAD_DESTRUCTORS=On"
self-host: true
variant: "pthread destructors"
# Individual mitigations
- os: "ubuntu-24.04"
build-type: Release
cmake-flags: "-DSNMALLOC_BENCHMARK_INDIVIDUAL_MITIGATIONS=On -DSNMALLOC_BUILD_TESTING=Off"
self-host: true
variant: "Individual mitigations"
# libstdc++ build-only
- os: "ubuntu-24.04"
build-type: Release
cmake-flags: "-DCMAKE_CXX_COMPILER=clang++ -DCMAKE_CXX_FLAGS=-stdlib=libstdc++"
build-only: true
variant: "clang libstdc++"
# Traced build
- os: "ubuntu-22.04"
build-type: Release
cmake-flags: "-DSNMALLOC_TRACING=On"
build-only: true
variant: "Tracing"
# clang + libstdc++
- os: "ubuntu-22.04"
build-type: Release
cmake-flags: "-DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_FLAGS=-stdlib=libstdc++"
build-only: true
variant: "clang libstdc++"
# Self-vendored STL with clang
- os: "ubuntu-24.04"
build-type: RelWithDebInfo
cmake-flags: "-DSNMALLOC_USE_SELF_VENDORED_STL=ON"
cxx-compiler: clang++-18
c-compiler: clang-18
variant: "Self-vendored clang"
# Self-vendored STL with gcc
- os: "ubuntu-24.04"
build-type: RelWithDebInfo
cmake-flags: "-DSNMALLOC_USE_SELF_VENDORED_STL=ON"
cxx-compiler: g++-14
c-compiler: gcc-14
variant: "Self-vendored gcc"
# Sanitizer builds (TSan + UBSan)
- os: "ubuntu-24.04"
build-type: Release
cmake-flags: "-DCMAKE_CXX_COMPILER=clang++ -DCMAKE_CXX_FLAGS=-stdlib=\"libc++ -g\" -DSNMALLOC_SANITIZER=undefined,thread"
variant: "TSan + UBSan"
dependencies: "sudo apt install -y ninja-build libc++-dev"
test-exclude-pattern: "memcpy|external_pointer"
test-extra-args: "--repeat-until-fail 2"
- os: "ubuntu-22.04"
build-type: Release
cmake-flags: "-DCMAKE_CXX_COMPILER=clang++ -DCMAKE_CXX_FLAGS=-stdlib=\"libc++ -g\" -DSNMALLOC_SANITIZER=undefined,thread"
variant: "TSan + UBSan"
dependencies: "sudo apt install -y ninja-build libc++-dev"
test-exclude-pattern: "memcpy|external_pointer"
test-extra-args: "--repeat-until-fail 2"
uses: ./.github/workflows/reusable-cmake-build.yml
with:
os: ${{ matrix.os }}
build-type: ${{ matrix.build-type }}
dependencies: ${{ matrix.dependencies || 'sudo apt install -y ninja-build' }}
cmake-flags: ${{ matrix.cmake-flags }}
self-host: ${{ matrix.self-host || false }}
build-only: ${{ matrix.build-only || false }}
cxx-compiler: ${{ matrix.cxx-compiler || '' }}
c-compiler: ${{ matrix.c-compiler || '' }}
variant: ${{ matrix.variant }}
test-exclude-pattern: ${{ matrix.test-exclude-pattern || '' }}
test-extra-args: ${{ matrix.test-extra-args || '' }}
# ============================================================================
# Bazel builds
# ============================================================================
bazel:
strategy:
fail-fast: false
matrix:
os: [ "ubuntu-24.04", "ubuntu-22.04", "macos-14", "macos-15" ]
build-type: [ "Release", "Debug" ]
runs-on: ${{ matrix.os }}
name: Bazel - ${{ matrix.os }} ${{ matrix.build-type }}
steps:
- uses: actions/checkout@v4
- uses: bazelbuild/setup-bazelisk@v3
- name: Mount bazel cache
uses: actions/cache@v4
with:
path: "~/.cache/bazel"
key: bazel-${{ matrix.os }}-${{ matrix.build-type }}
- run: bazel build -c opt //:snmalloc
- run: bazel build -c opt //:snmalloc-rs
- run: bazel test -c opt --config=asan //fuzzing:snmalloc_fuzzer
if: ${{ matrix.os != 'macos-14' && matrix.os != 'macos-15' }}
# ============================================================================
# macOS builds - using reusable workflow
# ============================================================================
macos:
strategy:
fail-fast: false
matrix:
os: [ "macos-14", "macos-15" ]
build-type: [ "Release", "Debug" ]
cxx17: [ false, true ]
cmake-flags: [ "" ]
variant: [ "" ]
include:
# Self-vendored STL
- os: "macos-latest"
build-type: RelWithDebInfo
cmake-flags: "-DSNMALLOC_USE_SELF_VENDORED_STL=ON"
cxx-compiler: clang++
c-compiler: clang
variant: "Self-vendored"
uses: ./.github/workflows/reusable-cmake-build.yml
with:
os: ${{ matrix.os }}
build-type: ${{ matrix.build-type }}
dependencies: "rm -f /usr/local/bin/2to3 || true; brew update && brew install ninja"
cmake-flags: ${{ matrix.cxx17 && '-DSNMALLOC_USE_CXX17=ON' || matrix.cmake-flags || '' }}
cxx-compiler: ${{ matrix.cxx-compiler || '' }}
c-compiler: ${{ matrix.c-compiler || '' }}
variant: ${{ matrix.cxx17 && 'C++17' || matrix.variant || '' }}
# ============================================================================
# BSD builds - using reusable VM workflow
# ============================================================================
freebsd:
strategy:
fail-fast: false
matrix:
build-type: [ Release, Debug ]
uses: ./.github/workflows/reusable-vm-build.yml
with:
vm-type: freebsd
vm-version: '13.2'
build-type: ${{ matrix.build-type }}
dependencies: "pkg ins -y cmake ninja"
netbsd:
uses: ./.github/workflows/reusable-vm-build.yml
with:
vm-type: netbsd
vm-version: '9.2'
build-type: Release
dependencies: "/usr/sbin/pkg_add cmake ninja-build gcc10"
cmake-flags: "-DCMAKE_CXX_COMPILER=/usr/pkg/gcc10/bin/g++ -DCMAKE_C_COMPILER=/usr/pkg/gcc10/bin/gcc"
# ============================================================================
# QEMU cross-compilation builds
# ============================================================================
qemu-crossbuild:
strategy:
fail-fast: false
matrix:
build-type: [ Release, Debug ]
arch:
- name: armhf
system-processor: arm
triple: arm-linux-gnueabihf
rtld: ld-linux-armhf.so.3
ld-flavour: lld
host-os: ubuntu-24.04
- name: arm64
system-processor: aarch64
triple: aarch64-linux-gnu
rtld: ld-linux-aarch64.so.1
ld-flavour: lld
host-os: ubuntu-24.04
- name: riscv64
system-processor: riscv64
triple: riscv64-linux-gnu
rtld: ld-linux-riscv64-lp64d.so.1
extra-packages: binutils-riscv64-linux-gnu
ld-flavour: bfd
ld: /usr/bin/riscv64-linux-gnu-ld.bfd
host-os: ubuntu-24.04
runs-on: ${{ matrix.arch.host-os }}
name: Crossbuild - ${{ matrix.build-type }} ${{ matrix.arch.triple }}
steps:
- uses: actions/checkout@v4
- name: Install cross-compile toolchain and QEMU
run: |
sudo apt update
sudo apt install libstdc++-12-dev-${{ matrix.arch.name }}-cross qemu-user ninja-build binfmt-support
sudo apt install ${{ matrix.arch.extra-packages }}
- name: Configure
env:
SNMALLOC_CI_CLANG_VERSION: 16
RTLD_NAME: ${{ matrix.arch.rtld }}
ARCH: ${{ matrix.arch.system-processor }}
TRIPLE: ${{ matrix.arch.triple }}
run: >
cmake
-B ${{ github.workspace }}/build
-DCMAKE_BUILD_TYPE=${{ matrix.build-type }}
-G Ninja
-DSNMALLOC_CI_BUILD=ON
-DSNMALLOC_QEMU_WORKAROUND=ON
-DSNMALLOC_STATIC_LIBRARY=OFF
-DCMAKE_TOOLCHAIN_FILE=ci/Toolchain.cmake
-DSNMALLOC_LINKER=${{ matrix.arch.ld }}
-DSNMALLOC_LINKER_FLAVOUR=${{ matrix.arch.ld-flavour }}
- name: Build
working-directory: ${{ github.workspace }}/build
run: NINJA_STATUS="%p [%f:%s/%t] %o/s, %es" ninja
- name: Verify cross-compilation
working-directory: ${{ github.workspace }}/build
run: file func*
- name: Test
working-directory: ${{ github.workspace }}/build
run: ctest -j 2 --output-on-failure -E '(perf-.*)|(.*-malloc$)' --timeout 400
timeout-minutes: 30
# ============================================================================
# Windows builds - using reusable workflow
# ============================================================================
windows:
strategy:
fail-fast: false
matrix:
os: [ windows-2022, windows-2025 ]
build-type: [ Release, Debug ]
arch: [ Win32, x64 ]
toolchain: [ "", "-T ClangCL" ]
cmake-flags: [ "-DSNMALLOC_CI_BUILD=On -DSNMALLOC_RUST_SUPPORT=On" ]
build-only: [ false ]
dependencies: [ "" ]
cxx-compiler: [ "" ]
c-compiler: [ "" ]
variant: [ "" ]
include:
# Windows 8 compatible build
- os: windows-2022
build-type: Release
arch: x64
toolchain: ""
cmake-flags: "-DWIN8COMPAT=TRUE -DSNMALLOC_CI_BUILD=On -DSNMALLOC_RUST_SUPPORT=On"
variant: "Win8 compat"
# ARM64 builds (build-only, no tests)
- os: windows-2022
build-type: Release
arch: ARM64
toolchain: ""
cmake-flags: "-DSNMALLOC_CI_BUILD=On -DSNMALLOC_RUST_SUPPORT=On"
build-only: true
- os: windows-2022
build-type: Debug
arch: ARM64
toolchain: ""
cmake-flags: "-DSNMALLOC_CI_BUILD=On -DSNMALLOC_RUST_SUPPORT=On"
build-only: true
# ARM64EC builds (build-only, no tests)
- os: windows-2022
build-type: Release
arch: ARM64EC
toolchain: ""
cmake-flags: "-DCMAKE_SYSTEM_VERSION=10.0.22621.0 -DSNMALLOC_CI_BUILD=On -DSNMALLOC_RUST_SUPPORT=On"
build-only: true
- os: windows-2022
build-type: Debug
arch: ARM64EC
toolchain: ""
cmake-flags: "-DCMAKE_SYSTEM_VERSION=10.0.22621.0 -DSNMALLOC_CI_BUILD=On -DSNMALLOC_RUST_SUPPORT=On"
build-only: true
# Self-vendored STL (uses Ninja, not MSBuild)
- os: windows-2022
build-type: RelWithDebInfo
arch: ""
toolchain: ""
cmake-flags: "-DSNMALLOC_USE_SELF_VENDORED_STL=ON"
dependencies: "choco upgrade llvm && choco install ninja"
cxx-compiler: clang-cl
c-compiler: clang-cl
variant: "Self-vendored"
uses: ./.github/workflows/reusable-cmake-build.yml
with:
os: ${{ matrix.os }}
build-type: ${{ matrix.build-type }}
arch: ${{ matrix.arch }}
toolchain: ${{ matrix.toolchain }}
cmake-flags: ${{ matrix.cmake-flags }}
build-only: ${{ matrix.build-only || false }}
dependencies: ${{ matrix.dependencies || '' }}
cxx-compiler: ${{ matrix.cxx-compiler || '' }}
c-compiler: ${{ matrix.c-compiler || '' }}
variant: ${{ matrix.toolchain == '-T ClangCL' && 'ClangCL' || matrix.variant || '' }}
# ============================================================================
# Format and lint checks
# ============================================================================
format:
runs-on: ubuntu-22.04
name: Format check
steps:
- uses: actions/checkout@v4
- name: Install clang-tidy and clang-format
run: |
sudo apt update
sudo apt install clang-tidy-15 clang-format-15
- name: Configure CMake
run: cmake -B ${{ github.workspace }}/build -DSNMALLOC_USE_CXX17=ON
- name: Run clang-format
working-directory: ${{ github.workspace }}/build
run: |
set -eo pipefail
make clangformat
git diff --exit-code
- name: Run clang-tidy
run: |
clang-tidy-15 src/snmalloc/override/malloc.cc -header-filter="`pwd`/*" -warnings-as-errors='*' -export-fixes=tidy.fail -- -std=c++17 -mcx16 -DSNMALLOC_USE_WAIT_ON_ADDRESS=1 -DSNMALLOC_PLATFORM_HAS_GETENTROPY=0 -Isrc
if [ -f tidy.fail ]; then
cat tidy.fail
exit 1
fi
# ============================================================================
# Fuzzing
# ============================================================================
fuzzing:
name: Fuzzing
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Configure CMake
run: cmake -B ${{ github.workspace }}/build -DSNMALLOC_ENABLE_FUZZING=ON -DFUZZTEST_FUZZING_MODE=ON -DCMAKE_CXX_COMPILER=clang++
- name: Build
run: cmake --build ${{ github.workspace }}/build --target snmalloc-fuzzer
- name: Test
run: ${{ github.workspace }}/build/fuzzing/snmalloc-fuzzer
# ============================================================================
# GWP-ASan integration
# ============================================================================
gwp-asan:
strategy:
fail-fast: false
matrix:
os: [ubuntu-24.04, ubuntu-24.04-arm]
profile: [RelWithDebInfo, Debug]
runs-on: ${{ matrix.os }}
name: GWP-ASan - ${{ matrix.os }} ${{ matrix.profile }}
steps:
- uses: actions/checkout@v4
- name: Install Ninja
run: sudo apt-get install -y ninja-build
- name: Install Compiler-RT
run: |
cd ..
git clone https://github.com/llvm/llvm-project --depth=1 -b llvmorg-19.1.7
mkdir compiler-rt
cmake -G Ninja \
-S llvm-project/runtimes \
-B llvm-project/build \
-DCMAKE_BUILD_TYPE=${{ matrix.profile }} \
-DLLVM_ENABLE_RUNTIMES=compiler-rt \
-DCMAKE_CXX_COMPILER=clang++-18 \
-DCMAKE_C_COMPILER=clang-18 \
-DCMAKE_INSTALL_PREFIX=$(realpath compiler-rt)
cmake --build llvm-project/build --parallel
cmake --build llvm-project/build --target=install
- name: Configure SnMalloc
run: >
cmake -GNinja
-B${{ github.workspace }}/build
-DCMAKE_BUILD_TYPE=${{ matrix.profile }}
-DCMAKE_CXX_COMPILER=clang++-18
-DCMAKE_C_COMPILER=clang-18
-DSNMALLOC_ENABLE_GWP_ASAN_INTEGRATION=On
-DSNMALLOC_GWP_ASAN_INCLUDE_PATH=${{ github.workspace }}/../llvm-project/compiler-rt/lib
-DSNMALLOC_GWP_ASAN_LIBRARY_PATH=${{ github.workspace }}/../compiler-rt/lib/linux
- name: Build
run: cmake --build ${{ github.workspace }}/build --parallel
- name: Test
run: |
cd ${{ github.workspace }}/build
ctest --parallel --output-on-failure
# ============================================================================
# Final gate check
# ============================================================================
all-checks:
needs: [
ubuntu,
macos,
freebsd, netbsd,
qemu-crossbuild,
windows,
format
]
runs-on: ubuntu-24.04
steps:
- name: All checks passed
run: echo "All required checks passed!"