diff --git a/BUILD.bazel b/BUILD.bazel index 11411d4f1d..fc561cced9 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -1,5 +1,5 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") -load("//rust:defs.bzl", "capture_clippy_output", "clippy_flags", "error_format", "extra_exec_rustc_flag", "extra_exec_rustc_flags", "extra_rustc_flag", "extra_rustc_flags", "is_proc_macro_dep", "is_proc_macro_dep_enabled") +load("//rust:defs.bzl", "capture_clippy_output", "clippy_flags", "error_format", "extra_exec_rustc_flag", "extra_exec_rustc_flags", "extra_rustc_flag", "extra_rustc_flags", "is_proc_macro_dep", "is_proc_macro_dep_enabled", "source_path_prefix") exports_files(["LICENSE"]) @@ -76,6 +76,15 @@ extra_exec_rustc_flag( visibility = ["//visibility:public"], ) +# This setting may be used to override the prefix for source paths rustc embeds into build artifacts. +# Setting this setting to a fixed value (e.g., "/source/") can help achieve reproducible builds and +# improve cache utilization. +source_path_prefix( + name = "source_path_prefix", + build_setting_default = ".", + visibility = ["//visibility:public"], +) + # This setting is used by the clippy rules. See https://bazelbuild.github.io/rules_rust/rust_clippy.html label_flag( name = "clippy.toml", diff --git a/rust/defs.bzl b/rust/defs.bzl index 92c8a77406..d8a5631366 100644 --- a/rust/defs.bzl +++ b/rust/defs.bzl @@ -49,6 +49,7 @@ load( _extra_rustc_flags = "extra_rustc_flags", _is_proc_macro_dep = "is_proc_macro_dep", _is_proc_macro_dep_enabled = "is_proc_macro_dep_enabled", + _source_path_prefix = "source_path_prefix", ) load( "//rust/private:rustdoc.bzl", @@ -124,6 +125,9 @@ is_proc_macro_dep = _is_proc_macro_dep is_proc_macro_dep_enabled = _is_proc_macro_dep_enabled # See @rules_rust//rust/private:rustc.bzl for a complete description. +source_path_prefix = _source_path_prefix +# See @rules_rust//rust/private:rustc.bzl for a complete description. + rust_common = _rust_common # See @rules_rust//rust/private:common.bzl for a complete description. diff --git a/rust/private/rust.bzl b/rust/private/rust.bzl index 8ae8a0b215..e1e84f9bdf 100644 --- a/rust/private/rust.bzl +++ b/rust/private/rust.bzl @@ -663,6 +663,9 @@ _common_attrs = { "_extra_rustc_flags": attr.label( default = Label("//:extra_rustc_flags"), ), + "_source_path_prefix": attr.label( + default = Label("//:source_path_prefix"), + ), "_import_macro_dep": attr.label( default = Label("//util/import"), cfg = "exec", diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl index c837ac1b08..e06b87717e 100644 --- a/rust/private/rustc.bzl +++ b/rust/private/rustc.bzl @@ -90,6 +90,11 @@ is_proc_macro_dep_enabled = rule( build_setting = config.bool(flag = True), ) +SourcePathPrefixInfo = provider( + doc = "Remap source path prefixes in all output, including compiler diagnostics, debug information, macro expansions to a path", + fields = {"source_path_prefix": "string The path to substitute ${pwd} for"}, +) + def _get_rustc_env(attr, toolchain, crate_name): """Gathers rustc environment variables @@ -718,7 +723,6 @@ def construct_arguments( force_all_deps_direct = False, force_link = False, stamp = False, - remap_path_prefix = "", use_json_output = False, build_metadata = False, force_depend_on_objects = False): @@ -747,7 +751,6 @@ def construct_arguments( force_link (bool, optional): Whether to add link flags to the command regardless of `emit`. stamp (bool, optional): Whether or not workspace status stamping is enabled. For more details see https://docs.bazel.build/versions/main/user-manual.html#flag--stamp - remap_path_prefix (str, optional): A value used to remap `${pwd}` to. If set to None, no prefix will be set. use_json_output (bool): Have rustc emit json and process_wrapper parse json messages to output rendered output. build_metadata (bool): Generate CLI arguments for building *only* .rmeta files. This requires use_json_output. force_depend_on_objects (bool): Force using `.rlib` object files instead of metadata (`.rmeta`) files even if they are available. @@ -884,8 +887,8 @@ def construct_arguments( rustc_flags.add("--codegen=debuginfo=" + compilation_mode.debug_info) # For determinism to help with build distribution and such - if remap_path_prefix != None: - rustc_flags.add("--remap-path-prefix=${{pwd}}={}".format(remap_path_prefix)) + if hasattr(ctx.attr, "_source_path_prefix"): + rustc_flags.add("--remap-path-prefix=${{pwd}}={}".format(ctx.attr._source_path_prefix[SourcePathPrefixInfo].source_path_prefix)) if emit: rustc_flags.add("--emit=" + ",".join(emit_with_paths)) @@ -1861,6 +1864,19 @@ extra_rustc_flag = rule( build_setting = config.string(flag = True, allow_multiple = True), ) +def _source_path_prefix_impl(ctx): + return SourcePathPrefixInfo(source_path_prefix = ctx.build_setting_value) + +source_path_prefix = rule( + doc = ( + "Specify the path for the compiler to remap the source path prefix in all output, including compiler diagnostics," + + "debug information, and macro expansions with `--@rules_rust//:static_path_prefix`." + + "Setting the prefix a fixed value enables reproducible builds that do not depend on the location of the source directory." + ), + implementation = _source_path_prefix_impl, + build_setting = config.string(flag = True), +) + def _extra_exec_rustc_flags_impl(ctx): return ExtraExecRustcFlagsInfo(extra_exec_rustc_flags = ctx.build_setting_value) diff --git a/rust/private/rustdoc.bzl b/rust/private/rustdoc.bzl index ba3a12cec7..21c6075884 100644 --- a/rust/private/rustdoc.bzl +++ b/rust/private/rustdoc.bzl @@ -120,7 +120,6 @@ def rustdoc_compile_action( build_env_files = build_env_files, build_flags_files = build_flags_files, emit = [], - remap_path_prefix = None, force_link = True, force_depend_on_objects = is_test, ) diff --git a/tools/rust_analyzer/aquery.rs b/tools/rust_analyzer/aquery.rs index 7a04599938..8efbd520ce 100644 --- a/tools/rust_analyzer/aquery.rs +++ b/tools/rust_analyzer/aquery.rs @@ -4,6 +4,7 @@ use std::option::Option; use std::path::Path; use std::path::PathBuf; use std::process::Command; +use std::iter::FromIterator; use anyhow::Context; use serde::Deserialize; @@ -162,40 +163,10 @@ fn path_from_fragments( /// Read all crate specs, deduplicating crates with the same ID. This happens when /// a rust_test depends on a rust_library, for example. +/// GL: Currently this does nothing, because of situations in which cycles are encountered +/// Upstream issue: https://github.com/bazelbuild/rules_rust/issues/1589 fn consolidate_crate_specs(crate_specs: Vec) -> anyhow::Result> { - let mut consolidated_specs: BTreeMap = BTreeMap::new(); - for mut spec in crate_specs.into_iter() { - log::debug!("{:?}", spec); - if let Some(existing) = consolidated_specs.get_mut(&spec.crate_id) { - existing.deps.extend(spec.deps); - - spec.cfg.retain(|cfg| !existing.cfg.contains(cfg)); - existing.cfg.extend(spec.cfg); - - // display_name should match the library's crate name because Rust Analyzer - // seems to use display_name for matching crate entries in rust-project.json - // against symbols in source files. For more details, see - // https://github.com/bazelbuild/rules_rust/issues/1032 - if spec.crate_type == "rlib" { - existing.display_name = spec.display_name; - existing.crate_type = "rlib".into(); - } - - // For proc-macro crates that exist within the workspace, there will be a - // generated crate-spec in both the fastbuild and opt-exec configuration. - // Prefer proc macro paths with an opt-exec component in the path. - if let Some(dylib_path) = spec.proc_macro_dylib_path.as_ref() { - const OPT_PATH_COMPONENT: &str = "-opt-exec-"; - if dylib_path.contains(OPT_PATH_COMPONENT) { - existing.proc_macro_dylib_path.replace(dylib_path.clone()); - } - } - } else { - consolidated_specs.insert(spec.crate_id.clone(), spec); - } - } - - Ok(consolidated_specs.into_values().collect()) + Ok(BTreeSet::from_iter(crate_specs)) } #[cfg(test)] diff --git a/version.bzl b/version.bzl index 993c60e4d8..d969cc5673 100644 --- a/version.bzl +++ b/version.bzl @@ -1,3 +1,3 @@ """The version of rules_rust.""" -VERSION = "0.15.0" +VERSION = "0.15.1"