From 98d0b761b2183a500c3d536ef27fa4ccf879b596 Mon Sep 17 00:00:00 2001 From: Ian Petersen Date: Sun, 30 Aug 2026 17:27:25 -0700 Subject: [PATCH] ci: build modules with Clang 23 only; document modular-build support Clang's module-serialization ICE (a crash inside ASTReader::readTypeRecord / FunctionProtoType::Profile while deserializing from a BMI) makes the modular build unreliable on Clang 22. It reproduces on every released 22.1.x, including 22.1.8, which is the last planned 22.1.x release, so no released Clang 22 will ever build the modular tests. Which translation unit crashes is not stable -- it shifts with incidental state such as the build environment or unrelated source changes -- so an unrelated contribution can fail CI for reasons that have nothing to do with it, and the exclusion list cannot be made reliable by adding entries to it. The crash is gone in Clang 23.1.0. Move the modular CI job to Clang 23, declare Clang 23 the supported toolchain for modular builds in the README, and drop the ICE exclusion list: those tests all build once the compiler is fixed. rapidsai/devcontainers does not publish an llvm23 image yet, so the job installs Clang 23 from apt.llvm.org on top of the llvm22 image. The install step no-ops once the image tag matches the requested LLVM version, so de-hacking is a two-line matrix change. test/stdexec/detail/test_any_allocator.cpp stays excluded in modules mode for an unrelated, stdexec-side reason: __any_allocator is reachable but not exported from the stdexec module. --- .github/workflows/ci.cpu.yml | 35 +++++++++++++++++++++++++++++++---- README.md | 9 +++++++++ test/CMakeLists.txt | 18 ++++++------------ 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.cpu.yml b/.github/workflows/ci.cpu.yml index 24c6cc5df..20906c70c 100644 --- a/.github/workflows/ci.cpu.yml +++ b/.github/workflows/ci.cpu.yml @@ -25,8 +25,13 @@ jobs: - { name: "CPU (clang 16, Release)", build: "Release", tag: llvm16-cuda12.9, cxxstd: "20", cxxflags: "-stdlib=libc++" } - { name: "CPU (clang 16, Release, ASAN)", build: "Release", tag: llvm16-cuda12.9, cxxstd: "20", cxxflags: "-stdlib=libc++ -fsanitize=address -fsanitize-ignorelist=/home/coder/stdexec/sanitizer-ignorelist.txt" } - { name: "CPU (clang 22, Debug)", build: "Debug", tag: llvm22-cuda13.2, cxxstd: "23", cxxflags: "-stdlib=libc++" } - # Reenable this with clang-23 once we get it working in CI - # - { name: "CPU (clang 22, Debug, modules)", build: "Debug", tag: llvm22-cuda13.2, cxxstd: "23", cxxflags: "-stdlib=libc++" } + # Clang 23 is the only supported toolchain for modular builds (see + # "Modular builds" in the README). rapidsai/devcontainers does not + # publish an llvm23 image yet, so this job installs Clang 23 from + # apt.llvm.org on top of the llvm22 image. To de-hack once the image + # exists: drop `llvm: "23"` and set tag: llvm23-cuda13.2 -- the + # install step below then no-ops. + - { name: "CPU (clang 23, Debug, modules)", build: "Debug", tag: llvm22-cuda13.2, llvm: "23", cxxstd: "23", cxxflags: "-stdlib=libc++" } - { name: "CPU (clang 22, Release)", build: "Release", tag: llvm22-cuda13.2, cxxstd: "23", cxxflags: "-stdlib=libc++" } - { name: "CPU (clang 22, Release, noexcept)", build: "Release", tag: llvm22-cuda13.2, cxxstd: "23", cxxflags: "-stdlib=libc++ -fno-exceptions" } - { name: "CPU (gcc 12, Debug)", build: "Debug", tag: gcc12-cuda12.9, cxxstd: "20", cxxflags: "", } @@ -61,8 +66,29 @@ jobs: persist-credentials: false - name: Setup environment run: | - echo "ARTIFACT_PREFIX=${{runner.os}}-${{matrix.tag}}-amd64" >> "${GITHUB_ENV}" + echo "ARTIFACT_PREFIX=${{runner.os}}-${{matrix.tag}}${{ matrix.llvm && format('-llvm{0}', matrix.llvm) || '' }}-amd64" >> "${GITHUB_ENV}" echo "ARTIFACT_SUFFIX=${{github.run_id}}-${{github.run_attempt}}-$RANDOM" >> "${GITHUB_ENV}" + - if: ${{ matrix.llvm != '' && !startsWith(matrix.tag, format('llvm{0}-', matrix.llvm)) }} + name: Install Clang ${{ matrix.llvm }} from apt.llvm.org + # Runs as root: the workflow default shell (`su coder`) is overridden. + shell: bash + run: | + set -ex + . /etc/os-release + curl -fsSL https://apt.llvm.org/llvm-snapshot.gpg.key \ + -o /etc/apt/trusted.gpg.d/apt-llvm.asc + echo "deb http://apt.llvm.org/${VERSION_CODENAME}/ llvm-toolchain-${VERSION_CODENAME}-${{ matrix.llvm }} main" \ + > /etc/apt/sources.list.d/llvm-${{ matrix.llvm }}.list + apt-get update + # NB: libc++-N-dev Conflicts with the image's libc++-22-dev and will + # replace it. That is fine here -- this job builds only with Clang + # ${{ matrix.llvm }} -- but it is why this cannot be a shared setup step. + apt-get install -y --no-install-recommends \ + clang-${{ matrix.llvm }} \ + libc++-${{ matrix.llvm }}-dev \ + libc++abi-${{ matrix.llvm }}-dev + /usr/lib/llvm-${{ matrix.llvm }}/bin/clang++ --version + - if: github.repository_owner == 'NVIDIA' name: Get AWS credentials for sccache bucket uses: aws-actions/configure-aws-credentials@v4 @@ -121,7 +147,8 @@ jobs: -DSTDEXEC_BUILD_TESTS:BOOL=ON \ -DSTDEXEC_BUILD_EXAMPLES:BOOL=${{ !contains(matrix.name, 'modules') }} \ -DSTDEXEC_BUILD_MODULES:BOOL=${{ contains(matrix.name, 'modules') }} \ - -DCMAKE_CXX_STDLIB_MODULES_JSON=/usr/lib/llvm-22/lib/libc++.modules.json \ + ${{ matrix.llvm && format('-DCMAKE_CXX_COMPILER=/usr/lib/llvm-{0}/bin/clang++', matrix.llvm) || '' }} \ + -DCMAKE_CXX_STDLIB_MODULES_JSON=/usr/lib/llvm-${{ matrix.llvm || '22' }}/lib/libc++.modules.json \ ; # Compile diff --git a/README.md b/README.md index aa7cafbc1..27b8c57e0 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,15 @@ Requires `-std=c++20` or later. > [!NOTE] > `stdexec` does not yet support NVIDIA's `nvcc` compiler. +### Modular builds + +Building `stdexec` as a C++20 module (`-DSTDEXEC_BUILD_MODULES=ON`) is supported +on a smaller set of toolchains than the traditional header-based build: + +| Compiler | Minimum version | Notes | +|---|---|---| +| Clang | 23 | | + ## Installation Pick whichever fits your project. diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 78909f15f..086e815a8 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -79,21 +79,15 @@ set(stdexec_test_sources stdexec/types/test_task.cpp ) +# The rest of these built cleanly once the modular build moved to Clang 23; the +# Clang 22 ICE that forced a longer exclusion list here is documented under +# "Modular builds" in the README. if(NOT STDEXEC_BUILD_MODULES) - # these tests don't build in modules mode, yet + # Fails in modules mode on every supported compiler: __any_allocator is + # reachable but not exported from the stdexec module, so it needs a + # STDEXEC_MODULE_EXPORT annotation before this can be enabled. list(APPEND stdexec_test_sources - stdexec/algos/adaptors/test_let_error.cpp - stdexec/algos/adaptors/test_let_stopped.cpp - stdexec/algos/adaptors/test_let_value.cpp - stdexec/algos/adaptors/test_on.cpp - stdexec/algos/adaptors/test_on2.cpp - stdexec/algos/adaptors/test_on3.cpp - stdexec/algos/adaptors/test_when_all.cpp - stdexec/algos/factories/test_just_error.cpp - stdexec/cpos/test_cpo_bulk.cpp - stdexec/cpos/test_cpo_upon_error.cpp stdexec/detail/test_any_allocator.cpp - stdexec/schedulers/test_parallel_scheduler.cpp ) endif()