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