xref: /aosp_15_r20/external/bazelbuild-rules_cc/cc/toolchains/impl/collect.bzl (revision eed53cd41c5909d05eedc7ad9720bb158fd93452)
1*eed53cd4SHONG Yifan# Copyright 2024 The Bazel Authors. All rights reserved.
2*eed53cd4SHONG Yifan#
3*eed53cd4SHONG Yifan# Licensed under the Apache License, Version 2.0 (the "License");
4*eed53cd4SHONG Yifan# you may not use this file except in compliance with the License.
5*eed53cd4SHONG Yifan# You may obtain a copy of the License at
6*eed53cd4SHONG Yifan#
7*eed53cd4SHONG Yifan#     http://www.apache.org/licenses/LICENSE-2.0
8*eed53cd4SHONG Yifan#
9*eed53cd4SHONG Yifan# Unless required by applicable law or agreed to in writing, software
10*eed53cd4SHONG Yifan# distributed under the License is distributed on an "AS IS" BASIS,
11*eed53cd4SHONG Yifan# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*eed53cd4SHONG Yifan# See the License for the specific language governing permissions and
13*eed53cd4SHONG Yifan# limitations under the License.
14*eed53cd4SHONG Yifan"""Helper functions to allow us to collect data from attr.label_list."""
15*eed53cd4SHONG Yifan
16*eed53cd4SHONG Yifanload(
17*eed53cd4SHONG Yifan    "//cc/toolchains:cc_toolchain_info.bzl",
18*eed53cd4SHONG Yifan    "ActionTypeConfigSetInfo",
19*eed53cd4SHONG Yifan    "ActionTypeSetInfo",
20*eed53cd4SHONG Yifan    "ArgsListInfo",
21*eed53cd4SHONG Yifan    "FeatureSetInfo",
22*eed53cd4SHONG Yifan    "ToolInfo",
23*eed53cd4SHONG Yifan)
24*eed53cd4SHONG Yifan
25*eed53cd4SHONG Yifanvisibility([
26*eed53cd4SHONG Yifan    "//cc/toolchains/...",
27*eed53cd4SHONG Yifan    "//tests/rule_based_toolchain/...",
28*eed53cd4SHONG Yifan])
29*eed53cd4SHONG Yifan
30*eed53cd4SHONG Yifandef collect_provider(targets, provider):
31*eed53cd4SHONG Yifan    """Collects providers from a label list.
32*eed53cd4SHONG Yifan
33*eed53cd4SHONG Yifan    Args:
34*eed53cd4SHONG Yifan        targets: (List[Target]) An attribute from attr.label_list
35*eed53cd4SHONG Yifan        provider: (provider) The provider to look up
36*eed53cd4SHONG Yifan    Returns:
37*eed53cd4SHONG Yifan        A list of the providers
38*eed53cd4SHONG Yifan    """
39*eed53cd4SHONG Yifan    return [target[provider] for target in targets]
40*eed53cd4SHONG Yifan
41*eed53cd4SHONG Yifandef collect_defaultinfo(targets):
42*eed53cd4SHONG Yifan    """Collects DefaultInfo from a label list.
43*eed53cd4SHONG Yifan
44*eed53cd4SHONG Yifan    Args:
45*eed53cd4SHONG Yifan        targets: (List[Target]) An attribute from attr.label_list
46*eed53cd4SHONG Yifan    Returns:
47*eed53cd4SHONG Yifan        A list of the associated defaultinfo
48*eed53cd4SHONG Yifan    """
49*eed53cd4SHONG Yifan    return collect_provider(targets, DefaultInfo)
50*eed53cd4SHONG Yifan
51*eed53cd4SHONG Yifandef _make_collector(provider, field):
52*eed53cd4SHONG Yifan    def collector(targets, direct = [], transitive = []):
53*eed53cd4SHONG Yifan        # Avoid mutating what was passed in.
54*eed53cd4SHONG Yifan        transitive = transitive[:]
55*eed53cd4SHONG Yifan        for value in collect_provider(targets, provider):
56*eed53cd4SHONG Yifan            transitive.append(getattr(value, field))
57*eed53cd4SHONG Yifan        return depset(direct = direct, transitive = transitive)
58*eed53cd4SHONG Yifan
59*eed53cd4SHONG Yifan    return collector
60*eed53cd4SHONG Yifan
61*eed53cd4SHONG Yifancollect_action_types = _make_collector(ActionTypeSetInfo, "actions")
62*eed53cd4SHONG Yifancollect_features = _make_collector(FeatureSetInfo, "features")
63*eed53cd4SHONG Yifancollect_files = _make_collector(DefaultInfo, "files")
64*eed53cd4SHONG Yifan
65*eed53cd4SHONG Yifandef collect_data(ctx, targets):
66*eed53cd4SHONG Yifan    """Collects from a 'data' attribute.
67*eed53cd4SHONG Yifan
68*eed53cd4SHONG Yifan    This is distinguished from collect_files by the fact that data attributes
69*eed53cd4SHONG Yifan    attributes include runfiles.
70*eed53cd4SHONG Yifan
71*eed53cd4SHONG Yifan    Args:
72*eed53cd4SHONG Yifan        ctx: (Context) The ctx for the current rule
73*eed53cd4SHONG Yifan        targets: (List[Target]) A list of files or executables
74*eed53cd4SHONG Yifan
75*eed53cd4SHONG Yifan    Returns:
76*eed53cd4SHONG Yifan        A depset containing all files for each of the targets, and all runfiles
77*eed53cd4SHONG Yifan        required to run them.
78*eed53cd4SHONG Yifan    """
79*eed53cd4SHONG Yifan    return ctx.runfiles(transitive_files = collect_files(targets)).merge_all([
80*eed53cd4SHONG Yifan        info.default_runfiles
81*eed53cd4SHONG Yifan        for info in collect_defaultinfo(targets)
82*eed53cd4SHONG Yifan        if info.default_runfiles != None
83*eed53cd4SHONG Yifan    ])
84*eed53cd4SHONG Yifan
85*eed53cd4SHONG Yifandef collect_tools(ctx, targets, fail = fail):
86*eed53cd4SHONG Yifan    """Collects tools from a label_list.
87*eed53cd4SHONG Yifan
88*eed53cd4SHONG Yifan    Each entry in the label list may either be a cc_tool or a binary.
89*eed53cd4SHONG Yifan
90*eed53cd4SHONG Yifan    Args:
91*eed53cd4SHONG Yifan        ctx: (Context) The ctx for the current rule
92*eed53cd4SHONG Yifan        targets: (List[Target]) A list of targets. Each of these targets may be
93*eed53cd4SHONG Yifan          either a cc_tool or an executable.
94*eed53cd4SHONG Yifan        fail: (function) The fail function. Should only be used in tests.
95*eed53cd4SHONG Yifan
96*eed53cd4SHONG Yifan    Returns:
97*eed53cd4SHONG Yifan        A List[ToolInfo], with regular executables creating custom tool info.
98*eed53cd4SHONG Yifan    """
99*eed53cd4SHONG Yifan    tools = []
100*eed53cd4SHONG Yifan    for target in targets:
101*eed53cd4SHONG Yifan        info = target[DefaultInfo]
102*eed53cd4SHONG Yifan        if ToolInfo in target:
103*eed53cd4SHONG Yifan            tools.append(target[ToolInfo])
104*eed53cd4SHONG Yifan        elif info.files_to_run != None and info.files_to_run.executable != None:
105*eed53cd4SHONG Yifan            tools.append(ToolInfo(
106*eed53cd4SHONG Yifan                label = target.label,
107*eed53cd4SHONG Yifan                exe = info.files_to_run.executable,
108*eed53cd4SHONG Yifan                runfiles = collect_data(ctx, [target]),
109*eed53cd4SHONG Yifan                requires_any_of = tuple(),
110*eed53cd4SHONG Yifan                execution_requirements = tuple(),
111*eed53cd4SHONG Yifan            ))
112*eed53cd4SHONG Yifan        else:
113*eed53cd4SHONG Yifan            fail("Expected %s to be a cc_tool or a binary rule" % target.label)
114*eed53cd4SHONG Yifan
115*eed53cd4SHONG Yifan    return tools
116*eed53cd4SHONG Yifan
117*eed53cd4SHONG Yifandef collect_args_lists(targets, label):
118*eed53cd4SHONG Yifan    """Collects a label_list of ArgsListInfo into a single ArgsListInfo
119*eed53cd4SHONG Yifan
120*eed53cd4SHONG Yifan    Args:
121*eed53cd4SHONG Yifan        targets: (List[Target]) A label_list of targets providing ArgsListInfo
122*eed53cd4SHONG Yifan        label: The label to attach to the resulting ArgsListInfo
123*eed53cd4SHONG Yifan    Returns:
124*eed53cd4SHONG Yifan        An ArgsListInfo that is the result of joining all of the ArgsListInfos
125*eed53cd4SHONG Yifan        together.
126*eed53cd4SHONG Yifan    """
127*eed53cd4SHONG Yifan    args = []
128*eed53cd4SHONG Yifan    by_action = {}
129*eed53cd4SHONG Yifan    transitive_files = []
130*eed53cd4SHONG Yifan    for target in targets:
131*eed53cd4SHONG Yifan        args_list = target[ArgsListInfo]
132*eed53cd4SHONG Yifan        args.extend(args_list.args)
133*eed53cd4SHONG Yifan        transitive_files.extend([args_info.files for args_info in args_list.args])
134*eed53cd4SHONG Yifan        for value in args_list.by_action:
135*eed53cd4SHONG Yifan            out = by_action.setdefault(
136*eed53cd4SHONG Yifan                value.action,
137*eed53cd4SHONG Yifan                struct(args = [], transitive_files = [], action = value.action),
138*eed53cd4SHONG Yifan            )
139*eed53cd4SHONG Yifan            out.args.extend(value.args)
140*eed53cd4SHONG Yifan            out.transitive_files.append(value.files)
141*eed53cd4SHONG Yifan
142*eed53cd4SHONG Yifan    return ArgsListInfo(
143*eed53cd4SHONG Yifan        label = label,
144*eed53cd4SHONG Yifan        args = tuple(args),
145*eed53cd4SHONG Yifan        files = depset(transitive = transitive_files),
146*eed53cd4SHONG Yifan        by_action = tuple([
147*eed53cd4SHONG Yifan            struct(
148*eed53cd4SHONG Yifan                action = k,
149*eed53cd4SHONG Yifan                args = tuple(v.args),
150*eed53cd4SHONG Yifan                files = depset(transitive = v.transitive_files),
151*eed53cd4SHONG Yifan            )
152*eed53cd4SHONG Yifan            for k, v in by_action.items()
153*eed53cd4SHONG Yifan        ]),
154*eed53cd4SHONG Yifan    )
155*eed53cd4SHONG Yifan
156*eed53cd4SHONG Yifandef collect_action_type_config_sets(targets, label, fail = fail):
157*eed53cd4SHONG Yifan    """Collects several `cc_action_type_config` labels together.
158*eed53cd4SHONG Yifan
159*eed53cd4SHONG Yifan    Args:
160*eed53cd4SHONG Yifan        targets: (List[Target]) A list of targets providing ActionTypeConfigSetInfo
161*eed53cd4SHONG Yifan        label: The label to apply to the resulting config.
162*eed53cd4SHONG Yifan        fail: (function) The fail function. Should only be used in tests.
163*eed53cd4SHONG Yifan    Returns:
164*eed53cd4SHONG Yifan        A combined ActionTypeConfigSetInfo representing a variety of action
165*eed53cd4SHONG Yifan        types.
166*eed53cd4SHONG Yifan    """
167*eed53cd4SHONG Yifan    configs = {}
168*eed53cd4SHONG Yifan    for atcs in collect_provider(targets, ActionTypeConfigSetInfo):
169*eed53cd4SHONG Yifan        for action_type, config in atcs.configs.items():
170*eed53cd4SHONG Yifan            if action_type in configs:
171*eed53cd4SHONG Yifan                fail("The action type %s is configured by both %s and %s. Each action type may only be configured once." % (action_type.label, config.label, configs[action_type].label))
172*eed53cd4SHONG Yifan            configs[action_type] = config
173*eed53cd4SHONG Yifan    return ActionTypeConfigSetInfo(label = label, configs = configs)
174