diff --git a/rust/private/clippy.bzl b/rust/private/clippy.bzl index dd787d3ff0..05a3d83f90 100644 --- a/rust/private/clippy.bzl +++ b/rust/private/clippy.bzl @@ -137,7 +137,7 @@ def _clippy_aspect_impl(target, ctx): ctx.rule.file, ctx.rule.files, # Clippy doesn't need to invoke transitive linking, therefore doesn't need linkstamps. - depset([]), + [], toolchain, cc_toolchain, feature_configuration, diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl index f475087e77..02b99df7b4 100644 --- a/rust/private/rustc.bzl +++ b/rust/private/rustc.bzl @@ -224,19 +224,21 @@ def _is_proc_macro(crate_info): def collect_deps( deps, proc_macro_deps, - aliases): + aliases, + collect_linkstamps = False): """Walks through dependencies and collects the transitive dependencies. Args: deps (list): The deps from ctx.attr.deps. proc_macro_deps (list): The proc_macro deps from ctx.attr.proc_macro_deps. aliases (dict): A dict mapping aliased targets to their actual Crate information. + collect_linkstamps(bool): Whether to collect linkstamps from the deps' CcInfo. Returns: tuple: Returns a tuple of: DepInfo, BuildInfo, - linkstamps (depset[CcLinkstamp]): A depset of CcLinkstamps that need to be compiled and linked into all linked binaries when applicable. + linkstamps (list[CcLinkstamp]): A list of CcLinkstamps that need to be compiled and linked into all linked binaries when applicable. """ direct_crates = [] @@ -276,7 +278,12 @@ def collect_deps( cc_info = _get_cc_info(dep) dep_build_info = _get_build_info(dep) - if cc_info: + # These linkstamps will be used to register an action, and there is no other way + # to register an action for each member of a depset than flattening the depset as of 2021-10-12. + # Luckily, usually there is only one linkstamp in a build, and we only flatten the list on + # binary targets that perform transitive linking, so it's extremely unlikely that this call + # to `to_list()` will ever be a performance problem. + if collect_linkstamps and cc_info: for li in cc_info.linking_context.linker_inputs.to_list(): linkstamps.extend(li.linkstamps) @@ -380,7 +387,7 @@ def collect_deps( dep_env = build_info.dep_env if build_info else None, ), build_info, - depset(linkstamps), + linkstamps, ) def _collect_libs_from_linker_inputs(linker_inputs, use_pic): @@ -672,7 +679,7 @@ def collect_inputs( ctx (ctx): The rule's context object. file (struct): A struct containing files defined in label type attributes marked as `allow_single_file`. files (list): A list of all inputs (`ctx.files`). - linkstamps (depset): A depset of CcLinkstamps that need to be compiled and linked into all linked binaries. + linkstamps (list): A list of CcLinkstamps that need to be compiled and linked into all linked binaries. toolchain (rust_toolchain): The current `rust_toolchain`. cc_toolchain (CcToolchainInfo): The current `cc_toolchain`. feature_configuration (FeatureConfiguration): Feature configuration to be queried. @@ -764,34 +771,28 @@ def collect_inputs( ], ) - # Register linkstamps when linking with rustc (when linking with - # cc_common.link linkstamps are handled by cc_common.link itself). - if not experimental_use_cc_common_link and crate_info.type in ("bin", "cdylib"): - # There is no other way to register an action for each member of a depset than - # flattening the depset as of 2021-10-12. Luckily, usually there is only one linkstamp - # in a build, and we only flatten the list on binary targets that perform transitive linking, - # so it's extremely unlikely that this call to `to_list()` will ever be a performance - # problem. - for linkstamp in linkstamps.to_list(): - # The linkstamp output path is based on the binary crate - # name and the input linkstamp path. This is to disambiguate - # the linkstamp outputs produced by multiple binary crates - # that depend on the same linkstamp. We use the same pattern - # for the output name as the one used by native cc rules. - out_name = "_objs/" + crate_info.output.basename + "/" + linkstamp.file().path[:-len(linkstamp.file().extension)] + "o" - linkstamp_out = ctx.actions.declare_file(out_name) - linkstamp_outs.append(linkstamp_out) - cc_common.register_linkstamp_compile_action( - actions = ctx.actions, - cc_toolchain = cc_toolchain, - feature_configuration = feature_configuration, - source_file = linkstamp.file(), - output_file = linkstamp_out, - compilation_inputs = linkstamp.hdrs(), - inputs_for_validation = nolinkstamp_compile_inputs, - label_replacement = str(ctx.label), - output_replacement = crate_info.output.path, - ) + # TODO(zbarsky): It might be a bit clearer to collect the CcInfos in `collect_deps` and perform the expansion here. + for linkstamp in linkstamps: + # The linkstamp output path is based on the binary crate + # name and the input linkstamp path. This is to disambiguate + # the linkstamp outputs produced by multiple binary crates + # that depend on the same linkstamp. We use the same pattern + # for the output name as the one used by native cc rules. + file = linkstamp.file() + out_name = "_objs/" + crate_info.output.basename + "/" + file.path[:-len(file.extension)] + "o" + linkstamp_out = ctx.actions.declare_file(out_name) + linkstamp_outs.append(linkstamp_out) + cc_common.register_linkstamp_compile_action( + actions = ctx.actions, + cc_toolchain = cc_toolchain, + feature_configuration = feature_configuration, + source_file = file, + output_file = linkstamp_out, + compilation_inputs = linkstamp.hdrs(), + inputs_for_validation = nolinkstamp_compile_inputs, + label_replacement = str(ctx.label), + output_replacement = crate_info.output.path, + ) # If stamping is enabled include the volatile and stable status info file stamp_info = [ctx.version_file, ctx.info_file] if stamp else [] @@ -1246,6 +1247,9 @@ def rustc_compile_action( deps = crate_info_dict["deps"], proc_macro_deps = crate_info_dict["proc_macro_deps"], aliases = crate_info_dict["aliases"], + # Collect linkstamps to register when linking with rustc (when linking with + # cc_common.link linkstamps are handled by cc_common.link itself). + collect_linkstamps = not experimental_use_cc_common_link and crate_info.type in ("bin", "cdylib"), ) extra_disabled_features = [RUST_LINK_CC_FEATURE] if crate_info.type in ["bin", "cdylib"] and dep_info.transitive_noncrates.to_list(): @@ -1256,7 +1260,7 @@ def rustc_compile_action( feature_configuration = feature_configuration, has_grep_includes = hasattr(ctx.attr, "_use_grep_includes"), ): - linkstamps = depset([]) + linkstamps = [] # Determine if the build is currently running with --stamp stamp = is_stamping_enabled(attr) diff --git a/rust/private/rustdoc.bzl b/rust/private/rustdoc.bzl index 8b33d17065..ae86b407b9 100644 --- a/rust/private/rustdoc.bzl +++ b/rust/private/rustdoc.bzl @@ -107,7 +107,7 @@ def rustdoc_compile_action( ctx = ctx, file = ctx.file, files = ctx.files, - linkstamps = depset([]), + linkstamps = [], toolchain = toolchain, cc_toolchain = cc_toolchain, feature_configuration = feature_configuration, diff --git a/rust/private/unpretty.bzl b/rust/private/unpretty.bzl index e8a720a2ca..56405a113e 100644 --- a/rust/private/unpretty.bzl +++ b/rust/private/unpretty.bzl @@ -152,7 +152,7 @@ def _rust_unpretty_aspect_impl(target, ctx): ctx.rule.file, ctx.rule.files, # Rust expand doesn't need to invoke transitive linking, therefore doesn't need linkstamps. - depset([]), + [], toolchain, cc_toolchain, feature_configuration,