| # pylint: disable=g-bad-file-header | 
 | # Copyright 2016 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. | 
 | """ | 
 | Helpers for CC Toolchains. | 
 |  | 
 | Rules that require a CC toolchain should call `use_cc_toolchain` and `find_cc_toolchain` | 
 | to depend on and find a cc toolchain. | 
 |  | 
 | * When https://github.com/bazelbuild/bazel/issues/7260 is **not** flipped, current | 
 |   C++ toolchain is selected using the legacy mechanism (`--crosstool_top`, | 
 |   `--cpu`, `--compiler`). For that to work the rule needs to declare an | 
 |   `_cc_toolchain` attribute, e.g. | 
 |  | 
 |     foo = rule( | 
 |         implementation = _foo_impl, | 
 |         attrs = { | 
 |             "_cc_toolchain": attr.label( | 
 |                 default = Label( | 
 |                     "@rules_cc//cc:current_cc_toolchain", | 
 |                 ), | 
 |             ), | 
 |         }, | 
 |     ) | 
 |  | 
 | * When https://github.com/bazelbuild/bazel/issues/7260 **is** flipped, current | 
 |   C++ toolchain is selected using the toolchain resolution mechanism | 
 |   (`--platforms`). For that to work the rule needs to declare a dependency on | 
 |   C++ toolchain type: | 
 |  | 
 |     load(":find_cc_toolchain/bzl", "use_cc_toolchain") | 
 |  | 
 |     foo = rule( | 
 |         implementation = _foo_impl, | 
 |         toolchains = use_cc_toolchain(), | 
 |     ) | 
 |  | 
 | We advise to depend on both `_cc_toolchain` attr and on the toolchain type for | 
 | the duration of the migration. After | 
 | https://github.com/bazelbuild/bazel/issues/7260 is flipped (and support for old | 
 | Bazel version is not needed), it's enough to only keep the toolchain type. | 
 | """ | 
 |  | 
 | load("//cc/common:cc_common.bzl", "cc_common") | 
 |  | 
 | CC_TOOLCHAIN_TYPE = Label("@bazel_tools//tools/cpp:toolchain_type") | 
 |  | 
 | CC_TOOLCHAIN_ATTRS = { | 
 |     # Needed for Bazel 6.x and 7.x compatibility. | 
 |     "_cc_toolchain": attr.label(default = Label("@rules_cc//cc:current_cc_toolchain")), | 
 | } | 
 |  | 
 | def find_cc_toolchain(ctx, *, mandatory = True): | 
 |     """ | 
 | Returns the current `CcToolchainInfo`. | 
 |  | 
 |     Args: | 
 |       ctx: The rule context for which to find a toolchain. | 
 |       mandatory: (bool) If this is set to False, this function will return None | 
 |         rather than fail if no toolchain is found. | 
 |  | 
 |     Returns: | 
 |       A CcToolchainInfo or None if the c++ toolchain is declared as | 
 |       optional, mandatory is False and no toolchain has been found. | 
 |     """ | 
 |  | 
 |     # Check the incompatible flag for toolchain resolution. | 
 |     if hasattr(cc_common, "is_cc_toolchain_resolution_enabled_do_not_use") and cc_common.is_cc_toolchain_resolution_enabled_do_not_use(ctx = ctx): | 
 |         if not CC_TOOLCHAIN_TYPE in ctx.toolchains: | 
 |             fail("In order to use find_cc_toolchain, your rule has to depend on C++ toolchain. See find_cc_toolchain.bzl docs for details.") | 
 |         toolchain_info = ctx.toolchains[CC_TOOLCHAIN_TYPE] | 
 |         if toolchain_info == None: | 
 |             if not mandatory: | 
 |                 return None | 
 |  | 
 |             # No cpp toolchain was found, so report an error. | 
 |             fail("Unable to find a CC toolchain using toolchain resolution. Target: %s, Platform: %s, Exec platform: %s" % | 
 |                  (ctx.label, ctx.fragments.platform.platform, ctx.fragments.platform.host_platform)) | 
 |         if hasattr(toolchain_info, "cc_provider_in_toolchain") and hasattr(toolchain_info, "cc"): | 
 |             return toolchain_info.cc | 
 |         return toolchain_info | 
 |  | 
 |     # Fall back to the legacy implicit attribute lookup. | 
 |     if hasattr(ctx.attr, "_cc_toolchain"): | 
 |         return ctx.attr._cc_toolchain[cc_common.CcToolchainInfo] | 
 |  | 
 |     # We didn't find anything. | 
 |     if not mandatory: | 
 |         return None | 
 |     fail("In order to use find_cc_toolchain, your rule has to depend on C++ toolchain. See find_cc_toolchain.bzl docs for details.") | 
 |  | 
 | def find_cpp_toolchain(ctx): | 
 |     """Deprecated, use `find_cc_toolchain` instead. | 
 |  | 
 |     Args: | 
 |       ctx: See `find_cc_toolchain`. | 
 |  | 
 |     Returns: | 
 |       A CcToolchainInfo. | 
 |     """ | 
 |     return find_cc_toolchain(ctx) | 
 |  | 
 | def use_cc_toolchain(mandatory = True): | 
 |     """ | 
 |     Helper to depend on the cc toolchain. | 
 |  | 
 |     Usage: | 
 |     ``` | 
 |     my_rule = rule( | 
 |         toolchains = [other toolchain types] + use_cc_toolchain(), | 
 |     ) | 
 |     ``` | 
 |  | 
 |     Args: | 
 |       mandatory: Whether or not it should be an error if the toolchain cannot be resolved. | 
 |  | 
 |     Returns: | 
 |       A list that can be used as the value for `rule.toolchains`. | 
 |     """ | 
 |     return [config_common.toolchain_type(CC_TOOLCHAIN_TYPE, mandatory = mandatory)] |