From b6b9eec8ea44ceca80d345c1b3b81412bbd97a81 Mon Sep 17 00:00:00 2001 From: Googler Date: Tue, 4 Apr 2023 03:52:24 -0700 Subject: [PATCH] Fix cc_shared_library to take into account unused CcInfos In https://github.com/bazelbuild/bazel/commit/f9008f698467eb85657711c608db16086a9908eb cc_shared_library was fixed to make sure that indirect top level deps were wrapped in "alwayslink" and not dropped by the linker. The loop which finds them didn't check for previously visited nodes under the assumption that it'd be quick to exit because a top level dep containing code would be found a few levels into the dependencies. This causes the code to hang in builds where there are custom C++ rules that do not propagate all the CcInfos from their deps. The code works using the structure of the graph recreated by the aspect, if it sees a target providing a dependency which isn't part of the static linker inputs, it assumes that it's an empty top level dependency and therefore we have to keep crawling up the graph to find the library that needs to be whole-archived. What was happening though was that the custom C++ rule cut off that dependency (even though it had code to link) and didn't make it part of the CcInfo it provided. The code would go many levels down and would revisit the same nodes over and over. RELNOTES:none PiperOrigin-RevId: 521717764 Change-Id: I0935ceb53572d6000d86cde518a6759b95c956a5 --- .../common/cc/experimental_cc_shared_library.bzl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/starlark/builtins_bzl/common/cc/experimental_cc_shared_library.bzl b/src/main/starlark/builtins_bzl/common/cc/experimental_cc_shared_library.bzl index 90b8ecd70a877a..a8a7b0d794b6be 100644 --- a/src/main/starlark/builtins_bzl/common/cc/experimental_cc_shared_library.bzl +++ b/src/main/starlark/builtins_bzl/common/cc/experimental_cc_shared_library.bzl @@ -270,14 +270,17 @@ def _find_top_level_linker_input_labels( top_level_linker_input_labels_set = {} nodes_to_check = list(nodes) + seen_nodes_set = {} for i in range(2147483647): if i == len(nodes_to_check): break node = nodes_to_check[i] must_add_children = False + node_str_owners = [] for owner in node.owners: owner_str = str(owner) + node_str_owners.append(owner_str) if owner_str in linker_inputs_to_be_linked_statically_map: must_add_children = True for linker_input in linker_inputs_to_be_linked_statically_map[owner_str]: @@ -290,8 +293,10 @@ def _find_top_level_linker_input_labels( # linker_inputs but didn't contribute any linker_input of its own. must_add_children = True - if must_add_children: + node_key = "".join(node_str_owners) + if must_add_children and node_key not in seen_nodes_set: nodes_to_check.extend(node.children) + seen_nodes_set[node_key] = True return top_level_linker_input_labels_set