mirror of
https://github.com/boostorg/boost-ci.git
synced 2026-01-19 04:02:12 +00:00
840 lines
39 KiB
YAML
840 lines
39 KiB
YAML
#
|
|
# Copyright 2020-2021 Peter Dimov
|
|
# Copyright 2021 Andrey Semashev
|
|
# Copyright 2021-2024 Alexander Grund
|
|
# Copyright 2022-2025 James E. King III
|
|
#
|
|
# Distributed under the Boost Software License, Version 1.0.
|
|
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
|
#
|
|
# This reusable workflow is called from ci.yml, if you want to use it you should do the
|
|
# same. See the README for more details.
|
|
#
|
|
---
|
|
name: Boost.CI
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
branch_coverage:
|
|
description: "Collect branch coverage instead of line coverage. Enabled by default."
|
|
required: false
|
|
type: boolean
|
|
default: true
|
|
enable_32bit:
|
|
description: "When enabled, 32-bit jobs will be added. Enabled by default."
|
|
required: false
|
|
type: boolean
|
|
default: true
|
|
enable_cmake:
|
|
description: "When enabled, CMake jobs will be added. Enabled by default."
|
|
required: false
|
|
type: boolean
|
|
default: true
|
|
min_cmake_version:
|
|
description: "Minimal required CMake version, defaults to 3.16. Default of ubuntu-latest is always tested additionally."
|
|
required: false
|
|
type: string
|
|
default: '3.16'
|
|
enable_cygwin:
|
|
description: "When enabled, Cygwin jobs will be added. Enabled by default."
|
|
required: false
|
|
type: boolean
|
|
default: true
|
|
enable_mingw:
|
|
description: "When enabled, MinGW jobs will be added using MSYS2. Enabled by default."
|
|
required: false
|
|
type: boolean
|
|
default: true
|
|
enable_multiarch:
|
|
description: "When enabled, a s390x big-endian job will be added. Enabled by default."
|
|
required: false
|
|
type: boolean
|
|
default: true
|
|
enable_posix:
|
|
description: "When enabled, POSIX jobs will be added (includes macos). Enabled by default."
|
|
required: false
|
|
type: boolean
|
|
default: true
|
|
enable_pr_coverage:
|
|
description: "When enabled, coverage will be collected even without a $CODECOV_TOKEN, e.g for PRs where it usually is not available. Enabled by default."
|
|
required: false
|
|
type: boolean
|
|
default: true
|
|
enable_sanitizers:
|
|
description: "When enabled, sanitizer (ASAN, UBSAN) jobs will be added. Enabled by default."
|
|
required: false
|
|
type: boolean
|
|
default: true
|
|
enable_windows:
|
|
description: "When enabled, Windows jobs will be added. Enabled by default."
|
|
required: false
|
|
type: boolean
|
|
default: true
|
|
enable_reflection:
|
|
description: "When enabled, clang-p2996 jobs will be added. Disabled by default."
|
|
required: false
|
|
type: boolean
|
|
default: false
|
|
exclude_compiler:
|
|
description: "Comma-separated list of compilers to disable. By default only GCC 4.7 is excluded."
|
|
required: false
|
|
type: string
|
|
# gcc-4.7 is not fully compliant with C++11, so we disable it by default
|
|
default: 'gcc-4.7'
|
|
exclude_cxxstd:
|
|
description: "Comma-separated list of C++ standards to disable. By default, only C++11 and later standards are enabled."
|
|
required: false
|
|
type: string
|
|
default: '98,03,0x'
|
|
exclude_os:
|
|
description: "Comma-separated list of OS to disable, e.g. 'ubuntu:18.04'. Supports partial matches such as 'macos'. By default no OS is excluded."
|
|
required: false
|
|
type: string
|
|
default: ''
|
|
secrets:
|
|
CODECOV_TOKEN:
|
|
description: "The token for covecov.io; if defined then coverage will be collected."
|
|
required: false
|
|
COVERITY_SCAN_NOTIFICATION_EMAIL:
|
|
description: "The email address for coverity scan notifications"
|
|
required: false
|
|
COVERITY_SCAN_TOKEN:
|
|
description: "The project token for coverity scan; if defined then coverity scan will run."
|
|
required: false
|
|
|
|
concurrency:
|
|
group: ${{format('{0}:{1}:{2}', github.repository, github.ref, github.workflow_ref)}}
|
|
cancel-in-progress: true
|
|
|
|
env:
|
|
GIT_FETCH_JOBS: 8
|
|
NET_RETRY_COUNT: 5
|
|
B2_VARIANT: debug,release
|
|
B2_LINK: shared,static
|
|
LCOV_BRANCH_COVERAGE: ${{ inputs.branch_coverage && '1' || '0' }}
|
|
CODECOV_NAME: Github Actions
|
|
|
|
jobs:
|
|
generate-posix-matrix:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
|
steps:
|
|
- id: set-matrix
|
|
run: |
|
|
import json, os
|
|
|
|
# All jobs
|
|
all_jobs = [
|
|
# libstdc++ (by default: disabled (see exclude_cxxstd, exclude_compiler),
|
|
# tests are pre-C++11 standard; gcc-4.7 is not fully compliant)
|
|
{"compiler": "gcc-4.4", "cxxstd": "98", "os": "ubuntu-latest", "container": "ubuntu:16.04"},
|
|
{"compiler": "gcc-4.6", "cxxstd": "03,0x", "os": "ubuntu-latest", "container": "ubuntu:16.04"},
|
|
{"compiler": "gcc-4.7", "cxxstd": "03,11", "os": "ubuntu-latest", "container": "ubuntu:16.04"},
|
|
# libstdc++
|
|
{"compiler": "gcc-4.7", "cxxstd": "11", "os": "ubuntu-latest", "container": "ubuntu:16.04"},
|
|
{"compiler": "gcc-4.8", "cxxstd": "11", "os": "ubuntu-latest", "container": "ubuntu:16.04"},
|
|
{"compiler": "gcc-4.9", "cxxstd": "11", "os": "ubuntu-latest", "container": "ubuntu:16.04"},
|
|
{"compiler": "gcc-5", "cxxstd": "11,14,1z", "os": "ubuntu-latest", "container": "ubuntu:18.04"},
|
|
{"compiler": "gcc-6", "cxxstd": "11,14,17", "os": "ubuntu-latest", "container": "ubuntu:18.04"},
|
|
{"compiler": "gcc-7", "cxxstd": "11,14,17", "os": "ubuntu-latest", "container": "ubuntu:20.04"},
|
|
{"compiler": "gcc-8", "cxxstd": "11,14,17,2a", "os": "ubuntu-latest", "container": "ubuntu:20.04"},
|
|
{"compiler": "gcc-9", "cxxstd": "11,14,17,2a", "os": "ubuntu-22.04"},
|
|
{"compiler": "gcc-10", "cxxstd": "11,14,17,20", "os": "ubuntu-22.04"},
|
|
{"compiler": "gcc-11", "cxxstd": "11,14,17,20", "os": "ubuntu-22.04"},
|
|
{"compiler": "gcc-12", "cxxstd": "11,14,17,20", "os": "ubuntu-22.04"},
|
|
{"compiler": "gcc-13", "cxxstd": "11,14,17,20,2b", "os": "ubuntu-24.04"},
|
|
{"name": "coverage-gcc-linux", "coverage": "yes",
|
|
"compiler": "gcc-13", "cxxstd": "2b", "os": "ubuntu-24.04", "install": "g++-13-multilib gcc-multilib", "address-model": "32,64" },
|
|
{"name": "sanitize-gcc-linux", "sanitize": "yes",
|
|
"compiler": "gcc-13", "cxxstd": "11,14,17,20", "os": "ubuntu-24.04"},
|
|
{"compiler": "gcc-14", "cxxstd": "11,14,17,20,23", "os": "ubuntu-24.04"},
|
|
{"compiler": "gcc-15", "cxxstd": "11,14,17,20,23,2c", "os": "ubuntu-latest", "container": "ubuntu:25.04"},
|
|
{"compiler": "clang-3.5", "cxxstd": "11", "os": "ubuntu-latest", "container": "ubuntu:16.04"},
|
|
{"compiler": "clang-3.6", "cxxstd": "11,14", "os": "ubuntu-latest", "container": "ubuntu:16.04"},
|
|
{"compiler": "clang-3.7", "cxxstd": "11,14", "os": "ubuntu-latest", "container": "ubuntu:16.04"},
|
|
{"compiler": "clang-3.8", "cxxstd": "11,14", "os": "ubuntu-latest", "container": "ubuntu:16.04"},
|
|
{"compiler": "clang-3.9", "cxxstd": "11,14", "os": "ubuntu-latest", "container": "ubuntu:18.04"},
|
|
{"compiler": "clang-4.0", "cxxstd": "11,14", "os": "ubuntu-latest", "container": "ubuntu:18.04"},
|
|
{"compiler": "clang-5.0", "cxxstd": "11,14,1z", "os": "ubuntu-latest", "container": "ubuntu:18.04"},
|
|
{"compiler": "clang-6.0", "cxxstd": "11,14,17", "os": "ubuntu-latest", "container": "ubuntu:20.04"},
|
|
{"compiler": "clang-7", "cxxstd": "11,14,17", "os": "ubuntu-latest", "container": "ubuntu:20.04"},
|
|
{"compiler": "clang-8", "cxxstd": "11,14,17", "os": "ubuntu-latest", "container": "ubuntu:20.04"},
|
|
{"compiler": "clang-9", "cxxstd": "11,14,17,2a", "os": "ubuntu-latest", "container": "ubuntu:20.04"},
|
|
{"compiler": "clang-10", "cxxstd": "11,14,17,20", "os": "ubuntu-latest", "container": "ubuntu:20.04"},
|
|
{"compiler": "clang-11", "cxxstd": "11,14,17,20", "os": "ubuntu-latest", "container": "ubuntu:20.04"},
|
|
{"compiler": "clang-12", "cxxstd": "11,14,17,20", "os": "ubuntu-latest", "container": "ubuntu:20.04"},
|
|
{"compiler": "clang-13", "cxxstd": "11,14,17,20", "os": "ubuntu-latest", "container": "ubuntu:22.04"},
|
|
{"compiler": "clang-14", "cxxstd": "11,14,17,20", "os": "ubuntu-latest", "container": "ubuntu:22.04"},
|
|
{"compiler": "clang-15", "cxxstd": "11,14,17,20", "os": "ubuntu-latest", "container": "ubuntu:22.04"},
|
|
{"compiler": "clang-16", "cxxstd": "11,14,17,20,2b", "os": "ubuntu-24.04"},
|
|
{"compiler": "clang-17", "cxxstd": "11,14,17,20,23", "os": "ubuntu-latest", "container": "ubuntu:24.04"},
|
|
{"compiler": "clang-18", "cxxstd": "11,14,17,20,23,2c", "os": "ubuntu-24.04"},
|
|
{"compiler": "clang-19", "cxxstd": "11,14,17,20,23,2c", "os": "ubuntu-24.04"},
|
|
{"compiler": "clang-20", "cxxstd": "11,14,17,20,23,2c", "os": "ubuntu-latest", "container": "ubuntu:25.04"},
|
|
{"compiler": "icpx-2025", "cxxstd": "11,14,17,20,23,2c", "os": "ubuntu-latest", "container": "intel/oneapi-hpckit:2025.2.2-0-devel-ubuntu24.04"},
|
|
# libc++
|
|
{"stdlib": "libc++",
|
|
"compiler": "clang-6.0", "cxxstd": "11,14", "os": "ubuntu-latest", "container": "ubuntu:18.04", "install": "clang-6.0 libc++-dev libc++abi-dev"},
|
|
{"stdlib": "libc++",
|
|
"compiler": "clang-7", "cxxstd": "11,14,17", "os": "ubuntu-latest", "container": "ubuntu:20.04"},
|
|
{"name": "Clang w/ sanitizers", "sanitize": "yes", "stdlib": "libc++",
|
|
"compiler": "clang-12", "cxxstd": "11,14,17,20", "os": "ubuntu-latest", "container": "ubuntu:20.04"},
|
|
# MacOS
|
|
{"name": "MacOS sanitize w/ clang",
|
|
"os": "macos-14", "compiler": "clang", "cxxstd": "11,14,17,20,2b", "sanitize": "yes"},
|
|
{"os": "macos-15", "compiler": "clang-16", "cxxstd": "11,14,17,20,2b", "xcode_app": "Xcode_16.2"},
|
|
{"os": "macos-15", "compiler": "clang-18", "cxxstd": "11,14,17,20,2b"},
|
|
# Coverity
|
|
{"name": "coverage-clang-linux", "coverity": "yes",
|
|
"compiler": "clang-12", "cxxstd": "20", "os": "ubuntu-22.04", "ccache": "no"},
|
|
# Big-Endian
|
|
{"name": "bigendian-s390x", "multiarch": "yes",
|
|
"compiler": "clang", "cxxstd": "17", "os": "ubuntu-22.04", "ccache": "no", "distro": "fedora", "edition": "34", "arch": "s390x"},
|
|
# Reflection
|
|
{"name": "Clang-preview w/ reflection",
|
|
"compiler": "clang", "cxxstd": "20,23,2c", "os": "ubuntu-latest", "container": "cppalliance/2404-p2996:1", "reflection": "yes"},
|
|
]
|
|
|
|
def is_true(env_var):
|
|
return os.environ.get(env_var).lower() == 'true'
|
|
|
|
def filter_multi_valued(in_list, key_name, excluded):
|
|
"""Remove all entries from the value identified by key_name that are contained in excluded (comma-separated).
|
|
Omit the entry when the attribute is empty, keep it if the attribute is not present."""
|
|
excluded_values = {x.strip() for x in excluded.split(',')}
|
|
for entry in in_list:
|
|
try:
|
|
values = [x.strip() for x in entry[key_name].split(',')]
|
|
except KeyError:
|
|
yield entry
|
|
else:
|
|
remaining_values = [v for v in values if v and v not in excluded_values]
|
|
if remaining_values:
|
|
entry[key_name] = ",".join(remaining_values)
|
|
yield entry
|
|
|
|
def filter_os(in_list, excluded):
|
|
"""Remove all jobs that match any of the excluded OS (comma-separated, supports partial matches)"""
|
|
excluded_values = [v for v in (x.strip().replace('-', ':') for x in excluded.split(',')) if v]
|
|
return (job for job in in_list if not any(ev in job.get('container', job['os']).replace('-', ':') for ev in excluded_values))
|
|
|
|
def filter_yes_values(in_list, key_name):
|
|
"""Remove all entries with value 'yes' for the key"""
|
|
return (e for e in in_list if not e.get(key_name) == "yes")
|
|
|
|
filtered = all_jobs
|
|
filtered = filter_multi_valued(filtered, 'cxxstd', os.environ['EXCLUDE_CXXSTD'])
|
|
filtered = filter_multi_valued(filtered, 'compiler', os.environ['EXCLUDE_COMPILER'])
|
|
filtered = filter_os(filtered, os.environ['EXCLUDE_OS'])
|
|
if not is_true('ENABLE_32BIT'):
|
|
filtered = filter_multi_valued(filtered, 'address-model', '32')
|
|
if not is_true('ENABLE_MULTIARCH'):
|
|
filtered = filter_yes_values(filtered, 'multiarch')
|
|
if not is_true('ENABLE_SANITIZERS'):
|
|
filtered = filter_yes_values(filtered, 'sanitize')
|
|
if not os.environ.get('CODECOV_TOKEN') and '${{inputs.enable_pr_coverage}}' != 'true':
|
|
filtered = filter_yes_values(filtered, 'coverage')
|
|
if not os.environ.get('COVERITY_SCAN_TOKEN'):
|
|
filtered = filter_yes_values(filtered, 'coverity')
|
|
if not is_true('ENABLE_REFLECTION'):
|
|
filtered = filter_yes_values(filtered, 'reflection')
|
|
|
|
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
|
|
print(f"matrix={json.dumps({'include': list(filtered)})}", file=fh)
|
|
shell: python
|
|
env:
|
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
|
ENABLE_32BIT: ${{ inputs.enable_32bit }}
|
|
ENABLE_MULTIARCH: ${{ inputs.enable_multiarch }}
|
|
ENABLE_SANITIZERS: ${{ inputs.enable_sanitizers }}
|
|
ENABLE_REFLECTION: ${{ inputs.enable_reflection }}
|
|
EXCLUDE_COMPILER: ${{ inputs.exclude_compiler }}
|
|
EXCLUDE_CXXSTD: ${{ inputs.exclude_cxxstd }}
|
|
EXCLUDE_OS: ${{ inputs.exclude_os }}
|
|
|
|
posix:
|
|
if: ${{ inputs.enable_posix }}
|
|
needs: generate-posix-matrix
|
|
runs-on: ${{matrix.os}}
|
|
timeout-minutes: 120
|
|
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{fromJson(needs.generate-posix-matrix.outputs.matrix)}}
|
|
|
|
container:
|
|
image: ${{matrix.container}}
|
|
volumes:
|
|
- /node20217:/node20217:rw,rshared
|
|
- ${{ startsWith(matrix.container, 'ubuntu:1') && '/node20217:/__e/node20:ro,rshared' || ' ' }}
|
|
|
|
env: {B2_USE_CCACHE: 1}
|
|
|
|
steps:
|
|
- name: Setup environment
|
|
run: |
|
|
if [ -f "/etc/debian_version" ]; then
|
|
echo "DEBIAN_FRONTEND=noninteractive" >> $GITHUB_ENV
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
fi
|
|
if [ -n "${{matrix.container}}" ] && [ -f "/etc/debian_version" ]; then
|
|
apt-get -o Acquire::Retries=$NET_RETRY_COUNT update
|
|
apt-get -o Acquire::Retries=$NET_RETRY_COUNT -y -q --no-install-suggests --no-install-recommends install sudo software-properties-common curl
|
|
# Need (newer) git, and the older Ubuntu container may require requesting the key manually using port 80
|
|
key_server="keyserver.boost.org"
|
|
echo "Downloading key from $key_server"
|
|
curl -sSL --retry ${NET_RETRY_COUNT:-5} "https://$key_server/pks/lookup?op=get&search=0xE1DD270288B4E6030699E45FA1715D88E1DF1F24" | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/git-core_ubuntu_ppa.gpg
|
|
for i in {1..${NET_RETRY_COUNT:-3}}; do sudo -E add-apt-repository -y ppa:git-core/ppa && break || sleep 10; done
|
|
apt-get -o Acquire::Retries=$NET_RETRY_COUNT update
|
|
osver=$(lsb_release -sr | cut -f1 -d.)
|
|
pkgs="g++ git xz-utils"
|
|
# Ubuntu 22+ has only Python 3 in the repos
|
|
if [ -n "$osver" ] && [ "$osver" -ge "20" ]; then
|
|
pkgs+=" python-is-python3 libpython3-dev"
|
|
else
|
|
pkgs+=" python libpython-dev"
|
|
fi
|
|
apt-get -o Acquire::Retries=$NET_RETRY_COUNT -y -q --no-install-suggests --no-install-recommends install $pkgs
|
|
fi
|
|
# For jobs not compatible with ccache, use "ccache: no" in the matrix
|
|
if [[ "${{ matrix.ccache }}" == "no" ]]; then
|
|
echo "B2_USE_CCACHE=0" >> $GITHUB_ENV
|
|
fi
|
|
if [[ "${{ matrix.sanitize }}" == "yes" ]]; then
|
|
echo "LSAN_OPTIONS=suppressions=${GITHUB_WORKSPACE}/test/suppressions.txt" >> $GITHUB_ENV
|
|
fi
|
|
git config --global pack.threads 0
|
|
if [[ "${{matrix.container}}" == "ubuntu:1"* ]]; then
|
|
# Node 20 doesn't work with Ubuntu 16/18 glibc: https://github.com/actions/checkout/issues/1590
|
|
curl -sL https://archives.boost.io/misc/node/node-v20.9.0-linux-x64-glibc-217.tar.xz | tar -xJ --strip-components 1 -C /node20217
|
|
fi
|
|
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
# For coverage builds fetch the whole history, else only 1 commit using a 'fake ternary'
|
|
fetch-depth: ${{ matrix.coverage && '0' || '1' }}
|
|
|
|
- name: Cache ccache
|
|
uses: actions/cache@v4
|
|
if: env.B2_USE_CCACHE
|
|
with:
|
|
path: ~/.ccache
|
|
key: ${{matrix.os}}-${{matrix.container}}-${{matrix.xcode_app}}${{matrix.compiler}}-${{github.sha}}
|
|
restore-keys: ${{matrix.os}}-${{matrix.container}}-${{matrix.xcode_app}}${{matrix.compiler}}-
|
|
|
|
- name: Fetch Boost.CI
|
|
uses: actions/checkout@v4
|
|
with:
|
|
repository: boostorg/boost-ci
|
|
ref: master
|
|
path: boost-ci-cloned
|
|
|
|
- name: Get CI scripts folder
|
|
run: |
|
|
# Copy ci folder if not testing Boost.CI
|
|
[[ "$GITHUB_REPOSITORY" =~ "boost-ci" ]] || cp -r boost-ci-cloned/ci .
|
|
rm -rf boost-ci-cloned
|
|
|
|
- name: Install packages
|
|
if: startsWith(matrix.os, 'ubuntu')
|
|
run: |
|
|
SOURCE_KEYS=("${{join(matrix.source_keys, '" "')}}")
|
|
SOURCES=("${{join(matrix.sources, '" "')}}")
|
|
# Add this by default
|
|
SOURCE_KEYS+=('0x1E9377A2BA9EF27F')
|
|
SOURCES+=(ppa:ubuntu-toolchain-r/test)
|
|
|
|
ci/add-apt-keys.sh "${SOURCE_KEYS[@]}"
|
|
# Initial update before adding sources required to get e.g. keys
|
|
sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT update
|
|
ci/add-apt-repositories.sh "${SOURCES[@]}"
|
|
|
|
sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT update
|
|
if [[ -z "${{matrix.install}}" ]]; then
|
|
if [[ ! "${{matrix.compiler}}" =~ icpx ]]; then
|
|
compiler="${{matrix.compiler}}"
|
|
pkgs="${compiler/gcc-/g++-}"
|
|
[[ -z "${{matrix.gcc_toolchain}}" ]] || pkgs+=" g++-${{matrix.gcc_toolchain}}"
|
|
if [[ "${{matrix.stdlib}}" == "libc++" && $compiler == "clang-"* ]]; then
|
|
ver=${compiler#*-}
|
|
pkgs+=" libc++-${ver}-dev libc++abi-${ver}-dev"
|
|
fi
|
|
fi
|
|
else
|
|
pkgs="${{matrix.install}}"
|
|
fi
|
|
if [ -n "${pkgs}" ]; then
|
|
sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT -y -q --no-install-suggests --no-install-recommends install $pkgs
|
|
fi
|
|
|
|
- name: Setup GCC Toolchain
|
|
if: matrix.gcc_toolchain
|
|
run: |
|
|
GCC_TOOLCHAIN_ROOT="$HOME/gcc-toolchain"
|
|
echo "GCC_TOOLCHAIN_ROOT=$GCC_TOOLCHAIN_ROOT" >> $GITHUB_ENV
|
|
if ! command -v dpkg-architecture; then
|
|
apt-get -o Acquire::Retries=$NET_RETRY_COUNT -y -q --no-install-suggests --no-install-recommends install dpkg-dev
|
|
fi
|
|
MULTIARCH_TRIPLET="$(dpkg-architecture -qDEB_HOST_MULTIARCH)"
|
|
mkdir -p "$GCC_TOOLCHAIN_ROOT"
|
|
ln -s /usr/include "$GCC_TOOLCHAIN_ROOT/include"
|
|
ln -s /usr/bin "$GCC_TOOLCHAIN_ROOT/bin"
|
|
mkdir -p "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET"
|
|
ln -s "/usr/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}" "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}"
|
|
|
|
- name: Setup multiarch
|
|
if: matrix.multiarch
|
|
run: ci/github/setup_bdde.sh
|
|
env:
|
|
BDDE_DISTRO: ${{matrix.distro}}
|
|
BDDE_EDITION: ${{matrix.edition}}
|
|
BDDE_ARCH: ${{matrix.arch}}
|
|
|
|
- name: Setup Boost
|
|
run: source ci/github/install.sh
|
|
env:
|
|
B2_ADDRESS_MODEL: ${{matrix.address-model}}
|
|
B2_COMPILER: ${{matrix.compiler}}
|
|
B2_CXXSTD: ${{matrix.cxxstd}}
|
|
B2_SANITIZE: ${{matrix.sanitize}}
|
|
B2_STDLIB: ${{matrix.stdlib}}
|
|
# Optional. Variables set here (to non-empty) will override the top-level environment variables
|
|
B2_DEFINES: ${{matrix.defines}}
|
|
B2_VARIANT: ${{matrix.variant}}
|
|
B2_LINK: ${{matrix.link}}
|
|
XCODE_APP: ${{matrix.xcode_app}}
|
|
# More entries can be added in the same way, see the B2_ARGS assignment in ci/enforce.sh for the possible keys.
|
|
# Set the (B2) target(s) to build, defaults to the test folder of the current library
|
|
# Can alternatively be done like this in the build step or in the build command of the build step, e.g. `run: B2_TARGETS=libs/$SELF/doc ci/build.sh`
|
|
# B2_TARGETS: libs/foo/test//bar
|
|
|
|
- name: Setup coverage collection
|
|
if: matrix.coverage
|
|
run: ci/github/codecov.sh "setup"
|
|
|
|
- name: Run tests
|
|
if: '!matrix.coverity'
|
|
run: ci/build.sh
|
|
# inherits environment from install.sh step
|
|
|
|
- name: Show config.log
|
|
if: always()
|
|
run: cat "$BOOST_ROOT/bin.v2/config.log" || true
|
|
|
|
- name: Collect coverage
|
|
if: matrix.coverage
|
|
run: ci/codecov.sh "collect"
|
|
|
|
- name: Upload coverage
|
|
if: matrix.coverage
|
|
uses: codecov/codecov-action@v5
|
|
with:
|
|
fail_ci_if_error: true
|
|
disable_search: true
|
|
files: coverage.info
|
|
name: ${{env.CODECOV_NAME}} (POSIX)
|
|
token: ${{secrets.CODECOV_TOKEN}}
|
|
verbose: true
|
|
|
|
- name: Run coverity
|
|
if: matrix.coverity && github.event_name == 'push' && (github.ref_name == 'develop' || github.ref_name == 'master')
|
|
run: ci/github/coverity.sh
|
|
env:
|
|
COVERITY_SCAN_NOTIFICATION_EMAIL: ${{ secrets.COVERITY_SCAN_NOTIFICATION_EMAIL }}
|
|
COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
|
|
|
generate-windows-matrix:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
|
|
|
steps:
|
|
- id: set-matrix
|
|
run: |
|
|
import json, os
|
|
|
|
all_jobs = [
|
|
{"toolset": "msvc-14.3", "cxxstd": "14,17,20,latest", "address-model": "32,64", "os": "windows-2022"},
|
|
{"toolset": "msvc-14.3", "cxxstd": "14,17,20,latest", "address-model": "64", "os": "windows-11-arm"},
|
|
{"name": "Collect coverage", "coverage": "yes",
|
|
"toolset": "msvc-14.3", "cxxstd": "latest", "address-model": "64", "os": "windows-2025"},
|
|
{"toolset": "clang-win", "cxxstd": "14,17,latest", "address-model": "32,64", "os": "windows-2025"},
|
|
{"toolset": "gcc", "cxxstd": "11,14,17,2a", "address-model": "64", "os": "windows-2022"},
|
|
{"toolset": "gcc", "cxxstd": "11,14,17,2a", "address-model": "32", "os": "windows-2025", "target-os": "cygwin"},
|
|
{"toolset": "gcc", "cxxstd": "11,14,17,2a", "address-model": "64", "os": "windows-2025", "target-os": "cygwin"},
|
|
]
|
|
|
|
def is_true(env_var):
|
|
return os.environ.get(env_var).lower() == 'true'
|
|
|
|
def filter_multi_valued(in_list, key_name, excluded):
|
|
"""Remove all entries from the value identified by key_name that are contained in excluded (comma-separated).
|
|
Omit the entry when the attribute is empty, keep it if the attribute is not present."""
|
|
excluded_values = {x.strip() for x in excluded.split(',')}
|
|
for entry in in_list:
|
|
try:
|
|
values = [x.strip() for x in entry[key_name].split(',')]
|
|
except KeyError:
|
|
yield entry
|
|
else:
|
|
remaining_values = [v for v in values if v and v not in excluded_values]
|
|
if remaining_values:
|
|
entry[key_name] = ",".join(remaining_values)
|
|
yield entry
|
|
|
|
def filter_os(in_list, excluded):
|
|
"""Remove all jobs that match any of the excluded OS (comma-separated, supports partial matches)"""
|
|
excluded_values = [v for v in (x.strip().replace('-', ':') for x in excluded.split(',')) if v]
|
|
return (job for job in in_list if not any(ev in job.get('container', job['os']).replace('-', ':') for ev in excluded_values))
|
|
|
|
def filter_yes_values(in_list, key_name):
|
|
"""Remove all entries with value 'yes' for the key"""
|
|
return (e for e in in_list if not e.get(key_name) == "yes")
|
|
|
|
filtered = all_jobs
|
|
filtered = filter_multi_valued(filtered, 'cxxstd', os.environ['EXCLUDE_CXXSTD'])
|
|
filtered = filter_multi_valued(filtered, 'toolset', os.environ['EXCLUDE_COMPILER'])
|
|
filtered = filter_os(filtered, os.environ['EXCLUDE_OS'])
|
|
if not is_true('ENABLE_32BIT'):
|
|
filtered = filter_multi_valued(filtered, 'address-model', '32')
|
|
if not is_true('ENABLE_CYGWIN'):
|
|
filtered = filter_multi_valued(filtered, 'target-os', 'cygwin')
|
|
|
|
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
|
|
print(f"matrix={json.dumps({'include': list(filtered)})}", file=fh)
|
|
shell: python
|
|
env:
|
|
ENABLE_32BIT: ${{ inputs.enable_32bit }}
|
|
ENABLE_CYGWIN: ${{ inputs.enable_cygwin }}
|
|
EXCLUDE_CXXSTD: ${{ inputs.exclude_cxxstd }}
|
|
EXCLUDE_COMPILER: ${{ inputs.exclude_compiler }}
|
|
EXCLUDE_OS: ${{ inputs.exclude_os }}
|
|
|
|
windows:
|
|
if: ${{ inputs.enable_windows }}
|
|
needs: generate-windows-matrix
|
|
runs-on: ${{matrix.os}}
|
|
timeout-minutes: 120
|
|
|
|
defaults:
|
|
run:
|
|
shell: cmd
|
|
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{fromJson(needs.generate-windows-matrix.outputs.matrix)}}
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Fetch Boost.CI
|
|
uses: actions/checkout@v4
|
|
with:
|
|
repository: boostorg/boost-ci
|
|
ref: master
|
|
path: boost-ci-cloned
|
|
- name: Get CI scripts folder
|
|
run: |
|
|
REM Copy ci folder if not testing Boost.CI
|
|
if "%GITHUB_REPOSITORY%" == "%GITHUB_REPOSITORY:boost-ci=%" xcopy /s /e /q /i /y boost-ci-cloned\ci .\ci
|
|
rmdir /s /q boost-ci-cloned
|
|
|
|
- name: Setup cygwin
|
|
if: ${{ matrix.target-os == 'cygwin' }}
|
|
uses: cygwin/cygwin-install-action@v6
|
|
with:
|
|
packages: coreutils, gcc-g++, libstdc++6, make, moreutils, openssl, libbz2-devel, libgmp-devel, libicu-devel, libjpeg-devel, libmpfr-devel, libpng-devel, libssl-devel, libtiff-devel, libxslt-devel, libzstd-devel
|
|
platform: ${{ matrix.address-model == '64' && 'x86_64' || 'x86' }}
|
|
|
|
- name: Setup Boost
|
|
run: ci\github\install.bat
|
|
env:
|
|
B2_TOOLSET: ${{matrix.toolset}}
|
|
|
|
- name: Run tests
|
|
if: '!matrix.coverage'
|
|
run: ci\build.bat
|
|
env:
|
|
B2_TOOLSET: ${{matrix.toolset}}
|
|
B2_TARGET_OS: ${{matrix.target-os}}
|
|
B2_CXXSTD: ${{matrix.cxxstd}}
|
|
B2_ADDRESS_MODEL: ${{matrix.address-model}}
|
|
B2_DEFINES: ${{matrix.defines}}
|
|
B2_VARIANT: ${{matrix.variant}}
|
|
B2_LINK: ${{matrix.link}}
|
|
|
|
- name: Collect coverage
|
|
shell: powershell
|
|
if: matrix.coverage
|
|
run: ci\opencppcoverage.ps1
|
|
env:
|
|
B2_TOOLSET: ${{matrix.toolset}}
|
|
B2_CXXSTD: ${{matrix.cxxstd}}
|
|
B2_ADDRESS_MODEL: ${{matrix.address-model}}
|
|
B2_DEFINES: ${{matrix.defines}}
|
|
B2_VARIANT: ${{matrix.variant}}
|
|
B2_LINK: ${{matrix.link}}
|
|
|
|
- name: Upload coverage
|
|
if: matrix.coverage
|
|
uses: codecov/codecov-action@v5
|
|
with:
|
|
disable_search: true
|
|
files: __out/cobertura.xml
|
|
name: ${{env.CODECOV_NAME}} (Windows)
|
|
token: ${{secrets.CODECOV_TOKEN}}
|
|
verbose: true
|
|
|
|
generate-mingw-matrix:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
|
steps:
|
|
- id: set-matrix
|
|
run: |
|
|
import json, os
|
|
|
|
all_jobs = [
|
|
{"sys": "MINGW32", "compiler": "gcc", "cxxstd": "11,17,20"},
|
|
{"sys": "MINGW64", "compiler": "gcc", "cxxstd": "11,17,20"}
|
|
]
|
|
|
|
def is_true(env_var):
|
|
return os.environ.get(env_var).lower() == 'true'
|
|
|
|
def filter_multi_valued(in_list, key_name, excluded):
|
|
"""Remove all entries from the value identified by key_name that are contained in excluded (comma-separated).
|
|
Omit the entry when the attribute is empty, keep it if the attribute is not present."""
|
|
excluded_values = {x.strip() for x in excluded.split(',')}
|
|
for entry in in_list:
|
|
try:
|
|
values = [x.strip() for x in entry[key_name].split(',')]
|
|
except KeyError:
|
|
yield entry
|
|
else:
|
|
remaining_values = [v for v in values if v and v not in excluded_values]
|
|
if remaining_values:
|
|
entry[key_name] = ",".join(remaining_values)
|
|
yield entry
|
|
|
|
def filter_os(in_list, excluded):
|
|
"""Remove all jobs that match any of the excluded OS (comma-separated, supports partial matches)"""
|
|
excluded_values = [v for v in (x.strip().replace('-', ':') for x in excluded.split(',')) if v]
|
|
return (job for job in in_list if not any(ev in job['sys'] for ev in excluded_values))
|
|
|
|
def filter_yes_values(in_list, key_name):
|
|
"""Remove all entries with value 'yes' for the key"""
|
|
return (e for e in in_list if not e.get(key_name) == "yes")
|
|
|
|
filtered = all_jobs
|
|
filtered = filter_multi_valued(filtered, 'cxxstd', os.environ['EXCLUDE_CXXSTD'])
|
|
if not is_true('ENABLE_32BIT'):
|
|
filtered = filter_multi_valued(filtered, 'sys', 'MINGW32')
|
|
|
|
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
|
|
print(f"matrix={json.dumps({'include': list(filtered)})}", file=fh)
|
|
shell: python
|
|
env:
|
|
ENABLE_32BIT: ${{ inputs.enable_32bit }}
|
|
EXCLUDE_CXXSTD: ${{ inputs.exclude_cxxstd }}
|
|
|
|
mingw:
|
|
if: ${{ inputs.enable_mingw }}
|
|
needs: generate-mingw-matrix
|
|
runs-on: windows-latest
|
|
timeout-minutes: 120
|
|
|
|
defaults:
|
|
run:
|
|
shell: msys2 {0}
|
|
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{fromJson(needs.generate-mingw-matrix.outputs.matrix)}}
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Setup MSYS2 environment for MinGW
|
|
uses: msys2/setup-msys2@v2
|
|
with:
|
|
msystem: ${{matrix.sys}}
|
|
update: true
|
|
install: git python
|
|
pacboy: gcc:p cmake:p ninja:p
|
|
|
|
- name: Fetch Boost.CI
|
|
uses: actions/checkout@v4
|
|
with:
|
|
repository: boostorg/boost-ci
|
|
ref: master
|
|
path: boost-ci-cloned
|
|
- name: Get CI scripts folder
|
|
run: |
|
|
# Copy ci folder if not testing Boost.CI
|
|
[[ "$GITHUB_REPOSITORY" =~ "boost-ci" ]] || cp -r boost-ci-cloned/ci .
|
|
rm -rf boost-ci-cloned
|
|
|
|
- name: Setup Boost
|
|
run: ci/github/install.sh
|
|
env:
|
|
B2_COMPILER: ${{matrix.compiler}}
|
|
B2_CXXSTD: ${{matrix.cxxstd}}
|
|
B2_SANITIZE: ${{matrix.sanitize}}
|
|
B2_STDLIB: ${{matrix.stdlib}}
|
|
B2_DEFINES: ${{matrix.defines}}
|
|
B2_VARIANT: ${{matrix.variant}}
|
|
B2_LINK: ${{matrix.link}}
|
|
|
|
- name: Run tests
|
|
run: ci/build.sh
|
|
# inherits environment from install.sh step
|
|
|
|
# Run the CMake tests to avoid having to setup another matrix for CMake on MSYS
|
|
- name: Run CMake tests
|
|
if: ${{ inputs.enable_cmake }}
|
|
run: |
|
|
cd "$BOOST_ROOT"
|
|
mkdir __build_cmake_test__ && cd __build_cmake_test__
|
|
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DBOOST_INCLUDE_LIBRARIES=$SELF -DBUILD_SHARED_LIBS=ON -DBUILD_TESTING=ON -DBoost_VERBOSE=ON ..
|
|
cmake --build . --target tests --config Debug -j$B2_JOBS
|
|
ctest --output-on-failure --build-config Debug
|
|
|
|
cmake:
|
|
if: ${{ inputs.enable_cmake }}
|
|
runs-on: ${{matrix.os}}
|
|
timeout-minutes: 120
|
|
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- { os: ubuntu-latest, build_shared: ON, build_type: Debug, generator: 'Unix Makefiles' }
|
|
- { os: ubuntu-latest, build_shared: OFF, build_type: Debug, generator: 'Unix Makefiles' }
|
|
- { os: windows-2025, build_shared: ON, build_type: Debug, generator: 'Visual Studio 17 2022' }
|
|
- { os: windows-2025, build_shared: OFF, build_type: Debug, generator: 'Visual Studio 17 2022' }
|
|
- { name: "Min. CMake", cmake_version: '${{inputs.min_cmake_version}}',
|
|
os: ubuntu-latest, build_shared: ON, build_type: Debug, generator: 'Unix Makefiles' }
|
|
|
|
steps:
|
|
- name: Cache CMake
|
|
if: matrix.cmake_version
|
|
id: cache-cmake
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: /tmp/cmake
|
|
key: ${{runner.os}}-cmake-${{matrix.cmake_version}}
|
|
|
|
- name: Install CMake dependencies
|
|
if: matrix.cmake_version
|
|
run: |
|
|
sudo apt-get -o Acquire::Retries=3 -y -q --no-install-suggests --no-install-recommends install curl libcurl4-openssl-dev libarchive-dev
|
|
echo /tmp/cmake/bin >> $GITHUB_PATH
|
|
|
|
- name: Build CMake
|
|
if: matrix.cmake_version && steps.cache-cmake.outputs.cache-hit != 'true'
|
|
run: |
|
|
version=${{matrix.cmake_version}}
|
|
[[ ${version} =~ [0-9]+\.[0-9]+\.[0-9]+ ]] || version+=".0"
|
|
filename="cmake-$version.tar.gz"
|
|
cd "$(mktemp -d)"
|
|
wget https://cmake.org/files/v${version%.*}/$filename
|
|
tar -xf $filename --strip-components=1
|
|
flags=(
|
|
"-DCMAKE_BUILD_TYPE=Release"
|
|
"-DCMAKE_INSTALL_PREFIX=/tmp/cmake"
|
|
"-B" "__build"
|
|
"-Wno-dev" # Make configuring more silent
|
|
"-DCMAKE_USE_SYSTEM_CURL=1" # Avoid failures caused by newer (system) OpenSSL in CMake < 3.10
|
|
"-DCMAKE_CXX_FLAGS='-include cstdint -include limits'" # Fix missing includes in CMake < 3.10
|
|
)
|
|
cmake "${flags[@]}" .
|
|
cmake --build __build -- -j 3
|
|
cmake --build __build --target install
|
|
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Cache ccache
|
|
uses: hendrikmuhs/ccache-action@v1.2
|
|
if: runner.os == 'Linux'
|
|
with:
|
|
create-symlink: true
|
|
key: ${{matrix.os}}-${{matrix.build_shared}}
|
|
|
|
- name: Fetch Boost.CI
|
|
uses: actions/checkout@v4
|
|
with:
|
|
repository: boostorg/boost-ci
|
|
ref: master
|
|
path: boost-ci-cloned
|
|
|
|
- name: Get CI scripts folder
|
|
run: |
|
|
# Copy ci folder if not testing Boost.CI
|
|
[[ "$GITHUB_REPOSITORY" =~ "boost-ci" ]] || cp -r boost-ci-cloned/ci .
|
|
rm -rf boost-ci-cloned
|
|
|
|
- name: Setup Boost
|
|
run: source ci/github/install.sh
|
|
env: {B2_DONT_BOOTSTRAP: 1}
|
|
|
|
- name: Run CMake tests
|
|
run: |
|
|
cd "$BOOST_ROOT"
|
|
mkdir __build_cmake_test__ && cd __build_cmake_test__
|
|
cmake -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DBOOST_INCLUDE_LIBRARIES=$SELF -DBUILD_SHARED_LIBS=${{matrix.build_shared}} -DBUILD_TESTING=ON -DBoost_VERBOSE=ON ..
|
|
cmake --build . --target tests --config ${{matrix.build_type}} -j$B2_JOBS
|
|
ctest --output-on-failure --build-config ${{matrix.build_type}}
|
|
|
|
- name: Run CMake subdir tests
|
|
run: |
|
|
cmake_test_folder="$BOOST_ROOT/libs/$SELF/test/cmake_test" # New unified folder
|
|
[ -d "$cmake_test_folder" ] || cmake_test_folder="$BOOST_ROOT/libs/$SELF/test/cmake_subdir_test"
|
|
cd "$cmake_test_folder"
|
|
mkdir __build_cmake_subdir_test__ && cd __build_cmake_subdir_test__
|
|
extra_args=""
|
|
# On Windows DLLs need to be either in PATH or in the same folder as the executable, so put all binaries into the same folder
|
|
if [[ "$RUNNER_OS" == "Windows" ]] && [[ "${{matrix.build_shared}}" == "ON" ]]; then
|
|
extra_args="-DCMAKE_RUNTIME_OUTPUT_DIRECTORY='$(pwd)/bin'"
|
|
fi
|
|
cmake -G "${{matrix.generator}}" -DBOOST_CI_INSTALL_TEST=OFF -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DBUILD_SHARED_LIBS=${{matrix.build_shared}} $extra_args ..
|
|
cmake --build . --config ${{matrix.build_type}} -j$B2_JOBS
|
|
ctest --output-on-failure --build-config ${{matrix.build_type}}
|
|
|
|
- name: Install Library
|
|
run: |
|
|
BCM_INSTALL_PATH=/tmp/boost_install
|
|
echo "BCM_INSTALL_PATH=$BCM_INSTALL_PATH" >> $GITHUB_ENV
|
|
cd "$BOOST_ROOT"
|
|
mkdir __build_cmake_install_test__ && cd __build_cmake_install_test__
|
|
cmake -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DBOOST_INCLUDE_LIBRARIES=$SELF -DBUILD_SHARED_LIBS=${{matrix.build_shared}} -DCMAKE_INSTALL_PREFIX="$BCM_INSTALL_PATH" -DBoost_VERBOSE=ON -DBoost_DEBUG=ON ..
|
|
cmake --build . --target install --config ${{matrix.build_type}} -j$B2_JOBS
|
|
- name: Run CMake install tests
|
|
run: |
|
|
cmake_test_folder="$BOOST_ROOT/libs/$SELF/test/cmake_test" # New unified folder
|
|
[ -d "$cmake_test_folder" ] || cmake_test_folder="$BOOST_ROOT/libs/$SELF/test/cmake_install_test"
|
|
cd "$cmake_test_folder"
|
|
mkdir __build_cmake_install_test__ && cd __build_cmake_install_test__
|
|
cmake -G "${{matrix.generator}}" -DBOOST_CI_INSTALL_TEST=ON -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DBUILD_SHARED_LIBS=${{matrix.build_shared}} -DCMAKE_PREFIX_PATH="$BCM_INSTALL_PATH" ..
|
|
cmake --build . --config ${{matrix.build_type}} -j$B2_JOBS
|
|
if [[ "${{matrix.build_shared}}" == "ON" ]]; then
|
|
# Make sure shared libs can be found at runtime
|
|
if [ "$RUNNER_OS" == "Windows" ]; then
|
|
export PATH="$BCM_INSTALL_PATH/bin:$PATH"
|
|
else
|
|
export LD_LIBRARY_PATH="$BCM_INSTALL_PATH/lib:$LD_LIBRARY_PATH"
|
|
fi
|
|
fi
|
|
ctest --output-on-failure --build-config ${{matrix.build_type}}
|