diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 4d9725b..ad4f5f6 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -6,86 +6,88 @@ on: pull_request: branches: [ main, develop ] +# Compilers come from the runner images only. Pinning the OS pins the compiler +# set, which keeps an upstream repository change from breaking a required gate. +# +# The lower bounds do not line up across compilers. GCC is verified from 13 on +# ubuntu-24.04, but Clang starts at 20 on ubuntu-26.04: older Clang releases +# cannot build this library's C++23 usage against the libstdc++ they are paired +# with on ubuntu-24.04. Both are verified up to what ubuntu-26.04 provides. + jobs: build-ubuntu-gcc: - name: Ubuntu GCC Build - runs-on: ubuntu-latest + name: Ubuntu GCC ${{ matrix.toolchain.gcc }} (${{ matrix.build_type }}) + runs-on: ${{ matrix.toolchain.os }} strategy: + fail-fast: false matrix: build_type: [Debug, Release] - gcc_version: [13, 14] + toolchain: + - { os: ubuntu-24.04, gcc: 13 } + - { os: ubuntu-26.04, gcc: 15 } steps: - uses: actions/checkout@v7 - - name: Install dependencies and GCC ${{ matrix.gcc_version }} + - name: Report toolchain versions run: | - sudo apt-get update - sudo apt-get install -y cmake build-essential software-properties-common - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update - sudo apt-get install -y gcc-${{ matrix.gcc_version }} g++-${{ matrix.gcc_version }} + gcc-${{ matrix.toolchain.gcc }} --version + cmake --version - name: Configure CMake run: | cmake -S . -B build \ -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ - -DCMAKE_C_COMPILER=gcc-${{ matrix.gcc_version }} \ - -DCMAKE_CXX_COMPILER=g++-${{ matrix.gcc_version }} + -DCMAKE_C_COMPILER=gcc-${{ matrix.toolchain.gcc }} \ + -DCMAKE_CXX_COMPILER=g++-${{ matrix.toolchain.gcc }} - name: Build - run: cmake --build build --config ${{ matrix.build_type }} -j$(nproc) + run: cmake --build build --config ${{ matrix.build_type }} -j"$(nproc)" - name: Test run: ./build/test/dross_test --gtest_color=yes build-ubuntu-clang: - name: Ubuntu Clang Build - runs-on: ubuntu-latest + name: Ubuntu Clang ${{ matrix.toolchain.clang }} (${{ matrix.build_type }}) + runs-on: ${{ matrix.toolchain.os }} strategy: + fail-fast: false matrix: build_type: [Debug, Release] - clang_version: [17, 18] + toolchain: + - { os: ubuntu-26.04, clang: 20 } + - { os: ubuntu-26.04, clang: 22 } steps: - uses: actions/checkout@v7 - - name: Install dependencies and Clang ${{ matrix.clang_version }} + - name: Report toolchain versions run: | - sudo apt-get update - sudo apt-get install -y cmake build-essential - wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc - echo "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-${{ matrix.clang_version }} main" | sudo tee /etc/apt/sources.list.d/llvm.list - sudo apt-get update - sudo apt-get install -y clang-${{ matrix.clang_version }} libc++-${{ matrix.clang_version }}-dev libc++abi-${{ matrix.clang_version }}-dev + clang-${{ matrix.toolchain.clang }} --version + cmake --version + # No -stdlib override: the default standard library is what most Clang + # users on Linux build against. - name: Configure CMake run: | cmake -S . -B build \ -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ - -DCMAKE_C_COMPILER=clang-${{ matrix.clang_version }} \ - -DCMAKE_CXX_COMPILER=clang++-${{ matrix.clang_version }} \ - -DCMAKE_CXX_FLAGS="-stdlib=libc++" \ - -DCMAKE_EXE_LINKER_FLAGS="-stdlib=libc++" + -DCMAKE_C_COMPILER=clang-${{ matrix.toolchain.clang }} \ + -DCMAKE_CXX_COMPILER=clang++-${{ matrix.toolchain.clang }} - name: Build - run: cmake --build build --config ${{ matrix.build_type }} -j$(nproc) + run: cmake --build build --config ${{ matrix.build_type }} -j"$(nproc)" - name: Test run: ./build/test/dross_test --gtest_color=yes build-static-library: name: Static Library Build - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v7 - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y cmake build-essential - - name: Configure CMake (Static) run: | cmake -S . -B build \ @@ -93,27 +95,27 @@ jobs: -DBUILD_SHARED_LIBS=OFF - name: Build - run: cmake --build build -j$(nproc) + run: cmake --build build -j"$(nproc)" - name: Test run: ./build/test/dross_test --gtest_color=yes install-test: name: Installation Test - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v7 - - name: Install dependencies + - name: Report toolchain versions run: | - sudo apt-get update - sudo apt-get install -y cmake build-essential pkg-config + cmake --version + pkg-config --version - name: Build and Install run: | cmake -S . -B build -DCMAKE_BUILD_TYPE=Release - cmake --build build -j$(nproc) + cmake --build build -j"$(nproc)" sudo cmake --install build - name: Test find_package diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 23599b6..1cb3fe8 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -6,22 +6,28 @@ on: pull_request: branches: [ main, develop ] +# macOS users build with the Apple Clang that ships with the OS, so the OS +# generation is the axis worth varying: pinning to the two current releases +# covers two Apple Clang generations without a separate compiler axis. + jobs: build-macos-clang: - name: macOS Clang Build + name: macOS Clang (${{ matrix.os }}, ${{ matrix.build_type }}) runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: - os: [macos-14, macos-15] + os: [macos-15, macos-26] build_type: [Debug, Release] steps: - uses: actions/checkout@v7 - - name: Install dependencies + - name: Report toolchain versions run: | - brew update - brew install cmake + clang --version + xcrun --show-sdk-version + cmake --version - name: Configure CMake run: | @@ -29,62 +35,18 @@ jobs: -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} - name: Build - run: cmake --build build --config ${{ matrix.build_type }} -j$(sysctl -n hw.ncpu) - - - name: Test - run: ./build/test/dross_test --gtest_color=yes - - build-macos-gcc: - name: macOS GCC Build - runs-on: macos-latest - strategy: - matrix: - build_type: [Debug, Release] - gcc_version: [13, 14] - - steps: - - uses: actions/checkout@v7 - - - name: Install dependencies and GCC ${{ matrix.gcc_version }} - run: | - brew update - brew install cmake gcc@${{ matrix.gcc_version }} - - - name: Configure CMake - run: | - # Find GCC path (different for Intel and Apple Silicon) - if [ -x "/usr/local/bin/gcc-${{ matrix.gcc_version }}" ]; then - GCC_PATH="/usr/local/bin" - elif [ -x "/opt/homebrew/bin/gcc-${{ matrix.gcc_version }}" ]; then - GCC_PATH="/opt/homebrew/bin" - else - echo "GCC ${{ matrix.gcc_version }} not found" - exit 1 - fi - - cmake -S . -B build \ - -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ - -DCMAKE_C_COMPILER=$GCC_PATH/gcc-${{ matrix.gcc_version }} \ - -DCMAKE_CXX_COMPILER=$GCC_PATH/g++-${{ matrix.gcc_version }} - - - name: Build - run: cmake --build build --config ${{ matrix.build_type }} -j$(sysctl -n hw.ncpu) + run: cmake --build build --config ${{ matrix.build_type }} -j"$(sysctl -n hw.ncpu)" - name: Test run: ./build/test/dross_test --gtest_color=yes build-static-library: name: macOS Static Library Build - runs-on: macos-latest + runs-on: macos-15 steps: - uses: actions/checkout@v7 - - name: Install dependencies - run: | - brew update - brew install cmake - - name: Configure CMake (Static) run: | cmake -S . -B build \ @@ -92,27 +54,27 @@ jobs: -DBUILD_SHARED_LIBS=OFF - name: Build - run: cmake --build build -j$(sysctl -n hw.ncpu) + run: cmake --build build -j"$(sysctl -n hw.ncpu)" - name: Test run: ./build/test/dross_test --gtest_color=yes install-test: name: macOS Installation Test - runs-on: macos-latest + runs-on: macos-15 steps: - uses: actions/checkout@v7 - - name: Install dependencies + - name: Report toolchain versions run: | - brew update - brew install cmake pkg-config + cmake --version + pkg-config --version - name: Build and Install run: | cmake -S . -B build -DCMAKE_BUILD_TYPE=Release - cmake --build build -j$(sysctl -n hw.ncpu) + cmake --build build -j"$(sysctl -n hw.ncpu)" sudo cmake --install build - name: Test find_package diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml new file mode 100644 index 0000000..811f001 --- /dev/null +++ b/.github/workflows/nightly.yml @@ -0,0 +1,160 @@ +name: Nightly Toolchain Watch + +on: + schedule: + # 03:00 UTC daily + - cron: '0 3 * * *' + workflow_dispatch: + +# Early warning for environments outside the verified range: the newest +# compilers and the floating runner labels. These jobs deliberately use the +# wiring the required gates avoid — floating OS labels and compilers from +# external repositories — because breaking here is the signal we want, ahead +# of users hitting it. They never gate a pull request and must not be added to +# required status checks. + +jobs: + newest-gcc: + name: Newest GCC + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v7 + + # Resolve the newest versioned g++ available once the toolchain PPA is in + # place, rather than pinning a major, so this keeps tracking upstream + # without edits. + - name: Install newest GCC + run: | + sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y + sudo apt-get update + version=$(apt-cache search --names-only '^g\+\+-[0-9]+$' \ + | sed 's/^g++-//; s/ .*//' | sort -n | tail -1) + if [ -z "$version" ]; then + echo "No versioned g++ package found in the toolchain PPA" >&2 + exit 1 + fi + sudo apt-get install -y "gcc-$version" "g++-$version" + echo "GCC_VERSION=$version" >> "$GITHUB_ENV" + + - name: Report toolchain versions + run: | + gcc-"$GCC_VERSION" --version + cmake --version + + - name: Configure CMake + run: | + cmake -S . -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_C_COMPILER=gcc-"$GCC_VERSION" \ + -DCMAKE_CXX_COMPILER=g++-"$GCC_VERSION" + + - name: Build + run: cmake --build build -j"$(nproc)" + + - name: Test + run: ./build/test/dross_test --gtest_color=yes + + newest-clang: + name: Newest Clang + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v7 + + # llvm.sh adds the apt.llvm.org repository for the current stable release, + # then we take the newest versioned clang package available. Tracking the + # stable release rather than trunk (llvm.sh all) is deliberate: this watches + # what users will actually reach for, not what is still in development. + - name: Install newest Clang + run: | + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh + version=$(apt-cache search --names-only '^clang-[0-9]+$' \ + | sed 's/^clang-//; s/ .*//' | sort -n | tail -1) + if [ -z "$version" ]; then + echo "No versioned clang package found in the apt.llvm.org repository" >&2 + exit 1 + fi + sudo apt-get install -y "clang-$version" + echo "CLANG_VERSION=$version" >> "$GITHUB_ENV" + + - name: Report toolchain versions + run: | + clang-"$CLANG_VERSION" --version + cmake --version + + - name: Configure CMake + run: | + cmake -S . -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_C_COMPILER=clang-"$CLANG_VERSION" \ + -DCMAKE_CXX_COMPILER=clang++-"$CLANG_VERSION" + + - name: Build + run: cmake --build build -j"$(nproc)" + + - name: Test + run: ./build/test/dross_test --gtest_color=yes + + # The required gates build Clang against the default standard library. + # This covers the other choice, so neither ends up being the only one that + # works. + libcxx: + name: Clang with libc++ + runs-on: ubuntu-26.04 + + steps: + - uses: actions/checkout@v7 + + - name: Install libc++ + run: | + sudo apt-get update + sudo apt-get install -y libc++-20-dev libc++abi-20-dev + + - name: Report toolchain versions + run: | + clang-20 --version + cmake --version + + - name: Configure CMake + run: | + cmake -S . -B build \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_C_COMPILER=clang-20 \ + -DCMAKE_CXX_COMPILER=clang++-20 \ + -DCMAKE_CXX_FLAGS="-stdlib=libc++" \ + -DCMAKE_EXE_LINKER_FLAGS="-stdlib=libc++" + + - name: Build + run: cmake --build build -j"$(nproc)" + + - name: Test + run: ./build/test/dross_test --gtest_color=yes + + floating-runners: + name: Floating Runner (${{ matrix.os }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + + steps: + - uses: actions/checkout@v7 + + - name: Report toolchain versions + run: | + cc --version + cmake --version + + - name: Configure CMake + run: | + cmake -S . -B build -DCMAKE_BUILD_TYPE=Release + + - name: Build + run: cmake --build build --parallel + + - name: Test + run: ./build/test/dross_test --gtest_color=yes diff --git a/README.md b/README.md index 33b88f5..19713f2 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,10 @@ ### Requirements -- **C++23** compatible compiler (GCC 13+, Clang 17+, MSVC 2022+) +- **C++23** compatible compiler, verified in CI as: + - Linux: GCC 13–15 or Clang 20–22 + - macOS: the Apple Clang shipped with macOS 15 or 26 + - Newer versions are best effort, exercised by the nightly toolchain watch - **CMake 3.20+** ### Installation diff --git a/docs/sphinx/source/contributing.rst b/docs/sphinx/source/contributing.rst index ff41c57..c4c0fa9 100644 --- a/docs/sphinx/source/contributing.rst +++ b/docs/sphinx/source/contributing.rst @@ -33,7 +33,8 @@ Development Setup Build Requirements ~~~~~~~~~~~~~~~~~~ -- C++23 compatible compiler (GCC 13+, Clang 16+, MSVC 2022+) +- C++23 compatible compiler: on Linux, GCC 13-15 or Clang 20-22; on macOS, + the Apple Clang shipped with macOS 15 or 26. Newer versions are best effort. - CMake 3.20 or later - Git diff --git a/docs/sphinx/source/getting-started.rst b/docs/sphinx/source/getting-started.rst index 3d965a9..731e801 100644 --- a/docs/sphinx/source/getting-started.rst +++ b/docs/sphinx/source/getting-started.rst @@ -9,13 +9,21 @@ System Requirements To build and use dross, you need: - **C++ Compiler**: Supporting C++23 standard - - - GCC 13 or later - - Clang 16 or later (with libc++ for full C++23 support) - - MSVC 2022 or later + + - On Linux: GCC 13 through 15, or Clang 20 through 22 + - On macOS: the Apple Clang shipped with macOS 15 or 26 + + Newer versions are best effort: they are exercised by the nightly toolchain + watch rather than by the required build matrix. + + The Clang lower bound is higher than the GCC one because older Clang + releases cannot compile this library's C++23 ``std::expected`` usage against + the libstdc++ they are paired with on Ubuntu 24.04, whether or not newer + libstdc++ headers are installed alongside. Either standard library works + from Clang 20 onwards, so neither is imposed. - **Build System**: CMake 3.20 or later -- **Operating System**: Linux, macOS, Windows, or any POSIX-compliant system +- **Operating System**: Linux or macOS Installation ------------