Skip to content
Open
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
5 changes: 3 additions & 2 deletions cargo/private/cargo_build_script.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ def _cargo_build_script_impl(ctx):
# Pull in env vars which may be required for the cc_toolchain to work (e.g. on OSX, the SDK version).
# We hope that the linker env is sufficient for the whole cc_toolchain.
cc_toolchain, feature_configuration = find_cc_toolchain(ctx)
linker, _, link_args, linker_env = get_linker_and_args(ctx, "bin", toolchain, cc_toolchain, feature_configuration, None)
linker, _, _, link_args, linker_env = get_linker_and_args(ctx, "bin", toolchain, cc_toolchain, feature_configuration, None)
env.update(**linker_env)
env["LD"] = linker
env["LDFLAGS"] = " ".join(_pwd_flags(link_args))
Expand Down Expand Up @@ -577,7 +577,7 @@ def _cargo_build_script_impl(ctx):
args = ctx.actions.args()
args.add(script, format = "--script=%s")
args.add(links, format = "--links=%s")
args.add(out_dir.path, format = "--out_dir=%s")
args.add_all([out_dir], format_each = "--out_dir=%s", expand_directories = False)
args.add(env_out, format = "--env_out=%s")
args.add(flags_out, format = "--flags_out=%s")
args.add(link_flags, format = "--link_flags=%s")
Expand Down Expand Up @@ -649,6 +649,7 @@ def _cargo_build_script_impl(ctx):
mnemonic = "CargoBuildScriptRun",
progress_message = "Running Cargo build script {}".format(pkg_name),
env = env,
execution_requirements = {"supports-path-mapping": "1"},
toolchain = None,
use_default_shell_env = use_default_shell_env,
)
Expand Down
2 changes: 1 addition & 1 deletion extensions/bindgen/private/bindgen.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ def _rust_bindgen_impl(ctx):
for define in ctx.attr.cc_lib[CcInfo].compilation_context.defines.to_list():
args.add("-D" + define)

_, _, _, linker_env = get_linker_and_args(ctx, "bin", rust_toolchain, cc_toolchain, feature_configuration, None)
_, _, _, _, linker_env = get_linker_and_args(ctx, "bin", rust_toolchain, cc_toolchain, feature_configuration, None)
env.update(**linker_env)

# Set the dynamic linker search path so that clang uses the libstdcxx from the toolchain.
Expand Down
47 changes: 35 additions & 12 deletions rust/private/rustc.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ load(
"relativize",
)

def _file_dirname(file):
"""Returns the dirname of a file.

Used as a ``map_each`` callback so that Bazel can apply path mapping
(``--experimental_output_paths=strip``) to the resulting string.
"""
return file.dirname

# This feature is disabled unless one of the dependencies is a cc_library.
# Authors of C++ toolchains can place linker flags that should only be applied
# when linking with C objects in a feature with this name, or require this
Expand Down Expand Up @@ -419,13 +427,15 @@ def get_linker_and_args(ctx, crate_type, toolchain, cc_toolchain, feature_config
Returns:
tuple: A tuple of the following items:
- (str): The tool path for given action.
- (File or None): The linker File object for path mapping, or None when the cc_toolchain provides the linker.
- (bool): Whether or not the linker is a direct driver (e.g. `ld`) vs a wrapper (e.g. `gcc`).
- (sequence): A flattened command line flags for given action.
- (dict): Environment variables to be set for given action.
"""
user_link_flags = get_cc_user_link_flags(ctx)

ld = None
ld_file = None # File object for path mapping, when available
ld_is_direct_driver = False
link_args = []
link_env = {}
Expand Down Expand Up @@ -473,7 +483,8 @@ def get_linker_and_args(ctx, crate_type, toolchain, cc_toolchain, feature_config
ld_is_direct_driver = False

if not ld or toolchain.linker_preference == "rust":
ld = toolchain.linker.path
ld_file = toolchain.linker
ld = ld_file.path
ld_is_direct_driver = toolchain.linker_type == "direct"

# When using rust-lld directly, we still need library search paths from cc_toolchain
Expand Down Expand Up @@ -539,7 +550,7 @@ def get_linker_and_args(ctx, crate_type, toolchain, cc_toolchain, feature_config
for element in link_env["LIB"].split(";")
])

return ld, ld_is_direct_driver, link_args, link_env
return ld, ld_file, ld_is_direct_driver, link_args, link_env

def _symlink_for_ambiguous_lib(actions, toolchain, crate_info, lib):
"""Constructs a disambiguating symlink for a library dependency.
Expand Down Expand Up @@ -727,7 +738,7 @@ def collect_inputs(
Returns:
tuple: A tuple: A tuple of the following items:
- (list): A list of all build info `OUT_DIR` File objects
- (str): The `OUT_DIR` of the current build info
- (File): The `OUT_DIR` tree artifact of the current build info, or None
- (File): An optional path to a generated environment file from a `cargo_build_script` target
- (depset[File]): All direct and transitive build flag files from the current build info
- (list[File]): Linkstamp outputs
Expand Down Expand Up @@ -999,8 +1010,16 @@ def construct_arguments(
components = "${{pwd}}/{}/{}".format(ctx.label.workspace_root, ctx.label.package).split("/")
env["CARGO_MANIFEST_DIR"] = "/".join([c for c in components if c])

# Pass OUT_DIR via --set-env so it goes through Bazel's path mapping
# (--experimental_output_paths=strip). The env dict is NOT path-mapped;
# only Args objects are. out_dir is a tree artifact (directory File).
if out_dir != None:
env["OUT_DIR"] = "${pwd}/" + out_dir
process_wrapper_flags.add_all(
[out_dir],
before_each = "--set-env",
format_each = "OUT_DIR=${pwd}/%s",
expand_directories = False,
)

# Arguments for launching rustc from the process wrapper
rustc_path = ctx.actions.args()
Expand Down Expand Up @@ -1047,9 +1066,9 @@ def construct_arguments(
# Configure process_wrapper to terminate rustc when metadata are emitted
process_wrapper_flags.add("--rustc-quit-on-rmeta", "true")
if crate_info.rustc_rmeta_output:
process_wrapper_flags.add("--output-file", crate_info.rustc_rmeta_output.path)
process_wrapper_flags.add("--output-file", crate_info.rustc_rmeta_output)
elif crate_info.rustc_output:
process_wrapper_flags.add("--output-file", crate_info.rustc_output.path)
process_wrapper_flags.add("--output-file", crate_info.rustc_output)

rustc_flags.add(error_format, format = "--error-format=%s")

Expand All @@ -1065,7 +1084,7 @@ def construct_arguments(
rustc_flags.add(output_hash, format = "--codegen=extra-filename=-%s")

if output_dir:
rustc_flags.add(output_dir, format = "--out-dir=%s")
rustc_flags.add_all([crate_info.output], map_each = _file_dirname, format_each = "--out-dir=%s")

compilation_mode = get_compilation_mode_opts(ctx, toolchain)
rustc_flags.add(compilation_mode.opt_level, format = "--codegen=opt-level=%s")
Expand Down Expand Up @@ -1094,8 +1113,9 @@ def construct_arguments(
if linker_script:
rustc_flags.add(linker_script, format = "--codegen=link-arg=-T%s")

# Tell Rustc where to find the standard library (or libcore)
rustc_flags.add_all(toolchain.rust_std_paths, before_each = "-L", format_each = "%s")
# Tell Rustc where to find the standard library (or libcore).
# Use map_each for path mapping (--experimental_output_paths=strip).
rustc_flags.add_all(toolchain.rust_std_paths, map_each = _file_dirname, before_each = "-L", uniquify = True)
rustc_flags.add_all(rust_flags, map_each = map_flag)

# Gather data path from crate_info since it is inherited from real crate for rust_doc and rust_test
Expand All @@ -1122,7 +1142,7 @@ def construct_arguments(
else:
rpaths = depset()

ld, ld_is_direct_driver, link_args, link_env = get_linker_and_args(
ld, ld_file, ld_is_direct_driver, link_args, link_env = get_linker_and_args(
ctx,
crate_info.type,
toolchain,
Expand All @@ -1133,7 +1153,7 @@ def construct_arguments(
)

env.update(link_env)
rustc_flags.add(ld, format = "--codegen=linker=%s")
rustc_flags.add(ld_file if ld_file else ld, format = "--codegen=linker=%s")

# Split link args into individual "--codegen=link-arg=" flags to handle nested spaces.
# Additional context: https://github.com/rust-lang/rust/pull/36574
Expand Down Expand Up @@ -1524,6 +1544,7 @@ def rustc_compile_action(
),
toolchain = "@rules_rust//rust:toolchain_type",
resource_set = get_rustc_resource_set(toolchain),
execution_requirements = {"supports-path-mapping": "1"},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should this only be set if ld_file is not None?

)
if args_metadata:
ctx.actions.run(
Expand All @@ -1541,6 +1562,7 @@ def rustc_compile_action(
"" if len(srcs) == 1 else "s",
),
toolchain = "@rules_rust//rust:toolchain_type",
execution_requirements = {"supports-path-mapping": "1"},
)
elif hasattr(ctx.executable, "_bootstrap_process_wrapper"):
# Run without process_wrapper
Expand All @@ -1562,6 +1584,7 @@ def rustc_compile_action(
),
toolchain = "@rules_rust//rust:toolchain_type",
resource_set = get_rustc_resource_set(toolchain),
execution_requirements = {"supports-path-mapping": "1"},
)
else:
fail("No process wrapper was defined for {}".format(ctx.label))
Expand Down Expand Up @@ -2021,7 +2044,7 @@ def _process_build_scripts(
# We include the direct dep build_info because crates which use cargo build scripts may need to e.g. include_str! a generated file.
if build_info:
if build_info.out_dir:
out_dir = build_info.out_dir.path
out_dir = build_info.out_dir
direct_inputs.append(build_info.out_dir)
build_env_file = build_info.rustc_env
if build_info.flags:
Expand Down
2 changes: 1 addition & 1 deletion rust/toolchain.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ def _rust_toolchain_impl(ctx):
make_variables = make_variable_info,
rust_doc = sysroot.rustdoc,
rust_std = sysroot.rust_std,
rust_std_paths = depset([file.dirname for file in sysroot.rust_std.to_list()]),
rust_std_paths = sysroot.rust_std,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is now identical to the property above, use that instead at the call site?

rustc = sysroot.rustc,
rustc_lib = sysroot.rustc_lib,
rustfmt = sysroot.rustfmt,
Expand Down
20 changes: 19 additions & 1 deletion util/process_wrapper/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pub(crate) fn options() -> Result<Options, OptionError> {
let mut output_file = None;
let mut rustc_quit_on_rmeta_raw = None;
let mut rustc_output_format_raw = None;
let mut set_env_raw = None;
let mut flags = Flags::new();
let mut require_explicit_unstable_features = None;
flags.define_repeated_flag("--subst", "", &mut subst_mapping_raw);
Expand Down Expand Up @@ -121,6 +122,15 @@ pub(crate) fn options() -> Result<Options, OptionError> {
other -Zallow-features= is present in the rustc flags.",
&mut require_explicit_unstable_features,
);
flags.define_repeated_flag(
"--set-env",
"Set a child environment variable from a KEY=VALUE pair. \
Unlike the action env dict, values passed here go through \
Bazel's path mapping (--experimental_output_paths=strip) \
because they are conveyed via Args objects. \
The ${pwd} substitution is applied to values.",
&mut set_env_raw,
);

let mut child_args = match flags
.parse(env::args().collect())
Expand Down Expand Up @@ -157,7 +167,15 @@ pub(crate) fn options() -> Result<Options, OptionError> {
stable_status_file_raw.map_or_else(Vec::new, |s| read_stamp_status_to_array(s).unwrap());
let volatile_stamp_mappings =
volatile_status_file_raw.map_or_else(Vec::new, |s| read_stamp_status_to_array(s).unwrap());
let environment_file_block = env_from_files(env_file_raw.unwrap_or_default())?;
let mut environment_file_block = env_from_files(env_file_raw.unwrap_or_default())?;
// Merge --set-env KEY=VALUE pairs into the environment block.
// These arrive via Args objects and are path-mapped by Bazel.
for kv in set_env_raw.unwrap_or_default() {
let (key, val) = kv.split_once('=').ok_or_else(|| {
OptionError::Generic(format!("--set-env requires KEY=VALUE, got '{kv}'"))
})?;
environment_file_block.insert(key.to_owned(), val.to_owned());
}
let mut file_arguments = args_from_file(arg_file_raw.unwrap_or_default())?;
// Process --copy-output
let copy_output = copy_output_raw
Expand Down
Loading