diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 0bd25f84e..83104abd0 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -132,8 +132,10 @@ tasks: build_targets: *build_targets_bazel_6 test_targets: *test_targets_bazel_6 - ubuntu_rule_based_toolchains: - name: Ubuntu rule-based toolchains +# Rules-based toolchains + ubuntu_rule_based_toolchains_bazel_7: + name: Ubuntu rule-based toolchains (Bazel 7) + bazel: 7.2.1 platform: ubuntu1804 working_directory: examples/rule_based_toolchain build_flags: @@ -143,8 +145,53 @@ tasks: test_targets: - "//..." - macos_rule_based_toolchains: - name: macOS rule-based toolchains + ubuntu_rule_based_toolchains_bazel_8: + name: Ubuntu rule-based toolchains (Bazel 8) + bazel: 8.5.0 + platform: ubuntu1804 + working_directory: examples/rule_based_toolchain + build_flags: + - "--enable_bzlmod" + build_targets: + - "//..." + test_targets: + - "//..." + + ubuntu_rule_based_toolchains_bazel_9: + name: Ubuntu rule-based toolchains (Bazel 9) + bazel: 9.0.0rc3 + platform: ubuntu1804 + working_directory: examples/rule_based_toolchain + build_flags: + - "--enable_bzlmod" + build_targets: + - "//..." + test_targets: + - "//..." + + macos_rule_based_toolchains_bazel_7: + name: macOS rule-based toolchains (Bazel 7) + bazel: 7.2.1 + platform: macos + working_directory: examples/rule_based_toolchain + build_flags: + - "--enable_bzlmod" + build_targets: + - "//..." + + macos_rule_based_toolchains_bazel_8: + name: macOS rule-based toolchains (Bazel 8) + bazel: 8.5.0 + platform: macos + working_directory: examples/rule_based_toolchain + build_flags: + - "--enable_bzlmod" + build_targets: + - "//..." + + macos_rule_based_toolchains_bazel_9: + name: macOS rule-based toolchains (Bazel 9) + bazel: 9.0.0rc3 platform: macos working_directory: examples/rule_based_toolchain build_flags: diff --git a/cc/private/rules_impl/cc_toolchain.bzl b/cc/private/rules_impl/cc_toolchain.bzl index 16c13ea9b..bb5f5d3bc 100644 --- a/cc/private/rules_impl/cc_toolchain.bzl +++ b/cc/private/rules_impl/cc_toolchain.bzl @@ -19,11 +19,19 @@ load("//cc/common:cc_helper.bzl", "cc_helper") load("//cc/common:semantics.bzl", "semantics") load("//cc/private/rules_impl/fdo:fdo_context.bzl", "create_fdo_context") load("//cc/toolchains:cc_toolchain_config_info.bzl", "CcToolchainConfigInfo") +load("//cc/toolchains:cc_toolchain_info.bzl", "ActionTypeSetInfo", "ToolConfigInfo") +load("//cc/toolchains:legacy_file_group.bzl", "LEGACY_FILE_GROUPS") +load("//cc/toolchains/impl:collect.bzl", "collect_action_types") +load("//cc/toolchains/impl:toolchain_config.bzl", "CC_TOOLCHAIN_CONFIG_PUBLIC_ATTRS", "cc_toolchain_config_impl_helper") load(":cc_toolchain_provider_helper.bzl", "get_cc_toolchain_provider") ToolchainInfo = platform_common.ToolchainInfo TemplateVariableInfo = platform_common.TemplateVariableInfo +LEGACY_ACTION_SET_DEPS = [ + action for actions in LEGACY_FILE_GROUPS.values() for action in actions +] + def _files(ctx, attr_name): attr = getattr(ctx.attr, attr_name, None) files = [] @@ -81,42 +89,80 @@ def _attributes(ctx): latebound_libc = _latebound_libc(ctx, "libc_top", "_libc_top") - all_files = _files(ctx, "all_files") + if ctx.attr.toolchain_config: + for key in CC_TOOLCHAIN_CONFIG_PUBLIC_ATTRS.keys(): + if getattr(ctx.attr, key): + fail("Must not pass %s when passing `toolchain_config`" % key) + + cc_toolchain_config_info = ctx.attr.toolchain_config[CcToolchainConfigInfo] + all_files = _files(ctx, "all_files") + + legacy_file_groups = { + "as_files": _files(ctx, "as_files"), + "ar_files": _files(ctx, "ar_files"), + "dwp_files": _files(ctx, "dwp_files"), + "compiler_files": _files(ctx, "compiler_files"), + "strip_files": _files(ctx, "strip_files"), + "objcopy_files": _files(ctx, "objcopy_files"), + "coverage_files": _files(ctx, "coverage_files") or all_files, + } + + linker_files = _files(ctx, "linker_files") + + else: + if not ctx.attr.tool_map: + fail("Must pass `tool_map` when not passing `toolchain_config`") + toolchain_config_info, cc_toolchain_config_info = cc_toolchain_config_impl_helper(ctx) + + legacy_action_set_lookup = { + target.label: target + for target in ctx.attr._legacy_action_sets + } + + legacy_file_groups = {} + for group, actions in LEGACY_FILE_GROUPS.items(): + action_targets = [ + legacy_action_set_lookup[action] for action in actions + ] + legacy_file_groups[group] = depset(transitive = [ + toolchain_config_info.files[action] + for action in collect_action_types(action_targets).to_list() + if action in toolchain_config_info.files + ]) + + all_files = depset(transitive = legacy_file_groups.values()) + legacy_file_groups["coverage_files"] = legacy_file_groups["coverage_files"] or all_files + linker_files = legacy_file_groups.pop("linker_files") + return struct( supports_param_files = ctx.attr.supports_param_files, runtime_solib_dir_base = "_solib__" + cc_common.escape_label(label = ctx.label), - cc_toolchain_config_info = _provider(ctx.attr.toolchain_config, CcToolchainConfigInfo), + cc_toolchain_config_info = cc_toolchain_config_info, 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"), link_dynamic_library_tool = ctx.file._link_dynamic_library_tool, grep_includes = grep_includes, aggregate_ddi = _single_file(ctx, "_aggregate_ddi"), generate_modmap = _single_file(ctx, "_generate_modmap"), module_map = ctx.attr.module_map, - as_files = _files(ctx, "as_files"), - ar_files = _files(ctx, "ar_files"), - dwp_files = _files(ctx, "dwp_files"), module_map_artifact = _single_file(ctx, "module_map"), - all_files_including_libc = depset(transitive = [_files(ctx, "all_files"), _files(ctx, latebound_libc)]), + all_files_including_libc = depset(transitive = [all_files, _files(ctx, latebound_libc)]), zipper = ctx.file._zipper, linker_files = _full_inputs_for_link( ctx, - _files(ctx, "linker_files"), + linker_files, _files(ctx, latebound_libc), ), 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), libc_top_label = _label(ctx, latebound_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), + **legacy_file_groups ) def _cc_toolchain_impl(ctx): @@ -200,7 +246,6 @@ crosstool_config.toolchain. ), "all_files": attr.label( allow_files = True, - mandatory = True, doc = """ Collection of all cc_toolchain artifacts. These artifacts will be added as inputs to all rules_cc related actions (with the exception of actions that are using more precise sets of @@ -214,7 +259,6 @@ rules using C++ toolchain.

""", ), "compiler_files": attr.label( allow_files = True, - mandatory = True, doc = """ Collection of all cc_toolchain artifacts required for compile actions.""", ), @@ -226,13 +270,11 @@ input discovery is supported (currently Google-only).""", ), "strip_files": attr.label( allow_files = True, - mandatory = True, doc = """ Collection of all cc_toolchain artifacts required for strip actions.""", ), "objcopy_files": attr.label( allow_files = True, - mandatory = True, doc = """ Collection of all cc_toolchain artifacts required for objcopy actions.""", ), @@ -248,13 +290,11 @@ Collection of all cc_toolchain artifacts required for archiving actions.""", ), "linker_files": attr.label( allow_files = True, - mandatory = True, doc = """ Collection of all cc_toolchain artifacts required for linking actions.""", ), "dwp_files": attr.label( allow_files = True, - mandatory = True, doc = """ Collection of all cc_toolchain artifacts required for dwp actions.""", ), @@ -307,7 +347,6 @@ Set to True when cc_toolchain supports header parsing actions.""", ), "toolchain_config": attr.label( allow_files = False, - mandatory = True, providers = [CcToolchainConfigInfo], doc = """ The label of the rule providing cc_toolchain_config_info.""", @@ -340,5 +379,16 @@ The label of the rule providing cc_toolchain_config_info.""", default = semantics.BUILD_INFO_TRANLATOR_LABEL, providers = [OutputGroupInfo], ), + "_legacy_action_sets": attr.label_list( + default = LEGACY_ACTION_SET_DEPS, + providers = [ActionTypeSetInfo], + ), + } | CC_TOOLCHAIN_CONFIG_PUBLIC_ATTRS | { + # Override tool_map to make it optional. + "tool_map": attr.label( + cfg = "exec", + providers = [ToolConfigInfo], + ), + "_builtin_features": attr.label(default = "//cc/toolchains/features:all_builtin_features"), } | semantics.cpp_modules_tools(), # buildifier: disable=unsorted-dict-items ) diff --git a/cc/toolchains/BUILD b/cc/toolchains/BUILD index 5ebf9c8f3..5393bd148 100644 --- a/cc/toolchains/BUILD +++ b/cc/toolchains/BUILD @@ -28,6 +28,7 @@ bzl_library( "//cc/private/rules_impl:toolchain_rules", "//cc/private/rules_impl/fdo:fdo_rules", "//cc/toolchains/impl:toolchain_impl_rules", + "@bazel_features//:features", "@bazel_skylib//rules/directory:glob", "@cc_compatibility_proxy//:proxy_bzl", ], diff --git a/cc/toolchains/cc_toolchain_info.bzl b/cc/toolchains/cc_toolchain_info.bzl index 38148b463..3f2ae55b4 100644 --- a/cc/toolchains/cc_toolchain_info.bzl +++ b/cc/toolchains/cc_toolchain_info.bzl @@ -18,6 +18,7 @@ # Once it's stabilized, we *may* consider opening up parts of the API, or we may # decide to just require users to use the public user-facing rules. visibility([ + "//cc/private/rules_impl/...", "//cc/toolchains/...", "//tests/rule_based_toolchain/...", ]) diff --git a/cc/toolchains/impl/collect.bzl b/cc/toolchains/impl/collect.bzl index 671bb65b4..de06c8791 100644 --- a/cc/toolchains/impl/collect.bzl +++ b/cc/toolchains/impl/collect.bzl @@ -22,6 +22,7 @@ load( ) visibility([ + "//cc/private/rules_impl/...", "//cc/toolchains/...", "//tests/rule_based_toolchain/...", ]) diff --git a/cc/toolchains/impl/toolchain_config.bzl b/cc/toolchains/impl/toolchain_config.bzl index 1f6efefe5..0057c0f1f 100644 --- a/cc/toolchains/impl/toolchain_config.bzl +++ b/cc/toolchains/impl/toolchain_config.bzl @@ -29,6 +29,7 @@ load(":legacy_converter.bzl", "convert_toolchain") load(":toolchain_config_info.bzl", "toolchain_config_info") visibility([ + "//cc/private/rules_impl/...", "//cc/toolchains/...", "//tests/rule_based_toolchain/...", ]) @@ -50,7 +51,14 @@ cc_legacy_file_group = rule( }, ) -def _cc_toolchain_config_impl(ctx): +def cc_toolchain_config_impl_helper(ctx): + """Main implementation for _cc_toolchain_config_impl, reused for rules-based toolchains + + Args: + ctx: Rule context + Returns: + toolchain_config_info and cc_toolchain_config_info providers""" + if ctx.attr.features: fail("Features is a reserved attribute in bazel. Did you mean 'known_features' or 'enabled_features'?") @@ -66,7 +74,7 @@ def _cc_toolchain_config_impl(ctx): legacy = convert_toolchain(toolchain_config) - return [ + return ( toolchain_config, cc_common.create_cc_toolchain_config_info( ctx = ctx, @@ -90,6 +98,13 @@ def _cc_toolchain_config_impl(ctx): abi_version = "", abi_libc_version = "", ), + ) + +def _cc_toolchain_config_impl(ctx): + toolchain_config, cc_toolchain_config_info = cc_toolchain_config_impl_helper(ctx) + return [ + toolchain_config, + cc_toolchain_config_info, # This allows us to support all_files. # If all_files was simply an alias to # //cc/toolchains/actions:all_actions, @@ -98,19 +113,21 @@ def _cc_toolchain_config_impl(ctx): DefaultInfo(files = depset(transitive = toolchain_config.files.values())), ] +CC_TOOLCHAIN_CONFIG_PUBLIC_ATTRS = { + # Attributes new to this rule. + "compiler": attr.string(default = ""), + "cpu": attr.string(default = ""), + "tool_map": attr.label(providers = [ToolConfigInfo], mandatory = True), + "args": attr.label_list(providers = [ArgsListInfo]), + "known_features": attr.label_list(providers = [FeatureSetInfo]), + "enabled_features": attr.label_list(providers = [FeatureSetInfo]), + "artifact_name_patterns": attr.label_list(providers = [ArtifactNamePatternInfo]), + "make_variables": attr.label_list(providers = [MakeVariableInfo]), +} + cc_toolchain_config = rule( implementation = _cc_toolchain_config_impl, - # @unsorted-dict-items - attrs = { - # Attributes new to this rule. - "compiler": attr.string(default = ""), - "cpu": attr.string(default = ""), - "tool_map": attr.label(providers = [ToolConfigInfo], mandatory = True), - "args": attr.label_list(providers = [ArgsListInfo]), - "known_features": attr.label_list(providers = [FeatureSetInfo]), - "enabled_features": attr.label_list(providers = [FeatureSetInfo]), - "artifact_name_patterns": attr.label_list(providers = [ArtifactNamePatternInfo]), - "make_variables": attr.label_list(providers = [MakeVariableInfo]), + attrs = CC_TOOLCHAIN_CONFIG_PUBLIC_ATTRS | { "_builtin_features": attr.label(default = "//cc/toolchains/features:all_builtin_features"), }, provides = [ToolchainConfigInfo], diff --git a/cc/toolchains/legacy_file_group.bzl b/cc/toolchains/legacy_file_group.bzl new file mode 100644 index 000000000..a170a194c --- /dev/null +++ b/cc/toolchains/legacy_file_group.bzl @@ -0,0 +1,46 @@ +# Copyright 2018 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. +""""Mapping of legacy file groups""" + +# Taken from https://bazel.build/docs/cc-toolchain-config-reference#actions +# TODO: This is best-effort. Update this with the correct file groups once we +# work out what actions correspond to what file groups. +LEGACY_FILE_GROUPS = { + "ar_files": [ + Label("//cc/toolchains/actions:ar_actions"), + ], + "as_files": [ + Label("//cc/toolchains/actions:assembly_actions"), + ], + "compiler_files": [ + Label("//cc/toolchains/actions:cc_flags_make_variable"), + Label("//cc/toolchains/actions:c_compile"), + Label("//cc/toolchains/actions:cpp_compile"), + Label("//cc/toolchains/actions:cpp_header_parsing"), + ], + # There are no actions listed for coverage and objcopy in action_names.bzl. + "coverage_files": [], + "dwp_files": [ + Label("//cc/toolchains/actions:dwp"), + ], + "linker_files": [ + Label("//cc/toolchains/actions:cpp_link_dynamic_library"), + Label("//cc/toolchains/actions:cpp_link_nodeps_dynamic_library"), + Label("//cc/toolchains/actions:cpp_link_executable"), + ], + "objcopy_files": [], + "strip_files": [ + Label("//cc/toolchains/actions:strip"), + ], +} diff --git a/cc/toolchains/toolchain.bzl b/cc/toolchains/toolchain.bzl index fa41163ab..a97f37b6b 100644 --- a/cc/toolchains/toolchain.bzl +++ b/cc/toolchains/toolchain.bzl @@ -13,7 +13,9 @@ # limitations under the License. """Implementation of the cc_toolchain rule.""" +load("@bazel_features//private:util.bzl", _bazel_version_ge = "ge") load("//cc/toolchains:cc_toolchain.bzl", _cc_toolchain = "cc_toolchain") +load("//cc/toolchains:legacy_file_group.bzl", "LEGACY_FILE_GROUPS") load( "//cc/toolchains/impl:toolchain_config.bzl", "cc_legacy_file_group", @@ -22,38 +24,6 @@ load( visibility("public") -# Taken from https://bazel.build/docs/cc-toolchain-config-reference#actions -# TODO: This is best-effort. Update this with the correct file groups once we -# work out what actions correspond to what file groups. -_LEGACY_FILE_GROUPS = { - "ar_files": [ - Label("//cc/toolchains/actions:ar_actions"), - ], - "as_files": [ - Label("//cc/toolchains/actions:assembly_actions"), - ], - "compiler_files": [ - Label("//cc/toolchains/actions:cc_flags_make_variable"), - Label("//cc/toolchains/actions:c_compile"), - Label("//cc/toolchains/actions:cpp_compile"), - Label("//cc/toolchains/actions:cpp_header_parsing"), - ], - # There are no actions listed for coverage and objcopy in action_names.bzl. - "coverage_files": [], - "dwp_files": [ - Label("//cc/toolchains/actions:dwp"), - ], - "linker_files": [ - Label("//cc/toolchains/actions:cpp_link_dynamic_library"), - Label("//cc/toolchains/actions:cpp_link_nodeps_dynamic_library"), - Label("//cc/toolchains/actions:cpp_link_executable"), - ], - "objcopy_files": [], - "strip_files": [ - Label("//cc/toolchains/actions:strip"), - ], -} - def cc_toolchain( *, name, @@ -161,9 +131,40 @@ def cc_toolchain( **kwargs: [common attributes](https://bazel.build/reference/be/common-definitions#common-attributes) that should be applied to all rules created by this macro. """ + cc_toolchain_visibility = kwargs.pop("visibility", default = None) - for group in _LEGACY_FILE_GROUPS: + if _bazel_version_ge("9.0.0-pre.20250911"): + _cc_toolchain( + name = name, + tool_map = tool_map, + args = args, + artifact_name_patterns = artifact_name_patterns, + make_variables = make_variables, + known_features = known_features, + enabled_features = enabled_features, + compiler = compiler, + cpu = select({ + Label("//cc/toolchains/impl:darwin_aarch64"): "darwin_arm64", + Label("//cc/toolchains/impl:darwin_x86_64"): "darwin_x86_64", + Label("//cc/toolchains/impl:linux_aarch64"): "aarch64", + Label("//cc/toolchains/impl:linux_x86_64"): "k8", + Label("//cc/toolchains/impl:windows_x86_32"): "win32", + Label("//cc/toolchains/impl:windows_x86_64"): "win64", + "//conditions:default": "", + }), + dynamic_runtime_lib = dynamic_runtime_lib, + libc_top = libc_top, + module_map = module_map, + static_runtime_lib = static_runtime_lib, + supports_header_parsing = supports_header_parsing, + supports_param_files = supports_param_files, + visibility = cc_toolchain_visibility, + **kwargs + ) + return + + for group in LEGACY_FILE_GROUPS: if group in kwargs: fail("Don't use legacy file groups such as %s. Instead, associate files with `cc_tool` or `cc_args` rules." % group) @@ -192,7 +193,7 @@ def cc_toolchain( # Provides ar_files, compiler_files, linker_files, ... legacy_file_groups = {} - for group, actions in _LEGACY_FILE_GROUPS.items(): + for group, actions in LEGACY_FILE_GROUPS.items(): group_name = "_{}_{}".format(name, group) cc_legacy_file_group( name = group_name, diff --git a/examples/rule_based_toolchain/MODULE.bazel b/examples/rule_based_toolchain/MODULE.bazel index cdd551733..340b03b03 100644 --- a/examples/rule_based_toolchain/MODULE.bazel +++ b/examples/rule_based_toolchain/MODULE.bazel @@ -4,7 +4,7 @@ module( ) bazel_dep(name = "platforms", version = "0.0.10") -bazel_dep(name = "googletest", version = "1.15.2") +bazel_dep(name = "googletest", version = "1.17.0.bcr.2") bazel_dep(name = "bazel_skylib", version = "1.7.1") bazel_dep(name = "rules_cc") local_path_override( diff --git a/examples/rule_based_toolchain/quick_test.cc b/examples/rule_based_toolchain/quick_test.cc index a50fded7f..047a7fa29 100644 --- a/examples/rule_based_toolchain/quick_test.cc +++ b/examples/rule_based_toolchain/quick_test.cc @@ -27,5 +27,6 @@ TEST(Dynamic, ProperlyLinked) { } TEST(Asm, ProperlyLinked) { - EXPECT_EQ(asm_answer, 0xFE4B67C4); + constexpr int kExpectedAsmAnswer = static_cast(0xFE4B67C4u); + EXPECT_EQ(asm_answer, kExpectedAsmAnswer); } diff --git a/tests/rule_based_toolchain/toolchain_config/toolchain_config_test.bzl b/tests/rule_based_toolchain/toolchain_config/toolchain_config_test.bzl index 1047203c4..2b9b286fc 100644 --- a/tests/rule_based_toolchain/toolchain_config/toolchain_config_test.bzl +++ b/tests/rule_based_toolchain/toolchain_config/toolchain_config_test.bzl @@ -178,13 +178,6 @@ def _toolchain_collects_files_test(env, targets): tc.files().get(targets.c_compile[ActionTypeInfo]).contains_exactly(_COLLECTED_C_COMPILE_FILES) tc.files().get(targets.cpp_compile[ActionTypeInfo]).contains_exactly(_COLLECTED_CPP_COMPILE_FILES) - env.expect.that_target( - targets.collects_files_c_compile, - ).default_outputs().contains_exactly(_COLLECTED_C_COMPILE_FILES) - env.expect.that_target( - targets.collects_files_cpp_compile, - ).default_outputs().contains_exactly(_COLLECTED_CPP_COMPILE_FILES) - legacy = convert_toolchain(tc.actual) env.expect.that_collection(legacy.features).contains_exactly([ legacy_feature( @@ -263,8 +256,6 @@ TARGETS = [ "//tests/rule_based_toolchain/actions:cpp_compile", ":builtin_feature", ":compile_tool_map", - ":collects_files_c_compile", - ":collects_files_cpp_compile", ":collects_files_toolchain_config", ":compile_feature", ":c_compile_args",