diff --git a/cc/toolchains/BUILD b/cc/toolchains/BUILD index c9b29fc..cde0cb5 100644 --- a/cc/toolchains/BUILD +++ b/cc/toolchains/BUILD @@ -11,3 +11,11 @@ # 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. + +load("@bazel_skylib//rules:common_settings.bzl", "bool_flag") + +bool_flag( + name = "experimental_enable_rule_based_toolchains", + build_setting_default = False, + visibility = ["//visibility:public"], +) diff --git a/cc/toolchains/impl/toolchain_config.bzl b/cc/toolchains/impl/toolchain_config.bzl new file mode 100644 index 0000000..551b0d0 --- /dev/null +++ b/cc/toolchains/impl/toolchain_config.bzl @@ -0,0 +1,81 @@ +# 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. +"""Implementation of the cc_toolchain rule.""" + +load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") +load( + "//cc/toolchains:cc_toolchain_info.bzl", + "ActionTypeConfigSetInfo", + "ActionTypeSetInfo", + "ArgsListInfo", + "FeatureSetInfo", + "ToolchainConfigInfo", +) +load(":collect.bzl", "collect_action_types") +load(":toolchain_config_info.bzl", "toolchain_config_info") + +visibility([ + "//cc/toolchains/...", + "//tests/rule_based_toolchain/...", +]) + +def _cc_legacy_file_group_impl(ctx): + files = ctx.attr.config[ToolchainConfigInfo].files + + return [DefaultInfo(files = depset(transitive = [ + files[action] + for action in collect_action_types(ctx.attr.actions).to_list() + if action in files + ]))] + +cc_legacy_file_group = rule( + implementation = _cc_legacy_file_group_impl, + attrs = { + "actions": attr.label_list(providers = [ActionTypeSetInfo], mandatory = True), + "config": attr.label(providers = [ToolchainConfigInfo], mandatory = True), + }, +) + +def _cc_toolchain_config_impl(ctx): + if ctx.attr.features: + fail("Features is a reserved attribute in bazel. Did you mean 'toolchain_features'") + + if not ctx.attr._enabled[BuildSettingInfo].value and not ctx.attr.skip_experimental_flag_validation_for_test: + fail("Rule based toolchains are experimental. To use it, please add --//cc/toolchains:experimental_enable_rule_based_toolchains to your bazelrc") + + toolchain_config = toolchain_config_info( + label = ctx.label, + features = ctx.attr.toolchain_features + [ctx.attr._builtin_features], + action_type_configs = ctx.attr.action_type_configs, + args = ctx.attr.args, + ) + + return [ + # TODO: Transform toolchain_config into legacy cc_toolchain_config_info + toolchain_config, + ] + +cc_toolchain_config = rule( + implementation = _cc_toolchain_config_impl, + # @unsorted-dict-items + attrs = { + "action_type_configs": attr.label_list(providers = [ActionTypeConfigSetInfo]), + "args": attr.label_list(providers = [ArgsListInfo]), + "toolchain_features": attr.label_list(providers = [FeatureSetInfo]), + "skip_experimental_flag_validation_for_test": attr.bool(default = False), + "_builtin_features": attr.label(default = "//cc/toolchains/features:all_builtin_features"), + "_enabled": attr.label(default = "//cc/toolchains:experimental_enable_rule_based_toolchains"), + }, + provides = [ToolchainConfigInfo], +) diff --git a/tests/rule_based_toolchain/generics.bzl b/tests/rule_based_toolchain/generics.bzl index 90dfa21..17bd3a6 100644 --- a/tests/rule_based_toolchain/generics.bzl +++ b/tests/rule_based_toolchain/generics.bzl @@ -134,6 +134,6 @@ struct_subject = lambda **attrs: lambda value, *, meta: subjects.struct( dict_key_subject = lambda factory: lambda value, *, meta: struct( get = lambda key: factory( value[key], - meta = meta.derive(".get({})".format(key)), + meta = meta.derive("get({})".format(key)), ), ) diff --git a/tests/rule_based_toolchain/toolchain_config/BUILD b/tests/rule_based_toolchain/toolchain_config/BUILD index 4517b6a..56a0866 100644 --- a/tests/rule_based_toolchain/toolchain_config/BUILD +++ b/tests/rule_based_toolchain/toolchain_config/BUILD @@ -5,6 +5,7 @@ load("//cc/toolchains:feature.bzl", "cc_feature") load("//cc/toolchains:feature_set.bzl", "cc_feature_set") load("//cc/toolchains:tool.bzl", "cc_tool") load("//cc/toolchains/impl:external_feature.bzl", "cc_external_feature") +load("//cc/toolchains/impl:toolchain_config.bzl", "cc_legacy_file_group", "cc_toolchain_config") load("//tests/rule_based_toolchain:analysis_test_suite.bzl", "analysis_test_suite") load(":toolchain_config_test.bzl", "TARGETS", "TESTS") @@ -32,6 +33,29 @@ util.helper_target( args = ["c_compile_args"], ) +util.helper_target( + cc_toolchain_config, + name = "collects_files_toolchain_config", + action_type_configs = [":compile_config"], + args = [":c_compile_args"], + skip_experimental_flag_validation_for_test = True, + toolchain_features = [":compile_feature"], +) + +util.helper_target( + cc_legacy_file_group, + name = "collects_files_c_compile", + actions = ["//tests/rule_based_toolchain/actions:c_compile"], + config = ":collects_files_toolchain_config", +) + +util.helper_target( + cc_legacy_file_group, + name = "collects_files_cpp_compile", + actions = ["//tests/rule_based_toolchain/actions:cpp_compile"], + config = ":collects_files_toolchain_config", +) + util.helper_target( cc_args, name = "compile_args", 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 feee70a..83e453f 100644 --- a/tests/rule_based_toolchain/toolchain_config/toolchain_config_test.bzl +++ b/tests/rule_based_toolchain/toolchain_config/toolchain_config_test.bzl @@ -13,7 +13,7 @@ # limitations under the License. """Tests for the cc_args rule.""" -load("//cc/toolchains:cc_toolchain_info.bzl", "ActionTypeInfo") +load("//cc/toolchains:cc_toolchain_info.bzl", "ActionTypeInfo", "ToolchainConfigInfo") load("//cc/toolchains/impl:toolchain_config_info.bzl", _toolchain_config_info = "toolchain_config_info") load("//tests/rule_based_toolchain:subjects.bzl", "result_fn_wrapper", "subjects") @@ -21,6 +21,18 @@ visibility("private") toolchain_config_info = result_fn_wrapper(_toolchain_config_info) +_COLLECTED_CPP_COMPILE_FILES = [ + # From :compile_config's tool + "tests/rule_based_toolchain/testdata/bin", + # From :compile_feature's args + "tests/rule_based_toolchain/testdata/file2", +] + +_COLLECTED_C_COMPILE_FILES = _COLLECTED_CPP_COMPILE_FILES + [ + # From :c_compile_args + "tests/rule_based_toolchain/testdata/file1", +] + def _expect_that_toolchain(env, expr = None, **kwargs): return env.expect.that_value( value = toolchain_config_info(label = Label("//:toolchain"), **kwargs), @@ -164,32 +176,27 @@ def _tool_missing_requirements_invalid_test(env, targets): ) def _toolchain_collects_files_test(env, targets): - tc = _expect_that_toolchain( - env, - args = [targets.c_compile_args], - action_type_configs = [targets.compile_config], - features = [targets.compile_feature], - ).ok() - tc.files().get(targets.c_compile[ActionTypeInfo]).contains_exactly([ - # From :compile_config's tool - "tests/rule_based_toolchain/testdata/bin", - # From :c_compile_args - "tests/rule_based_toolchain/testdata/file1", - # From :compile_feature's args - "tests/rule_based_toolchain/testdata/file2", - ]) - tc.files().get(targets.cpp_compile[ActionTypeInfo]).contains_exactly([ - # From :compile_config's tool - "tests/rule_based_toolchain/testdata/bin", - # From :compile_feature's args - "tests/rule_based_toolchain/testdata/file2", - ]) + tc = env.expect.that_target( + targets.collects_files_toolchain_config, + ).provider(ToolchainConfigInfo) + 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) TARGETS = [ "//tests/rule_based_toolchain/actions:c_compile", "//tests/rule_based_toolchain/actions:cpp_compile", ":builtin_feature", ":compile_config", + ":collects_files_c_compile", + ":collects_files_cpp_compile", + ":collects_files_toolchain_config", ":compile_feature", ":c_compile_args", ":c_compile_config",