1# Copyright (C) 2023 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15load("//build/bazel/rules/cc:cc_library_shared.bzl", "CcSharedLibraryOutputInfo")
16
17CcTestSharedLibsInfo = provider(
18    "Shared lib dependencies needed to run the cc_test targets",
19    fields = {
20        "shared_libs": "Shared libs that this cc test needs.",
21    },
22)
23
24def _collect_cc_libs_aspect_impl(target, ctx):
25    shared_libs = []
26    transitive_deps = []
27
28    rules_propagate_src = [
29        "_bssl_hash_injection",
30        "stripped_shared_library",
31        "versioned_shared_library",
32        "stripped_test",
33        "versioned_binary",
34    ]
35
36    if ctx.rule.kind == "_cc_library_shared_proxy":
37        shared_libs.append(target[CcSharedLibraryOutputInfo].output_file)
38        if hasattr(ctx.rule.attr, "shared"):
39            transitive_deps.append(ctx.rule.attr.shared[0])
40    elif ctx.rule.kind in ["cc_shared_library", "cc_test"]:
41        # Propagate along the dynamic_deps edges for binaries and shared libs
42        if hasattr(ctx.rule.attr, "dynamic_deps"):
43            for dep in ctx.rule.attr.dynamic_deps:
44                transitive_deps.append(dep)
45        if ctx.rule.kind == "cc_test" and hasattr(ctx.rule.attr, "deps"):
46            for dep in ctx.rule.attr.deps:
47                transitive_deps.append(dep)
48    elif ctx.rule.kind == "_cc_library_combiner" and hasattr(ctx.rule.attr, "androidmk_dynamic_deps"):
49        for dep in ctx.rule.attr.androidmk_dynamic_deps:
50            transitive_deps.append(dep)
51    elif ctx.rule.kind in rules_propagate_src and hasattr(ctx.rule.attr, "src"):
52        if ctx.rule.kind == "stripped_test":
53            transitive_deps.append(ctx.rule.attr.src[0])
54        else:
55            transitive_deps.append(ctx.rule.attr.src)
56
57    if ctx.rule.kind in ["stripped_test", "_cc_library_shared_proxy"] and hasattr(ctx.rule.attr, "runtime_deps"):
58        for dep in ctx.rule.attr.runtime_deps:
59            for output_file in dep[DefaultInfo].files.to_list():
60                if output_file.extension == "so":
61                    shared_libs.append(output_file)
62            transitive_deps.append(dep)
63
64    return [
65        CcTestSharedLibsInfo(
66            shared_libs = depset(
67                shared_libs,
68                transitive = [info[CcTestSharedLibsInfo].shared_libs for info in transitive_deps],
69            ),
70        ),
71    ]
72
73# The list of attributes in a cc dep graph where this aspect will traverse on.
74CC_ATTR_ASPECTS = [
75    "dynamic_deps",
76    "deps",
77    "shared",
78    "src",
79    "runtime_deps",
80    "static_deps",
81    "whole_archive_deps",
82    "androidmk_dynamic_deps",
83]
84
85collect_cc_libs_aspect = aspect(
86    implementation = _collect_cc_libs_aspect_impl,
87    provides = [CcTestSharedLibsInfo],
88    attr_aspects = CC_ATTR_ASPECTS,
89)
90