# Copyright 2024 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Conversion helper functions to legacy cc_toolchain_config_info.""" load( "//cc:cc_toolchain_config_lib.bzl", legacy_action_config = "action_config", legacy_env_entry = "env_entry", legacy_env_set = "env_set", legacy_feature = "feature", legacy_feature_set = "feature_set", legacy_flag_group = "flag_group", legacy_flag_set = "flag_set", legacy_tool = "tool", legacy_with_feature_set = "with_feature_set", ) load( "//cc/toolchains:cc_toolchain_info.bzl", "ArgsListInfo", "FeatureInfo", ) visibility([ "//cc/toolchains/...", "//tests/rule_based_toolchain/...", ]) # Note that throughout this file, we sort anything for which the order is # nondeterministic (eg. depset's .to_list(), dictionary iteration). # This allows our tests to call equals() on the output, # and *may* provide better caching properties. def _convert_actions(actions): return sorted([action.name for action in actions.to_list()]) def convert_feature_constraint(constraint): return legacy_with_feature_set( features = sorted([ft.name for ft in constraint.all_of.to_list()]), not_features = sorted([ft.name for ft in constraint.none_of.to_list()]), ) def _convert_add_arg(add_arg): return [legacy_flag_group(flags = list(add_arg.args))] def _convert_args(args): actions = _convert_actions(args.actions) with_features = [ convert_feature_constraint(fc) for fc in args.requires_any_of ] flag_sets = [] if args.args: flag_groups = [] for add_args in args.args: flag_groups.extend(_convert_add_arg(add_args)) flag_sets.append(legacy_flag_set( actions = actions, with_features = with_features, flag_groups = flag_groups, )) env_sets = [] if args.env: env_sets.append(legacy_env_set( actions = actions, with_features = with_features, env_entries = [ legacy_env_entry( key = key, value = value, ) for key, value in args.env.items() ], )) return struct( flag_sets = flag_sets, env_sets = env_sets, ) def _convert_args_sequence(args_sequence): flag_sets = [] env_sets = [] for args in args_sequence: legacy_args = _convert_args(args) flag_sets.extend(legacy_args.flag_sets) env_sets.extend(legacy_args.env_sets) return struct(flag_sets = flag_sets, env_sets = env_sets) def convert_feature(feature): if feature.external: return None args = _convert_args_sequence(feature.args.args) return legacy_feature( name = feature.name, enabled = feature.enabled, flag_sets = args.flag_sets, env_sets = args.env_sets, implies = sorted([ft.name for ft in feature.implies.to_list()]), requires = [ legacy_feature_set(sorted([ feature.name for feature in requirement.features.to_list() ])) for requirement in feature.requires_any_of ], provides = [ mutex.name for mutex in feature.mutually_exclusive ], ) def convert_tool(tool): return legacy_tool( tool = tool.exe, execution_requirements = list(tool.execution_requirements), with_features = [ convert_feature_constraint(fc) for fc in tool.requires_any_of ], ) def _convert_action_type_config(atc): implies = sorted([ft.name for ft in atc.implies.to_list()]) if atc.args: implies.append("implied_by_%s" % atc.action_type.name) return legacy_action_config( action_name = atc.action_type.name, enabled = True, tools = [convert_tool(tool) for tool in atc.tools], implies = implies, ) def convert_toolchain(toolchain): """Converts a rule-based toolchain into the legacy providers. Args: toolchain: CcToolchainConfigInfo: The toolchain config to convert. Returns: A struct containing parameters suitable to pass to cc_common.create_cc_toolchain_config_info. """ features = [convert_feature(feature) for feature in toolchain.features] features.append(convert_feature(FeatureInfo( # We reserve names starting with implied_by. This ensures we don't # conflict with the name of a feature the user creates. name = "implied_by_always_enabled", enabled = True, args = ArgsListInfo(args = toolchain.args), implies = depset([]), requires_any_of = [], mutually_exclusive = [], external = False, ))) action_configs = [] for atc in toolchain.action_type_configs.values(): # Action configs don't take in an env like they do a flag set. # In order to support them, we create a feature with the env that the action # config will enable, and imply it in the action config. if atc.args: features.append(convert_feature(FeatureInfo( name = "implied_by_%s" % atc.action_type.name, enabled = False, args = ArgsListInfo(args = atc.args), implies = depset([]), requires_any_of = [], mutually_exclusive = [], external = False, ))) action_configs.append(_convert_action_type_config(atc)) return struct( features = sorted([ft for ft in features if ft != None], key = lambda ft: ft.name), action_configs = sorted(action_configs, key = lambda ac: ac.action_name), )