Skip to content

Add system_sysroot to rust_toolchain for pre-installed toolchains#3928

Open
rejuvenile wants to merge 1 commit intobazelbuild:mainfrom
rejuvenile:feat-system-sysroot
Open

Add system_sysroot to rust_toolchain for pre-installed toolchains#3928
rejuvenile wants to merge 1 commit intobazelbuild:mainfrom
rejuvenile:feat-system-sysroot

Conversation

@rejuvenile
Copy link

@rejuvenile rejuvenile commented Mar 24, 2026

Summary

Adds rust_system_toolchain_repository, a repository rule that discovers a pre-installed Rust toolchain on the system, following the cc_configure pattern from rules_cc.

Problem

When using remote execution with workers that have the Rust toolchain pre-installed, the entire sysroot (~670MB) is transferred as action inputs for every compilation action. This creates significant overhead when the toolchain is already available on the worker.

Solution

A repository rule (rust_system_toolchain_repository) that:

  1. Probes the system at fetch time: runs rustc --print sysroot, rustc --version --verbose, rustc --print target-libdir
  2. Generates a BUILD.bazel with rust_toolchain() targets where sysroot files are excluded from action inputs
  3. Creates symlinks to system binaries (rustc, cargo, rustdoc, clippy-driver)
  4. Registers toolchains with proper platform constraints

The rust_toolchain rule gains a sysroot_path string attribute. When set, --sysroot=<path> is passed to rustc and sysroot files are excluded from action inputs.

New files

  • rust/private/system_rust_configure.bzl — repository rule + module extension

Modified files

  • rust/toolchain.bzl — adds sysroot_path attribute
  • rust/private/rustc.bzl — uses system paths when sysroot_path is set
  • rust/private/clippy.bzl, rustdoc.bzl, unpretty.bzl — same
  • cargo/private/cargo_build_script.bzl — uses system CARGO/RUSTC paths

Usage

# MODULE.bazel
system_rust = use_extension("@rules_rust//rust/private:system_rust_configure.bzl", "system_rust_ext")
system_rust.toolchain(
    exec_triple = "x86_64-unknown-linux-gnu",
    target_triples = ["x86_64-unknown-linux-gnu"],
)
use_repo(system_rust, "system_rust_toolchain")
register_toolchains("@system_rust_toolchain//:all")

This follows the reviewer feedback on #3920 suggesting a repository rule approach similar to @rules_cc//cc/private/toolchain/cc_configure.bzl.

Test plan

  • Build with system toolchain on a machine with Rust installed
  • Verify sysroot files are not included in action inputs
  • Verify remote execution works without toolchain file transfers
  • Verify builds still work with the default (non-system) toolchain

Introduce a repository rule that probes the system for an installed Rust
toolchain and generates BUILD targets with sysroot_path set. This follows
the cc_configure pattern from rules_cc: the repository rule runs at fetch
time, discovers the toolchain, and generates appropriate targets.

Changes:
- New rust/private/system_rust_configure.bzl with:
  - rust_system_toolchain_repository repository rule
  - system_rust_ext module extension for bzlmod
  - System probing (rustc --print sysroot, --version, --print target-libdir)
  - BUILD file generation with rust_toolchain + toolchain targets
- rust/toolchain.bzl: Add sysroot_path attribute to rust_toolchain. When
  set, sysroot files are excluded from action inputs and --sysroot is
  passed to rustc pointing at the system installation.
- rust/private/rustc.bzl: Use system rustc path when sysroot_path is set
- rust/private/clippy.bzl: Use system clippy-driver when sysroot_path is set
- rust/private/rustdoc.bzl: Use system rustdoc when sysroot_path is set
- rust/private/unpretty.bzl: Use system rustc when sysroot_path is set
- cargo/private/cargo_build_script.bzl: Use system tool paths for CARGO,
  RUSTC, RUSTDOC env vars when sysroot_path is set

This replaces the previous system_sysroot boolean approach with a cleaner
separation: the repository rule handles system probing, and the toolchain
rule simply accepts a sysroot_path string for path redirection.
@rejuvenile rejuvenile force-pushed the feat-system-sysroot branch from 901ed83 to 2f03f47 Compare March 24, 2026 23:22
"opt": "debuginfo",
},
),
"sysroot_path": attr.string(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed if you're building the toolchain in a repository rule? Why not symlink the toolchain directory into the repository and wire things up with nominal filegroups?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed if you're building the toolchain in a repository rule? Why not symlink the toolchain directory into the repository and wire things up with nominal filegroups?

I had a small bias towards not transferring the symlinks during remote execution, but more importantly, I don't how how symlinks would work with sandboxed execution, since they would point outside of the sandbox. With the current approach, Bazel symlinks the toolchain into the sandbox itself.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then would it be sensible to have wrapper scripts that simply exec out to a hard-coded path on disk? I've seen this pattern in a number of places and haven't noticed a major difference

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants