From db503786e682d45e3d922b927b099b454a1070bb Mon Sep 17 00:00:00 2001 From: helly25 Date: Sat, 17 Oct 2026 14:38:16 +0100 Subject: [PATCH 1/8] Select stable LLVM 23 releases from the pinned catalogue --- CONTRIBUTING.md | 7 +++++-- bazelmod/llvm.MODULE.bazel | 21 +++++++++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5f92b4abc3c..9dcf160030b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -68,12 +68,15 @@ No tests contact GitHub or recursively invoke Bazel; the separate site integrati ## Compiler and sanitizer versions -`--config=clang` uses LLVM 23.1.2. The `msan` feature selects LLVM 22.1.8 and its matching +`--config=clang` selects the newest stable LLVM 23 release available for the host from the pinned +`toolchains_llvm` catalogue (`latest:major==23`). Updating that module can adopt LLVM 23 fixes +without a separate compiler-version edit; LLVM 24 requires an explicit selector change. The +`msan` feature selects LLVM 22.1.8 and its matching instrumented libc++ on Linux x86-64, independently of config flag order. ASan, TSan, coverage, fuzzing, releases, build tools, and clang-tidy use LLVM 23. The existing `--config=lto` selection continues to use native Apple ld on macOS and bundled LLD on Linux. -Pre-commit and `tools/clang_format.sh` run clang-format from the same pinned LLVM 23 distribution. +Pre-commit and `tools/clang_format.sh` run clang-format from the same selected LLVM 23 distribution. The first run fetches that distribution if needed; it does not compile XFF. CI runs clang-tidy across the complete indexed source set when the compiler or lint policy changes; ordinary source changes keep the affected-file scope. diff --git a/bazelmod/llvm.MODULE.bazel b/bazelmod/llvm.MODULE.bazel index d8cfa2c89c2..06275d8e458 100644 --- a/bazelmod/llvm.MODULE.bazel +++ b/bazelmod/llvm.MODULE.bazel @@ -15,8 +15,23 @@ """LLVM 23 by default; LLVM 22 with its matching instrumented libc++ for MSan.""" -# The release provides feature-based linker selection and native macOS ThinLTO. +# Replace this source pin with the release containing the shared version selectors: +# https://github.com/bazel-contrib/toolchains_llvm/pull/909 bazel_dep(name = "toolchains_llvm", version = "1.11.3") +git_override( + module_name = "toolchains_llvm", + commit = "195720770d169a5892ee92085e0b00be3fc97e81", + remote = "https://github.com/bazel-contrib/toolchains_llvm.git", +) + +# Root overrides do not propagate from toolchains_llvm. Use the published archive +# while its BCR entry awaits review: https://github.com/bazelbuild/bazel-central-registry/pull/11158 +archive_override( + module_name = "mboworks_bzl", + integrity = "sha256-sS12HYg9SX7MP15MAFoCsZtCVgax6t1RXRWD2KvpyhQ=", + strip_prefix = "bzl-0.7.0", + urls = ["https://github.com/mboworks/bzl/releases/download/0.7.0/bzl-0.7.0.tar.gz"], +) # The MemorySanitizer-instrumented libc++ (`--config=msan`, Linux only). MSan reports a # false positive for every read of memory written by code it did not instrument, and the @@ -41,7 +56,9 @@ bazel_dep(name = "toolchains_llvm", version = "1.11.3") # Keep the MSan compiler and instrumented standard library on the same release. # The ordinary compiler can advance independently through the feature override below. MSAN_LIBCXX_URL = "https://github.com/RealtimeRoboticsGroup/toolchains/releases/download/{v}/libcxx-msan-{v}-x86_64-linux-gnu-ubuntu-22.04.tar.zst" -LLVM_VERSION = "23.1.2" +# Follow stable LLVM 23 releases from the pinned toolchains_llvm catalogue. +# Major compiler and clang-tidy upgrades require an explicit policy change. +LLVM_VERSION = "latest:major==23" MSAN_LLVM_VERSION = "22.1.8" llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm", dev_dependency = True) From 945731430f33d9907d614a32e8ebd4e6b7ae1943 Mon Sep 17 00:00:00 2001 From: helly25 Date: Sat, 17 Oct 2026 14:51:10 +0100 Subject: [PATCH 2/8] Align LLVM sanitizer version naming and refresh selector source --- bazelmod/llvm.MODULE.bazel | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bazelmod/llvm.MODULE.bazel b/bazelmod/llvm.MODULE.bazel index 06275d8e458..59da45f6dac 100644 --- a/bazelmod/llvm.MODULE.bazel +++ b/bazelmod/llvm.MODULE.bazel @@ -20,7 +20,7 @@ bazel_dep(name = "toolchains_llvm", version = "1.11.3") git_override( module_name = "toolchains_llvm", - commit = "195720770d169a5892ee92085e0b00be3fc97e81", + commit = "06afb306f0b38501212041421a894361cb921ff1", remote = "https://github.com/bazel-contrib/toolchains_llvm.git", ) @@ -59,7 +59,7 @@ MSAN_LIBCXX_URL = "https://github.com/RealtimeRoboticsGroup/toolchains/releases/ # Follow stable LLVM 23 releases from the pinned toolchains_llvm catalogue. # Major compiler and clang-tidy upgrades require an explicit policy change. LLVM_VERSION = "latest:major==23" -MSAN_LLVM_VERSION = "22.1.8" +LLVM_VERSION_MSAN = "22.1.8" llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm", dev_dependency = True) llvm.toolchain( @@ -94,9 +94,9 @@ llvm.feature_override( features = ["msan"], targets = ["linux-x86_64"], libcxx_sha256 = "fd1ac49eeda4edc6deeda2037998e558718a63a5054fff4fdace7751b270217a", - libcxx_url = MSAN_LIBCXX_URL.format(v = MSAN_LLVM_VERSION), + libcxx_url = MSAN_LIBCXX_URL.format(v = LLVM_VERSION_MSAN), linker = {"linux-x86_64": ""}, - llvm_version = MSAN_LLVM_VERSION, + llvm_version = LLVM_VERSION_MSAN, ) use_repo(llvm, "llvm_toolchain_llvm") From 1da6ecc6fe5790837844f48644aaf24787af99bb Mon Sep 17 00:00:00 2001 From: helly25 Date: Sat, 17 Oct 2026 18:32:57 +0100 Subject: [PATCH 3/8] Use official bzl 0.7.0 registry resolution --- bazelmod/llvm.MODULE.bazel | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/bazelmod/llvm.MODULE.bazel b/bazelmod/llvm.MODULE.bazel index 59da45f6dac..bdf46ad5301 100644 --- a/bazelmod/llvm.MODULE.bazel +++ b/bazelmod/llvm.MODULE.bazel @@ -20,19 +20,10 @@ bazel_dep(name = "toolchains_llvm", version = "1.11.3") git_override( module_name = "toolchains_llvm", - commit = "06afb306f0b38501212041421a894361cb921ff1", + commit = "ac4055749414b749173bdfa820f5276d4c5714c8", remote = "https://github.com/bazel-contrib/toolchains_llvm.git", ) -# Root overrides do not propagate from toolchains_llvm. Use the published archive -# while its BCR entry awaits review: https://github.com/bazelbuild/bazel-central-registry/pull/11158 -archive_override( - module_name = "mboworks_bzl", - integrity = "sha256-sS12HYg9SX7MP15MAFoCsZtCVgax6t1RXRWD2KvpyhQ=", - strip_prefix = "bzl-0.7.0", - urls = ["https://github.com/mboworks/bzl/releases/download/0.7.0/bzl-0.7.0.tar.gz"], -) - # The MemorySanitizer-instrumented libc++ (`--config=msan`, Linux only). MSan reports a # false positive for every read of memory written by code it did not instrument, and the # C++ standard library ships PREBUILT (uninstrumented) inside the LLVM distribution - so From 41085afa98daccfd798bd2612b107f7aa8904fda Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Oct 2026 22:06:27 +0000 Subject: [PATCH 4/8] Bump bazel-contrib/setup-bazel from 0.19.0 to 0.19.1 Bumps [bazel-contrib/setup-bazel](https://github.com/bazel-contrib/setup-bazel) from 0.19.0 to 0.19.1. - [Release notes](https://github.com/bazel-contrib/setup-bazel/releases) - [Commits](https://github.com/bazel-contrib/setup-bazel/compare/0.19.0...0.19.1) --- updated-dependencies: - dependency-name: bazel-contrib/setup-bazel dependency-version: 0.19.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/benchmark_backfill.yml | 2 +- .github/workflows/benchmarks.yml | 2 +- .github/workflows/fuzz.yml | 2 +- .github/workflows/main.yml | 24 ++++++++++++------------ .github/workflows/release.yml | 4 ++-- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/benchmark_backfill.yml b/.github/workflows/benchmark_backfill.yml index 05f73afd42c..691ac6d3b30 100644 --- a/.github/workflows/benchmark_backfill.yml +++ b/.github/workflows/benchmark_backfill.yml @@ -70,7 +70,7 @@ jobs: - uses: actions/setup-python@v7 with: python-version: "3.13" - - uses: bazel-contrib/setup-bazel@0.19.0 + - uses: bazel-contrib/setup-bazel@0.19.1 - name: Check runner capacity run: | affinity=() diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml index ad5e5bb528e..f4a722b9b5e 100644 --- a/.github/workflows/benchmarks.yml +++ b/.github/workflows/benchmarks.yml @@ -36,7 +36,7 @@ jobs: ref: ${{ github.sha }} fetch-depth: 0 persist-credentials: false - - uses: bazel-contrib/setup-bazel@0.19.0 + - uses: bazel-contrib/setup-bazel@0.19.1 - uses: actions/setup-python@v7 with: python-version: "3.13" diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index b40c8ed7b90..a8bb3984fbf 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -21,7 +21,7 @@ jobs: timeout-minutes: 75 steps: - uses: actions/checkout@v7 - - uses: bazel-contrib/setup-bazel@0.19.0 + - uses: bazel-contrib/setup-bazel@0.19.1 - name: Restore Bazel compiled outputs id: bazel-cache uses: ./.github/actions/bazel-cache-restore diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0de423f140e..5d687ec062b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -30,7 +30,7 @@ jobs: - uses: actions/setup-python@v7 with: python-version: "3.13" - - uses: bazel-contrib/setup-bazel@0.19.0 + - uses: bazel-contrib/setup-bazel@0.19.1 - name: Check live repository tooling run: bazel run //tools:repository_tooling_test - uses: actions/setup-node@v7 @@ -83,7 +83,7 @@ jobs: steps: - uses: actions/checkout@v7 # bazelisk launches the Bazel release pinned in .bazelversion. - - uses: bazel-contrib/setup-bazel@0.19.0 + - uses: bazel-contrib/setup-bazel@0.19.1 # PRs restore main's latest compiled outputs. Every main run saves a new bounded # generation; GitHub cache entries cannot be updated in place. - name: Restore Bazel compiled outputs @@ -213,7 +213,7 @@ jobs: sudo update-alternatives --set gcc /usr/bin/gcc-15 gcc --version g++ --version - - uses: bazel-contrib/setup-bazel@0.19.0 + - uses: bazel-contrib/setup-bazel@0.19.1 - name: Restore Bazel compiled outputs id: bazel-cache uses: ./.github/actions/bazel-cache-restore @@ -248,7 +248,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - - uses: bazel-contrib/setup-bazel@0.19.0 + - uses: bazel-contrib/setup-bazel@0.19.1 - uses: actions/setup-python@v7 with: python-version: "3.13" @@ -280,7 +280,7 @@ jobs: FUZZ_SECONDS_PER_TARGET: 60 steps: - uses: actions/checkout@v7 - - uses: bazel-contrib/setup-bazel@0.19.0 + - uses: bazel-contrib/setup-bazel@0.19.1 - name: Restore Bazel compiled outputs id: bazel-cache uses: ./.github/actions/bazel-cache-restore @@ -338,7 +338,7 @@ jobs: - uses: actions/checkout@v7 with: fetch-depth: 0 - - uses: bazel-contrib/setup-bazel@0.19.0 + - uses: bazel-contrib/setup-bazel@0.19.1 # Coverage instrumentation has distinct action keys, so keep its compiled outputs in a # dedicated cache rather than crowding out the ordinary Clang build. Prefix restoration lets a # later run reuse objects from the newest saved generation. @@ -465,7 +465,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - - uses: bazel-contrib/setup-bazel@0.19.0 + - uses: bazel-contrib/setup-bazel@0.19.1 - name: Restore Bazel compiled outputs id: bazel-cache uses: ./.github/actions/bazel-cache-restore @@ -510,7 +510,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - - uses: bazel-contrib/setup-bazel@0.19.0 + - uses: bazel-contrib/setup-bazel@0.19.1 - name: Restore Bazel compiled outputs id: bazel-cache uses: ./.github/actions/bazel-cache-restore @@ -553,7 +553,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - - uses: bazel-contrib/setup-bazel@0.19.0 + - uses: bazel-contrib/setup-bazel@0.19.1 - name: Restore Bazel compiled outputs id: bazel-cache uses: ./.github/actions/bazel-cache-restore @@ -595,7 +595,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - - uses: bazel-contrib/setup-bazel@0.19.0 + - uses: bazel-contrib/setup-bazel@0.19.1 - name: Restore Bazel compiled outputs id: bazel-cache uses: ./.github/actions/bazel-cache-restore @@ -661,7 +661,7 @@ jobs: echo "CLANG_TIDY_SCOPE=none" >>"${GITHUB_ENV}" echo "No C++ source or header changed; clang-tidy is not required." fi - - uses: bazel-contrib/setup-bazel@0.19.0 + - uses: bazel-contrib/setup-bazel@0.19.1 if: env.CLANG_TIDY_ENABLED == 'true' - uses: actions/setup-python@v7 if: env.CLANG_TIDY_ENABLED == 'true' @@ -741,7 +741,7 @@ jobs: - uses: actions/checkout@v7 with: persist-credentials: false - - uses: bazel-contrib/setup-bazel@0.19.0 + - uses: bazel-contrib/setup-bazel@0.19.1 - uses: actions/setup-python@v7 with: python-version: "3.13" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8a9a3a876f4..3fe75c7e0c5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -50,7 +50,7 @@ jobs: - uses: actions/checkout@v7 with: ref: ${{ env.RELEASE_TAG }} - - uses: bazel-contrib/setup-bazel@0.19.0 + - uses: bazel-contrib/setup-bazel@0.19.1 # Tag caches cannot seed later releases or main; restore main outputs without saving. - name: Restore Bazel compiled outputs id: bazel-cache @@ -160,7 +160,7 @@ jobs: with: ref: ${{ env.RELEASE_TAG }} # bazelisk launches the Bazel release pinned in .bazelversion. - - uses: bazel-contrib/setup-bazel@0.19.0 + - uses: bazel-contrib/setup-bazel@0.19.1 # Tag caches cannot seed later releases or main; restore main outputs without saving. - name: Restore Bazel compiled outputs id: bazel-cache From ef14134699bc7f83210b05c4968eace81f503b1f Mon Sep 17 00:00:00 2001 From: helly25 Date: Thu, 22 Oct 2026 23:58:22 +0100 Subject: [PATCH 5/8] Align setup-bazel policy with the 0.19.1 update --- tools/release_prep_test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/release_prep_test.sh b/tools/release_prep_test.sh index 3232e8f858c..8bbe6d05252 100755 --- a/tools/release_prep_test.sh +++ b/tools/release_prep_test.sh @@ -300,8 +300,8 @@ test_workflows_use_setup_bazel() { fi workflow_setup_count=$(count_lines_with 'uses: bazel-contrib/setup-bazel@' "${workflow}") setup_count=$((setup_count + workflow_setup_count)) - if [ "${workflow_setup_count}" -ne "$(count_lines_with 'uses: bazel-contrib/setup-bazel@0.19.0' "${workflow}")" ]; then - fail "workflow $(basename "${workflow}"): every setup-bazel use must pin 0.19.0" + if [ "${workflow_setup_count}" -ne "$(count_lines_with 'uses: bazel-contrib/setup-bazel@0.19.1' "${workflow}")" ]; then + fail "workflow $(basename "${workflow}"): every setup-bazel use must pin 0.19.1" fi done if [ "${setup_count}" -eq 0 ]; then From c1c2ea90bb3335337090279a2271d5bfd153ecfb Mon Sep 17 00:00:00 2001 From: helly25 Date: Fri, 23 Oct 2026 00:02:17 +0100 Subject: [PATCH 6/8] Refresh LLVM selectors and support both Linux FUSE ABIs --- .github/workflows/main.yml | 23 ++++++++++++++--------- .github/workflows/release.yml | 2 +- CONTRIBUTING.md | 12 ++++++++++++ bazelmod/llvm.MODULE.bazel | 8 ++++---- extra_modules/fuse/fuse_abi.h | 10 +++++++--- extra_modules/fuse/fuse_loader.cc | 1 + extra_modules/fuse/fuse_loader.h | 7 ++++--- tools/fuse_linux_test.sh | 2 +- 8 files changed, 44 insertions(+), 21 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0de423f140e..797c43fb987 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -67,15 +67,19 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest] + os: [ubuntu-24.04, ubuntu-latest, macos-latest] config: - name: default flags: "--config=clang_release" - name: asan flags: "--config=clang --config=asan" exclude: - # asan on Linux is enough; the macOS asan cell is redundant sanitizer coverage, so drop it. - # This leaves: ubuntu default, ubuntu asan, macos default. + # Exercise both Linux FUSE SONAMEs in default builds; one Linux asan cell is enough. + # This leaves: Ubuntu 24.04 default, latest default + asan, and macOS default. + - os: ubuntu-24.04 + config: + name: asan + flags: "--config=clang --config=asan" - os: macos-latest config: name: asan @@ -90,7 +94,7 @@ jobs: id: bazel-cache uses: ./.github/actions/bazel-cache-restore with: - namespace: ${{ matrix.config.name }} + namespace: ${{ matrix.os == 'ubuntu-24.04' && 'default-ubuntu24' || matrix.config.name }} legacy-prefix: bazel-disk-${{ matrix.os }}-${{ matrix.config.name }}- # Every matrix cell uses hermetic LLVM. Do not persist the repository cache: one LLVM archive # is ~4.4 GB and would consume almost half of GitHub's per-repository cache budget. Compiled @@ -105,13 +109,14 @@ jobs: command -v mandoc # The FUSE server's integration test mounts a real filesystem through the kernel, which only # Linux runners can do (macOS has no fuse3; the test skips there by design). Install the - # runtime pieces the loader dlopens (libfuse3) and the unmount helper (fusermount3). The test + # fuse3 package, which pulls in the matching libfuse3 runtime (SONAME 3 on Ubuntu 24.04, + # SONAME 4 on Ubuntu 26.04) and the unmount helper (fusermount3). The test # command below opts Linux into the Bazel capability contract, so mounting failures cannot # silently become skips. - name: Enable FUSE integration coverage (Linux) run: | if [ "${RUNNER_OS}" = "Linux" ]; then - sudo apt-get install -y fuse3 libfuse3-3 + sudo apt-get install -y fuse3 fi # Every job builds with EVERY extra on (--config=xff_docs, which is --config=xff_full plus the # archive extra), so the composable extras get the SAME asan / tsan coverage as the core - our @@ -355,7 +360,7 @@ jobs: run: | # Ubuntu's lcov package supplies the Perl dependencies, but its old genhtml ignores # metric-specific color thresholds. Install the pinned current release over it below. - sudo apt-get install -y lcov mandoc fuse3 libfuse3-3 + sudo apt-get install -y lcov mandoc fuse3 tools/install_lcov.sh "${RUNNER_TEMP}/lcov" echo "${RUNNER_TEMP}/lcov/bin" >>"${GITHUB_PATH}" - name: Collect and enforce coverage @@ -477,7 +482,7 @@ jobs: # This runner promises a working mount path through the named Bazel config below. - name: Enable FUSE integration coverage run: | - sudo apt-get install -y fuse3 libfuse3-3 + sudo apt-get install -y fuse3 - name: bazel test run: | # shellcheck disable=SC2046 # deliberate word splitting: the tool prints bazel target patterns @@ -525,7 +530,7 @@ jobs: # macro in C++, the XFF_MSAN env in the shell test), so they hold whether or not this is set. - name: Enable FUSE integration coverage run: | - sudo apt-get install -y fuse3 libfuse3-3 + sudo apt-get install -y fuse3 - name: bazel test run: | # shellcheck disable=SC2046 # deliberate word splitting: the tool prints bazel target patterns diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8a9a3a876f4..58de810c81b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -65,7 +65,7 @@ jobs: run: | # Ubuntu's lcov package supplies the Perl dependencies, but its old genhtml ignores # metric-specific color thresholds. Install the pinned current release over it below. - sudo apt-get install -y lcov mandoc fuse3 libfuse3-3 + sudo apt-get install -y lcov mandoc fuse3 tools/install_lcov.sh "${RUNNER_TEMP}/lcov" echo "${RUNNER_TEMP}/lcov/bin" >>"${GITHUB_PATH}" - name: Check live repository tooling diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9dcf160030b..4ebb8981991 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -81,6 +81,18 @@ The first run fetches that distribution if needed; it does not compile XFF. CI r across the complete indexed source set when the compiler or lint policy changes; ordinary source changes keep the affected-file scope. +## Linux FUSE runtimes + +The FUSE extra loads either `libfuse3.so.4` (Ubuntu 26.04) or `libfuse3.so.3` (Ubuntu 24.04) +at runtime. Install `fuse3`; its package dependency selects the matching runtime library without +pinning a distribution-specific library package name. Both SONAMEs expose the FUSE3 API subset +used by xff, including the four-argument `fuse_session_new` compatibility entry point. No libfuse +headers or libraries are included in the build. + +Linux CI runs the real mount tests on Ubuntu 24.04 and `ubuntu-latest`, with +`--config=xff_fuse_tests_required` so missing libraries or failed mounts fail the job. Hosts without +a usable FUSE runtime retain the existing extraction fallback. + ## Local clang-tidy scope The normal commit and push hooks run clang-tidy on their changed C++ files. Changed headers diff --git a/bazelmod/llvm.MODULE.bazel b/bazelmod/llvm.MODULE.bazel index bdf46ad5301..7340eea57a2 100644 --- a/bazelmod/llvm.MODULE.bazel +++ b/bazelmod/llvm.MODULE.bazel @@ -15,12 +15,12 @@ """LLVM 23 by default; LLVM 22 with its matching instrumented libc++ for MSan.""" -# Replace this source pin with the release containing the shared version selectors: -# https://github.com/bazel-contrib/toolchains_llvm/pull/909 -bazel_dep(name = "toolchains_llvm", version = "1.11.3") +# Pin the selector support merged after 1.12.0; use a release containing it when available. +# https://github.com/bazel-contrib/toolchains_llvm/pull/911 +bazel_dep(name = "toolchains_llvm", version = "1.12.0") git_override( module_name = "toolchains_llvm", - commit = "ac4055749414b749173bdfa820f5276d4c5714c8", + commit = "b63941bcc533a52e1b81c81af5fe77d5a2b382f8", remote = "https://github.com/bazel-contrib/toolchains_llvm.git", ) diff --git a/extra_modules/fuse/fuse_abi.h b/extra_modules/fuse/fuse_abi.h index 242d58487ba..a1fe46820a1 100644 --- a/extra_modules/fuse/fuse_abi.h +++ b/extra_modules/fuse/fuse_abi.h @@ -33,12 +33,16 @@ // `fuse_conn_info` are only ever passed through, so their layouts are irrelevant AND absent. // What is not written cannot drift. // 2. Anything whose fields we touch carries the exact layout, field for field, in libfuse's own -// order, transcribed against fuse-3.18.2. Order IS the ABI. +// order, transcribed against fuse-3.18.2. Order IS the ABI. The prefix we use also matches +// fuse-3.14.0 (Linux SONAME 3); fuse-3.18.2 uses SONAME 4. We only access the common +// fuse_file_info fields and lowlevel ops prefix, and use the exported four-argument +// fuse_session_new compatibility entry point on both runtimes. // // HOW A MISTAKE SURFACES: the loader resolves every entry point by NAME (see fuse_loader.h), so a // wrong signature or field offset cannot be caught at link time - it corrupts at runtime. The guard -// is Linux CI, where fuse_server_test and the --archive-mount CLI cases drive a real fuse3: a -// mismatched `fuse_lowlevel_ops` prefix or a shifted `fuse_file_info::fh` fails there loudly. +// is Linux CI on Ubuntu 24.04 (SONAME 3) and ubuntu-latest (SONAME 4), where fuse_server_test +// and the --archive-mount CLI cases drive a real fuse3: a mismatched `fuse_lowlevel_ops` prefix or a shifted +// `fuse_file_info::fh` fails there loudly. // // EXTENDING IT: fields are only ever APPENDED to `fuse_lowlevel_ops`, and fuse_server passes // `op_size` as the offset just past the LAST op it implements (never `sizeof`), so this prefix means diff --git a/extra_modules/fuse/fuse_loader.cc b/extra_modules/fuse/fuse_loader.cc index 8756d963c7f..a88662c66bf 100644 --- a/extra_modules/fuse/fuse_loader.cc +++ b/extra_modules/fuse/fuse_loader.cc @@ -56,6 +56,7 @@ constexpr std::array kLibraryCandidates = std::to_array({ "/usr/local/lib/libfuse3.dylib", "libfuse3.dylib", #else + "libfuse3.so.4", "libfuse3.so.3", "libfuse3.so", #endif diff --git a/extra_modules/fuse/fuse_loader.h b/extra_modules/fuse/fuse_loader.h index ee466127291..697c4d8882c 100644 --- a/extra_modules/fuse/fuse_loader.h +++ b/extra_modules/fuse/fuse_loader.h @@ -24,9 +24,10 @@ // mount server needs is resolved then. One binary runs everywhere; where the library is absent, // `--archive-mount` degrades to extraction and this loader says why. // -// Scope: the FUSE3 API only. macFUSE installations that ship only the legacy fuse2 library report -// unavailable (with the library name in `error()`); supporting the fuse2 lowlevel API is a separate -// decision to take when a real macFUSE user appears, not a default. +// Scope: the FUSE3 API, including Linux SONAMEs 3 and 4. The ABI subset in fuse_abi.h +// works with both; SONAME 4 is still the FUSE3 API. macFUSE installations that ship only the legacy fuse2 library +// report unavailable (with the library name in `error()`); supporting the fuse2 lowlevel API is a separate decision to +// take when a real macFUSE user appears, not a default. #include #include diff --git a/tools/fuse_linux_test.sh b/tools/fuse_linux_test.sh index 3f1919ca4d4..cd2cf6bb88f 100755 --- a/tools/fuse_linux_test.sh +++ b/tools/fuse_linux_test.sh @@ -55,7 +55,7 @@ export DEBIAN_FRONTEND=noninteractive apt-get update -qq >/dev/null # git is not optional: MODULE.bazel pulls toolchains_llvm and hedron_compile_commands through # git_repository, so a cold cache cannot even compute the repo mapping without it. -apt-get install -y -qq curl git gcc g++ python3 unzip zip fuse3 libfuse3-3 >/dev/null +apt-get install -y -qq curl git gcc g++ python3 unzip zip fuse3 >/dev/null arch="$(uname -m)"; [ "${arch}" = "aarch64" ] && arch=arm64 || arch=amd64 curl -sSL -o /usr/local/bin/bazel "https://github.com/bazelbuild/bazelisk/releases/download/v1.20.0/bazelisk-linux-${arch}" chmod +x /usr/local/bin/bazel From 9212e7a743aebdea093cfb036b46f471c0b525f3 Mon Sep 17 00:00:00 2001 From: helly25 Date: Fri, 23 Oct 2026 00:23:58 +0100 Subject: [PATCH 7/8] Run the pinned MSan toolchain with compatible host libraries --- .github/workflows/main.yml | 10 ++++++---- CONTRIBUTING.md | 6 ++++++ tools/fuse_linux_test.sh | 2 ++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 797c43fb987..20b13050bba 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -512,7 +512,9 @@ jobs: contents: read actions: write # Retire replaced main cache generations after successful uploads. needs: [pre-commit, trunk] - runs-on: ubuntu-latest + # LLVM 22.1.8 LLD requires libxml2.so.2; Ubuntu 26.04 only packages SONAME 16. + # Keep the matching MSan compiler/libc++ pair on a host with compatible libraries. + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v7 - uses: bazel-contrib/setup-bazel@0.19.0 @@ -520,10 +522,10 @@ jobs: id: bazel-cache uses: ./.github/actions/bazel-cache-restore with: - namespace: msan + namespace: msan-ubuntu24 legacy-prefix: bazel-disk-msan- - - name: Install roff formatter (mandoc) - run: sudo apt-get install -y mandoc + - name: Install LLVM 22 runtime dependency and roff formatter + run: sudo apt-get install -y libxml2 mandoc # Installed for the same reason as the tsan cell, though every mounting test skips here: a # mount runs through the dlopened SYSTEM libfuse3, and MSan reports everything it did not # instrument as uninitialized. The skips key off --config=msan itself (the MEMORY_SANITIZER diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4ebb8981991..a286f95f5b4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -76,6 +76,12 @@ instrumented libc++ on Linux x86-64, independently of config flag order. ASan, T fuzzing, releases, build tools, and clang-tidy use LLVM 23. The existing `--config=lto` selection continues to use native Apple ld on macOS and bundled LLD on Linux. +The official LLVM 22.1.8 LLD executable requires `libxml2.so.2`. The MSan CI job uses +Ubuntu 24.04 and explicitly installs `libxml2`; Ubuntu 26.04 only packages `libxml2.so.16`, +which cannot satisfy that dependency. Ordinary LLVM 23 builds and the other sanitizer jobs +continue on `ubuntu-latest`. Moving MSan to that host requires a compatible compiler/runtime +distribution; keep its compiler and instrumented libc++ versions matched. + Pre-commit and `tools/clang_format.sh` run clang-format from the same selected LLVM 23 distribution. The first run fetches that distribution if needed; it does not compile XFF. CI runs clang-tidy across the complete indexed source set when the compiler or lint policy changes; ordinary source diff --git a/tools/fuse_linux_test.sh b/tools/fuse_linux_test.sh index cd2cf6bb88f..5ed720dae93 100755 --- a/tools/fuse_linux_test.sh +++ b/tools/fuse_linux_test.sh @@ -64,6 +64,8 @@ SETUP_EOF if [[ "${MODE}" == "msan" ]]; then script="${SETUP} +# The LLVM 22.1.8 linker needs SONAME 2, available in this Ubuntu 24.04 image. +apt-get install -y -qq libxml2 >/dev/null bazel --output_user_root=/bzcache test --config=xff_full @xff_fuse//... //xff/cli:full_extras_test \\ --config=clang --config=msan --config=xff_fuse_tests_required \\ --nocache_test_results --test_output=errors" From 16c86d96586d7caf1624bb1b4538b4b7965c7237 Mon Sep 17 00:00:00 2001 From: helly25 Date: Fri, 23 Oct 2026 01:12:02 +0100 Subject: [PATCH 8/8] Use a portable child command in the help boundary test --- xff/cli/help_topic_test.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xff/cli/help_topic_test.sh b/xff/cli/help_topic_test.sh index 8222fb4fa68..d11b19c77eb 100755 --- a/xff/cli/help_topic_test.sh +++ b/xff/cli/help_topic_test.sh @@ -398,8 +398,10 @@ test::bad_flags_are_hard_errors_even_with_help() { test::meta_spelling_inside_exec_stays_a_child_argument() { # Meta recognition follows parser boundaries. A child command is an opaque # argument run, so its `--help` must not turn xff itself into the usage page. + # Use the shell builtin: external printf implementations can interpret --help themselves. local out - out="$("$(_xff_bin)" --allow-exec . -maxdepth 0 -exec printf 'child:%s\n' --help ';' 2>&1)" + # shellcheck disable=SC2016 # The child shell expands its own positional argument. + out="$("$(_xff_bin)" --allow-exec . -maxdepth 0 -exec sh -c 'printf "child:%s\n" "$1"' child --help ';' 2>&1)" expect_output_contains 'child:--help' "${out}" expect_output_not_contains 'eXtended File Find' "${out}" }