Skip to content

feat: per-crate rustc flag configuration trimming#3923

Open
rejuvenile wants to merge 1 commit intobazelbuild:mainfrom
rejuvenile:add-per-crate-flag-trim
Open

feat: per-crate rustc flag configuration trimming#3923
rejuvenile wants to merge 1 commit intobazelbuild:mainfrom
rejuvenile:add-per-crate-flag-trim

Conversation

@rejuvenile
Copy link

Summary

Add a skip_per_crate_rustc_flags attribute and transition to clear the experimental_per_crate_rustc_flag setting for targets that would never match any per-crate flag filter, improving cache hit rates for third-party crates.

Problem

When experimental_per_crate_rustc_flag is set (e.g., to pass -Copt-level=2 to first-party crates matching //.*@), all transitive third-party crates are placed into a different Bazel configuration even though the flag filter never matches them. In a typical project with hundreds of third-party crates, this means:

  • Changing any per-crate flag causes a full rebuild of all third-party crates
  • Remote cache hit rates drop because the configuration hash changes
  • Build times increase proportionally to the number of third-party crates

Solution

Add a configuration trimming mechanism:

  1. New attribute: skip_per_crate_rustc_flags (bool, default False) on all Rust rule types (rust_library, rust_binary, rust_test, rust_proc_macro, rust_static_library, rust_shared_library)

  2. New transition: per_crate_flag_trim_transition in rust/private/per_crate_flag_trim.bzl — when skip_per_crate_rustc_flags = True, clears the experimental_per_crate_rustc_flag setting, returning the target to a canonical configuration

  3. Integration: The transition is applied via cfg on rust_library and rust_proc_macro, and integrated into existing platform transitions for binary/test/static/shared library rules

  4. crate_universe: The renderer sets skip_per_crate_rustc_flags: true on all generated third-party crate targets

How it works

first_party_binary (per_crate_flags = ["//.*@-Copt-level=2"])
  └── first_party_lib (flags match → -Copt-level=2 applied)
  └── serde (skip_per_crate_rustc_flags = True)
        → transition clears per_crate_flags → canonical config
        → cache key is stable regardless of flag changes

When skip_per_crate_rustc_flags = False (the default for first-party crates), the transition is a no-op and preserves the current behavior.

Changes

  • rust/private/per_crate_flag_trim.bzl (new): Transition implementation
  • rust/private/rust.bzl: Add attribute, wire transitions
  • crate_universe/src/rendering.rs: Set attribute on generated targets
  • crate_universe/src/utils/starlark.rs: Add field to CommonAttrs struct

Compatibility

  • Fully backward compatible: The attribute defaults to False, so existing targets are unaffected
  • No behavior change for first-party crates: Only targets explicitly opting in have their configuration trimmed
  • Works with existing --experimental_per_crate_rustc_flag usage: The trim only affects the per-crate flag setting, not other configuration values

Add a `skip_per_crate_rustc_flags` attribute and transition to clear
the `experimental_per_crate_rustc_flag` setting for targets that would
never match any per-crate flag filter.

When `experimental_per_crate_rustc_flag` is set (e.g., to pass flags to
first-party crates matching `//` prefix), all transitive third-party
crates are placed into a different configuration even though the flags
don't apply to them. This causes unnecessary rebuilds when the flag
value changes.

This change:
- Adds `per_crate_flag_trim.bzl` with a transition that clears the
  setting when `skip_per_crate_rustc_flags = True`
- Adds the `skip_per_crate_rustc_flags` attribute to `_common_attrs`
- Applies the transition to `rust_library` and `rust_proc_macro` rules
- Extends existing transitions (binary, test, static_library,
  shared_library) to also trim per-crate flags
- Updates crate_universe's rendering to set the attribute on generated
  third-party crate targets

This significantly improves cache hit rates for projects that use
per-crate flags for first-party code while depending on many
third-party crates.
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.

1 participant