1# Copyright 2024 The Bazel Authors. All rights reserved. 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"""Test subjects for cc_toolchain_info providers.""" 15 16load("@bazel_skylib//lib:structs.bzl", "structs") 17load("@rules_testing//lib:truth.bzl", _subjects = "subjects") 18load( 19 "//cc/toolchains:cc_toolchain_info.bzl", 20 "ActionTypeInfo", 21 "ActionTypeSetInfo", 22 "ArgsInfo", 23 "ArgsListInfo", 24 "FeatureConstraintInfo", 25 "FeatureInfo", 26 "FeatureSetInfo", 27 "MutuallyExclusiveCategoryInfo", 28 "NestedArgsInfo", 29 "ToolCapabilityInfo", 30 "ToolConfigInfo", 31 "ToolInfo", 32 "ToolchainConfigInfo", 33) 34load(":generate_factory.bzl", "ProviderDepset", "ProviderSequence", "generate_factory") 35load(":generics.bzl", "dict_key_subject", "optional_subject", "result_subject", "struct_subject", _result_fn_wrapper = "result_fn_wrapper") 36 37visibility("//tests/rule_based_toolchain/...") 38 39# The default runfiles subject uses path instead of short_path. 40# This makes it rather awkward for copybara. 41runfiles_subject = lambda value, meta: _subjects.depset_file(value.files, meta = meta) 42 43# The string type has .equals(), which is all we can really do for an unknown 44# type. 45unknown_subject = _subjects.str 46 47# Directory depsets are quite complex, so just simplify them as a list of paths. 48# buildifier: disable=name-conventions 49_FakeDirectoryDepset = lambda value, *, meta: _subjects.collection([v.path for v in value.to_list()], meta = meta) 50 51# buildifier: disable=name-conventions 52_ActionTypeFactory = generate_factory( 53 ActionTypeInfo, 54 "ActionTypeInfo", 55 dict( 56 name = _subjects.str, 57 ), 58) 59 60# buildifier: disable=name-conventions 61_ActionTypeSetFactory = generate_factory( 62 ActionTypeSetInfo, 63 "ActionTypeInfo", 64 dict( 65 actions = ProviderDepset(_ActionTypeFactory), 66 ), 67) 68 69# buildifier: disable=name-conventions 70_MutuallyExclusiveCategoryFactory = generate_factory( 71 MutuallyExclusiveCategoryInfo, 72 "MutuallyExclusiveCategoryInfo", 73 dict(name = _subjects.str), 74) 75 76_FEATURE_FLAGS = dict( 77 name = _subjects.str, 78 enabled = _subjects.bool, 79 args = None, 80 implies = None, 81 requires_any_of = None, 82 mutually_exclusive = ProviderSequence(_MutuallyExclusiveCategoryFactory), 83 overridable = _subjects.bool, 84 external = _subjects.bool, 85 overrides = None, 86 allowlist_include_directories = _FakeDirectoryDepset, 87) 88 89# Break the dependency loop. 90# buildifier: disable=name-conventions 91_FakeFeatureFactory = generate_factory( 92 FeatureInfo, 93 "FeatureInfo", 94 _FEATURE_FLAGS, 95) 96 97# buildifier: disable=name-conventions 98_FeatureSetFactory = generate_factory( 99 FeatureSetInfo, 100 "FeatureSetInfo", 101 dict(features = ProviderDepset(_FakeFeatureFactory)), 102) 103 104# buildifier: disable=name-conventions 105_FeatureConstraintFactory = generate_factory( 106 FeatureConstraintInfo, 107 "FeatureConstraintInfo", 108 dict( 109 all_of = ProviderDepset(_FakeFeatureFactory), 110 none_of = ProviderDepset(_FakeFeatureFactory), 111 ), 112) 113 114_NESTED_ARGS_FLAGS = dict( 115 nested = None, 116 files = _subjects.depset_file, 117 iterate_over = optional_subject(_subjects.str), 118 legacy_flag_group = unknown_subject, 119 requires_types = _subjects.dict, 120 unwrap_options = _subjects.collection, 121) 122 123# buildifier: disable=name-conventions 124_FakeNestedArgsFactory = generate_factory( 125 NestedArgsInfo, 126 "NestedArgsInfo", 127 _NESTED_ARGS_FLAGS, 128) 129 130# buildifier: disable=name-conventions 131_NestedArgsFactory = generate_factory( 132 NestedArgsInfo, 133 "NestedArgsInfo", 134 _NESTED_ARGS_FLAGS | dict( 135 nested = ProviderSequence(_FakeNestedArgsFactory), 136 ), 137) 138 139# buildifier: disable=name-conventions 140_ArgsFactory = generate_factory( 141 ArgsInfo, 142 "ArgsInfo", 143 dict( 144 actions = ProviderDepset(_ActionTypeFactory), 145 env = _subjects.dict, 146 files = _subjects.depset_file, 147 # Use .factory so it's not inlined. 148 nested = optional_subject(_NestedArgsFactory.factory), 149 requires_any_of = ProviderSequence(_FeatureConstraintFactory), 150 allowlist_include_directories = _FakeDirectoryDepset, 151 ), 152) 153 154# buildifier: disable=name-conventions 155_ArgsListFactory = generate_factory( 156 ArgsListInfo, 157 "ArgsListInfo", 158 dict( 159 args = ProviderSequence(_ArgsFactory), 160 by_action = lambda values, *, meta: dict_key_subject(struct_subject( 161 args = _subjects.collection, 162 files = _subjects.depset_file, 163 ))({value.action: value for value in values}, meta = meta), 164 files = _subjects.depset_file, 165 allowlist_include_directories = _FakeDirectoryDepset, 166 ), 167) 168 169# buildifier: disable=name-conventions 170_FeatureFactory = generate_factory( 171 FeatureInfo, 172 "FeatureInfo", 173 _FEATURE_FLAGS | dict( 174 # Use .factory so it's not inlined. 175 args = _ArgsListFactory.factory, 176 implies = ProviderDepset(_FakeFeatureFactory), 177 requires_any_of = ProviderSequence(_FeatureSetFactory), 178 overrides = optional_subject(_FakeFeatureFactory.factory), 179 ), 180) 181 182# buildifier: disable=name-conventions 183_ToolCapabilityFactory = generate_factory( 184 ToolCapabilityInfo, 185 "ToolCapabilityInfo", 186 dict( 187 name = _subjects.str, 188 ), 189) 190 191# buildifier: disable=name-conventions 192_ToolFactory = generate_factory( 193 ToolInfo, 194 "ToolInfo", 195 dict( 196 exe = _subjects.file, 197 runfiles = runfiles_subject, 198 execution_requirements = _subjects.collection, 199 allowlist_include_directories = _FakeDirectoryDepset, 200 capabilities = ProviderSequence(_ToolCapabilityFactory), 201 ), 202) 203 204# buildifier: disable=name-conventions 205_ToolConfigFactory = generate_factory( 206 ToolConfigInfo, 207 "ToolConfigInfo", 208 dict( 209 configs = dict_key_subject(_ToolFactory.factory), 210 ), 211) 212 213# buildifier: disable=name-conventions 214_ToolchainConfigFactory = generate_factory( 215 ToolchainConfigInfo, 216 "ToolchainConfigInfo", 217 dict( 218 features = ProviderDepset(_FeatureFactory), 219 enabled_features = _subjects.collection, 220 tool_map = optional_subject(_ToolConfigFactory.factory), 221 args = ProviderSequence(_ArgsFactory), 222 files = dict_key_subject(_subjects.depset_file), 223 allowlist_include_directories = _FakeDirectoryDepset, 224 ), 225) 226 227FACTORIES = [ 228 _ActionTypeFactory, 229 _ActionTypeSetFactory, 230 _NestedArgsFactory, 231 _ArgsFactory, 232 _ArgsListFactory, 233 _MutuallyExclusiveCategoryFactory, 234 _FeatureFactory, 235 _FeatureConstraintFactory, 236 _FeatureSetFactory, 237 _ToolFactory, 238 _ToolConfigFactory, 239 _ToolchainConfigFactory, 240] 241 242result_fn_wrapper = _result_fn_wrapper 243 244subjects = struct( 245 **(structs.to_dict(_subjects) | dict( 246 unknown = unknown_subject, 247 result = result_subject, 248 optional = optional_subject, 249 struct = struct_subject, 250 runfiles = runfiles_subject, 251 dict_key = dict_key_subject, 252 ) | {factory.name: factory.factory for factory in FACTORIES}) 253) 254