| # Copyright 2023 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. |
| |
| """Starlark implementation of cc_toolchain rule.""" |
| |
| load(":common/cc/cc_helper.bzl", "cc_helper") |
| load(":common/cc/cc_toolchain_provider_helper.bzl", "get_cc_toolchain_provider") |
| load(":common/cc/semantics.bzl", "semantics") |
| |
| cc_internal = _builtins.internal.cc_internal |
| ToolchainInfo = _builtins.toplevel.platform_common.ToolchainInfo |
| TemplateVariableInfo = _builtins.toplevel.platform_common.TemplateVariableInfo |
| apple_common = _builtins.toplevel.apple_common |
| FdoProfileInfo = _builtins.internal.FdoProfileInfo |
| FdoPrefetchHintsInfo = _builtins.internal.FdoPrefetchHintsInfo |
| PropellerOptimizeInfo = _builtins.internal.PropellerOptimizeInfo |
| PackageSpecificationInfo = _builtins.toplevel.PackageSpecificationInfo |
| CcToolchainConfigInfo = _builtins.toplevel.CcToolchainConfigInfo |
| MemProfProfileInfo = _builtins.internal.MemProfProfileInfo |
| |
| def _validate_toolchain(ctx, is_apple): |
| if not is_apple: |
| return |
| if ctx.attr._xcode_config[apple_common.XcodeVersionConfig].xcode_version() == None: |
| fail("Xcode version must be specified to use an Apple CROSSTOOL. If your Xcode version has " + |
| "changed recently, verify that \"xcode-select -p\" is correct and then try: " + |
| "\"bazel shutdown\" to re-run Xcode configuration") |
| |
| def _files(ctx, attr_name): |
| attr = getattr(ctx.attr, attr_name, None) |
| if attr != None and DefaultInfo in attr: |
| return attr[DefaultInfo].files |
| return depset() |
| |
| def _provider(attr, provider): |
| if attr != None and provider in attr: |
| return attr[provider] |
| return None |
| |
| def _latebound_libc(ctx, attr_name, implicit_attr_name): |
| if getattr(ctx.attr, implicit_attr_name, None) == None: |
| return attr_name |
| return implicit_attr_name |
| |
| def _full_inputs_for_link(ctx, linker_files, libc, is_apple_toolchain): |
| if not is_apple_toolchain: |
| return depset( |
| [ctx.file._interface_library_builder, ctx.file._link_dynamic_library_tool], |
| transitive = [linker_files, libc], |
| ) |
| return depset(transitive = [linker_files, libc]) |
| |
| def _label(ctx, attr_name): |
| if getattr(ctx.attr, attr_name, None) != None: |
| return getattr(ctx.attr, attr_name).label |
| return None |
| |
| def _package_specification_provider(ctx, allowlist_name): |
| possible_attr_names = ["_whitelist_" + allowlist_name, "_allowlist_" + allowlist_name] |
| for attr_name in possible_attr_names: |
| if hasattr(ctx.attr, attr_name): |
| package_specification_provider = getattr(ctx.attr, attr_name)[PackageSpecificationInfo] |
| if package_specification_provider != None: |
| return package_specification_provider |
| fail("Allowlist argument for " + allowlist_name + " not found") |
| |
| def _single_file(ctx, attr_name): |
| files = getattr(ctx.files, attr_name, []) |
| if len(files) > 1: |
| fail(ctx.label.name + " expected a single artifact", attr = attr_name) |
| if len(files) == 1: |
| return files[0] |
| return None |
| |
| def _attributes(ctx, is_apple): |
| grep_includes = None |
| if not semantics.is_bazel: |
| grep_includes = _single_file(ctx, "_grep_includes") |
| |
| latebound_libc = _latebound_libc(ctx, "libc_top", "_libc_top") |
| latebound_target_libc = _latebound_libc(ctx, "libc_top", "_target_libc_top") |
| |
| all_files = _files(ctx, "all_files") |
| return struct( |
| supports_param_files = ctx.attr.supports_param_files, |
| runtime_solib_dir_base = "_solib__" + cc_internal.escape_label(label = ctx.label), |
| fdo_prefetch_provider = _provider(ctx.attr._fdo_prefetch_hints, FdoPrefetchHintsInfo), |
| propeller_optimize_provider = _provider(ctx.attr._propeller_optimize, PropellerOptimizeInfo), |
| mem_prof_profile_provider = _provider(ctx.attr._memprof_profile, MemProfProfileInfo), |
| cc_toolchain_config_info = _provider(ctx.attr.toolchain_config, CcToolchainConfigInfo), |
| fdo_optimize_artifacts = ctx.files._fdo_optimize, |
| licenses_provider = cc_internal.licenses(ctx = ctx), |
| static_runtime_lib = ctx.attr.static_runtime_lib, |
| dynamic_runtime_lib = ctx.attr.dynamic_runtime_lib, |
| supports_header_parsing = ctx.attr.supports_header_parsing, |
| all_files = all_files, |
| compiler_files = _files(ctx, "compiler_files"), |
| strip_files = _files(ctx, "strip_files"), |
| objcopy_files = _files(ctx, "objcopy_files"), |
| fdo_optimize_label = _label(ctx, "_fdo_optimize"), |
| link_dynamic_library_tool = ctx.file._link_dynamic_library_tool, |
| grep_includes = grep_includes, |
| module_map = ctx.attr.module_map, |
| as_files = _files(ctx, "as_files"), |
| ar_files = _files(ctx, "ar_files"), |
| dwp_files = _files(ctx, "dwp_files"), |
| fdo_optimize_provider = _provider(ctx.attr._fdo_optimize, FdoProfileInfo), |
| module_map_artifact = _single_file(ctx, "module_map"), |
| all_files_including_libc = depset(transitive = [_files(ctx, "all_files"), _files(ctx, latebound_libc)]), |
| fdo_profile_provider = _provider(ctx.attr._fdo_profile, FdoProfileInfo), |
| cs_fdo_profile_provider = _provider(ctx.attr._csfdo_profile, FdoProfileInfo), |
| x_fdo_profile_provider = _provider(ctx.attr._xfdo_profile, FdoProfileInfo), |
| zipper = ctx.file._zipper, |
| linker_files = _full_inputs_for_link( |
| ctx, |
| _files(ctx, "linker_files"), |
| _files(ctx, latebound_libc), |
| is_apple, |
| ), |
| cc_toolchain_label = ctx.label, |
| coverage_files = _files(ctx, "coverage_files") or all_files, |
| compiler_files_without_includes = _files(ctx, "compiler_files_without_includes"), |
| libc = _files(ctx, latebound_libc), |
| target_libc = _files(ctx, latebound_target_libc), |
| libc_top_label = _label(ctx, latebound_libc), |
| target_libc_top_label = _label(ctx, latebound_target_libc), |
| if_so_builder = ctx.file._interface_library_builder, |
| allowlist_for_layering_check = _package_specification_provider(ctx, "disabling_parse_headers_and_layering_check_allowed"), |
| build_info_files = _provider(ctx.attr._build_info_translator, OutputGroupInfo), |
| ) |
| |
| def _cc_toolchain_impl(ctx): |
| _validate_toolchain(ctx, ctx.attr._is_apple) |
| xcode_config_info = None |
| if ctx.attr._is_apple: |
| xcode_config_info = ctx.attr._xcode_config[apple_common.XcodeVersionConfig] |
| attributes = _attributes(ctx, ctx.attr._is_apple) |
| providers = [] |
| if attributes.licenses_provider != None: |
| providers.append(attributes.licenses_provider) |
| |
| cc_toolchain = get_cc_toolchain_provider(ctx, attributes, xcode_config_info) |
| if cc_toolchain == None: |
| fail("This should never happen") |
| template_variable_info = TemplateVariableInfo( |
| cc_toolchain.get_additional_make_variables() | cc_helper.get_toolchain_global_make_variables(cc_toolchain), |
| ) |
| toolchain = ToolchainInfo( |
| cc = cc_toolchain, |
| # Add a clear signal that this is a CcToolchainProvider, since just "cc" is |
| # generic enough to possibly be re-used. |
| cc_provider_in_toolchain = True, |
| ) |
| providers.append(cc_toolchain) |
| providers.append(toolchain) |
| providers.append(template_variable_info) |
| providers.append(DefaultInfo(files = cc_toolchain.get_all_files_including_libc())) |
| return providers |
| |
| def make_cc_toolchain(cc_toolchain_attrs, **kwargs): |
| return rule( |
| implementation = _cc_toolchain_impl, |
| fragments = ["cpp", "platform", "apple"], |
| attrs = cc_toolchain_attrs, |
| **kwargs |
| ) |