Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions cargo/private/cargo_build_script_runner/bin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,16 @@ fn run_buildrs() -> Result<(), String> {
let file_name = path
.file_name()
.ok_or_else(|| "Failed while getting file name".to_string())?;

// Skip worker infrastructure directories — these are internal to
// rules_rust or Bazel and should never appear in CARGO_MANIFEST_DIR.
let name = file_name.to_string_lossy();
if name.starts_with("local-spawn-runner.")
|| name.starts_with("_pw_state")
{
continue;
}

let link = manifest_dir.join(file_name);

symlink_if_not_exists(&path, &link)
Expand Down
5 changes: 4 additions & 1 deletion crate_universe/src/metadata/cargo_bin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ impl Cargo {
/// Returns the output of running `cargo version`, trimming any leading or trailing whitespace.
/// This function performs normalisation to work around `<https://github.com/rust-lang/cargo/issues/10547>`
pub(crate) fn full_version(&self) -> Result<String> {
let mut full_version = self.full_version.lock().unwrap();
let mut full_version = self
.full_version
.lock()
.expect("cargo full_version mutex poisoned");
if full_version.is_none() {
let observed_version = Digest::bin_version(&self.path)?;
*full_version = Some(observed_version);
Expand Down
2 changes: 1 addition & 1 deletion rust/private/clippy.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def rust_clippy_action(ctx, clippy_executable, process_wrapper, crate_info, conf
attr = ctx.rule.attr,
file = ctx.file,
toolchain = toolchain,
tool_path = clippy_executable.path,
tool_path = clippy_executable,
cc_toolchain = cc_toolchain,
feature_configuration = feature_configuration,
crate_info = crate_info,
Expand Down
76 changes: 76 additions & 0 deletions rust/private/incremental.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"""A module defining Rust incremental compilation support"""

load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load("//rust/private:utils.bzl", "is_exec_configuration")

def _is_incremental_enabled(ctx, crate_info):
"""Returns True if incremental compilation is enabled for this target.

Args:
ctx (ctx): The calling rule's context object.
crate_info (CrateInfo): The CrateInfo provider of the target crate.

Returns:
bool: True if incremental compilation is enabled.
"""
if not hasattr(ctx.attr, "_incremental"):
return False
if is_exec_configuration(ctx):
return False
if not ctx.attr._incremental[BuildSettingInfo].value:
return False
if crate_info.type == "proc-macro":
return False

# Don't enable incremental for external/third-party crates, mirroring cargo's
# behavior. External crates rarely change, so incremental saves little; more
# importantly, the disk cache hardlinks their outputs as read-only, and running
# without sandboxing (which worker/no-sandbox requires) would cause rustc to
# fail trying to overwrite those read-only hardlinks.
if ctx.label.workspace_name:
return False
return True

def construct_incremental_arguments(ctx, crate_info, is_metadata = False):
"""Returns a list of 'rustc' flags to configure incremental compilation.

Args:
ctx (ctx): The calling rule's context object.
crate_info (CrateInfo): The CrateInfo provider of the target crate.
is_metadata (bool): True when building a RustcMetadata (--emit=metadata only) action.

Returns:
list: A list of strings that are valid flags for 'rustc'.
"""
if not _is_incremental_enabled(ctx, crate_info):
return []

# Use a separate cache directory for metadata-only (RustcMetadata) actions.
# Both RustcMetadata(A) and Rustc(A) compile the same crate, so they produce
# the same SVH — but sharing the same incremental path causes a rustc ICE
# ("no entry found for key") because the metadata-only session state is
# incompatible with a full-compilation session. Using distinct paths lets
# both actions benefit from incremental caching without interfering.
suffix = "-meta" if is_metadata else ""
cache_path = "/tmp/rules_rust_incremental/{}{}".format(crate_info.name, suffix)

# Explicitly set codegen-units=16 to match Cargo's dev profile default
# (since Cargo 1.73). Without this, rustc silently bumps CGUs from 16 to
# 256 when -Cincremental is present, adding ~37% of the cold-build overhead
# for no rebuild benefit at opt-level=0.
return ["-Cincremental={}".format(cache_path), "-Ccodegen-units=16"]

def is_incremental_enabled(ctx, crate_info):
"""Returns True if incremental compilation is enabled for this target.

This is the public API used by rustc_compile_action to determine whether
to set execution_requirements = {"no-sandbox": "1"}.

Args:
ctx (ctx): The calling rule's context object.
crate_info (CrateInfo): The CrateInfo provider of the target crate.

Returns:
bool: True if incremental compilation is enabled.
"""
return _is_incremental_enabled(ctx, crate_info)
74 changes: 64 additions & 10 deletions rust/private/rust.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ load(
"generate_output_diagnostics",
"get_edition",
"get_import_macro_deps",
"is_exec_configuration",
"transform_deps",
"transform_sources",
)
Expand All @@ -66,6 +67,25 @@ def _assert_no_deprecated_attributes(_ctx):
"""
pass

def _pipelining_output_hash_salt(ctx, toolchain, crate_type, disable_pipelining):
"""Returns a mode tag for artifact paths that differ across pipelining modes."""

if is_exec_configuration(ctx) or not can_use_metadata_for_pipelining(toolchain, crate_type):
return ""

if toolchain._worker_pipelining:
return "worker_pipelining"

if can_build_metadata(
toolchain,
ctx,
crate_type,
disable_pipelining = disable_pipelining,
):
return "hollow_rlib"

return ""

def _rust_library_impl(ctx):
"""The implementation of the `rust_library` rule.

Expand Down Expand Up @@ -146,6 +166,11 @@ def _rust_library_common(ctx, crate_type):
crate_root = crate_root_src(ctx.attr.name, ctx.attr.crate_name, ctx.files.srcs, crate_type)
srcs, compile_data, crate_root = transform_sources(ctx, ctx.files.srcs, ctx.files.compile_data, crate_root)

# Worker pipelining uses a single rustc invocation (no SVH mismatch risk),
# so disable_pipelining (which works around SVH issues in hollow rlib mode)
# should be ignored when worker pipelining is active.
effective_disable_pipelining = getattr(ctx.attr, "disable_pipelining", False) and not toolchain._worker_pipelining

# Determine unique hash for this rlib.
# Note that we don't include a hash for `cdylib` and `staticlib` since they are meant to be consumed externally
# and having a deterministic name is important since it ends up embedded in the executable. This is problematic
Expand All @@ -154,7 +179,16 @@ def _rust_library_common(ctx, crate_type):
if crate_type in ["cdylib", "staticlib"]:
output_hash = None
else:
output_hash = determine_output_hash(crate_root, ctx.label)
output_hash = determine_output_hash(
crate_root,
ctx.label,
salt = _pipelining_output_hash_salt(
ctx,
toolchain,
crate_type,
effective_disable_pipelining,
),
)

rust_lib_name = determine_lib_name(
crate_name,
Expand All @@ -166,24 +200,38 @@ def _rust_library_common(ctx, crate_type):
rust_metadata = None
rustc_rmeta_output = None
metadata_supports_pipelining = False

if can_build_metadata(
toolchain,
ctx,
crate_type,
disable_pipelining = getattr(ctx.attr, "disable_pipelining", False),
disable_pipelining = effective_disable_pipelining,
):
# The hollow rlib uses .rlib extension (not .rmeta) so rustc reads it as an
# rlib archive containing lib.rmeta with optimized MIR. It is placed in a
# "_hollow/" subdirectory so the full rlib and hollow rlib never appear in the
# same -Ldependency= search directory (which would cause E0463).
rust_metadata = ctx.actions.declare_file(
"_hollow/" + rust_lib_name[:-len(".rlib")] + "-hollow.rlib",
)
if can_use_metadata_for_pipelining(toolchain, crate_type) and toolchain._worker_pipelining and not is_exec_configuration(ctx):
# Worker pipelining: single rustc invocation emitting both .rmeta and .rlib.
# Use a real .rmeta file (not a hollow rlib) so downstream crates can use
# --extern name=path.rmeta. No -Zno-codegen, no RUSTC_BOOTSTRAP needed.
# The .rmeta is placed in a "_pipeline/" subdirectory so it never coexists
# with the .rlib in the same -Ldependency= search directory (which would
# cause E0463 if they're from different build runs with different SVHs).
# Exec-platform builds always use hollow rlib (with RUSTC_BOOTSTRAP=1)
# to maintain consistent SVH across all three pipelining configurations.
rust_metadata = ctx.actions.declare_file(
"_pipeline/" + rust_lib_name[:-len(".rlib")] + ".rmeta",
)
else:
# The hollow rlib uses .rlib extension (not .rmeta) so rustc reads it as an
# rlib archive containing lib.rmeta with optimized MIR. It is placed in a
# "_hollow/" subdirectory so the full rlib and hollow rlib never appear in the
# same -Ldependency= search directory (which would cause E0463).
rust_metadata = ctx.actions.declare_file(
"_hollow/" + rust_lib_name[:-len(".rlib")] + "-hollow.rlib",
)
rustc_rmeta_output = generate_output_diagnostics(ctx, rust_metadata)

metadata_supports_pipelining = (
can_use_metadata_for_pipelining(toolchain, crate_type) and
not ctx.attr.disable_pipelining
not effective_disable_pipelining
)

deps = transform_deps(deps)
Expand Down Expand Up @@ -589,6 +637,9 @@ RUSTC_ATTRS = {
"_extra_rustc_flags": attr.label(
default = Label("//rust/settings:extra_rustc_flags"),
),
"_incremental": attr.label(
default = Label("//rust/settings:experimental_incremental"),
),
"_is_proc_macro_dep": attr.label(
default = Label("//rust/private:is_proc_macro_dep"),
),
Expand All @@ -608,6 +659,9 @@ RUSTC_ATTRS = {
"_rustc_output_diagnostics": attr.label(
default = Label("//rust/settings:rustc_output_diagnostics"),
),
"_experimental_pipelined_compilation": attr.label(
default = Label("//rust/settings:experimental_pipelined_compilation"),
),
}

_COMMON_ATTRS = {
Expand Down
Loading