aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGoogler <noreply@google.com>2024-03-05 16:04:23 -0800
committerCopybara-Service <copybara-worker@google.com>2024-03-05 16:04:53 -0800
commitde4aaa64725ed9f8f11acf96458a6b082cfcb490 (patch)
treefd5fbca153711a1450aea52c229015acf744de7c
parent94d4760a89ceea80a7fa60deb3b2b5349425d6c5 (diff)
downloadbazelbuild-rules_cc-de4aaa64725ed9f8f11acf96458a6b082cfcb490.tar.gz
Allow cc_toolchain_info rule to be used as a parameter to pass into native.cc_toolchain(config = ...)
BEGIN_PUBLIC Allow cc_toolchain_info rule to be used as a parameter to pass into native.cc_toolchain(config = ...) END_PUBLIC PiperOrigin-RevId: 613000772 Change-Id: I8348e2cbb4aa7d0a523341dcaf1e2c2bc647f640
-rw-r--r--cc/toolchains/impl/legacy_converter.bzl190
-rw-r--r--cc/toolchains/impl/toolchain_config.bzl36
-rw-r--r--cc/toolchains/tool.bzl2
-rw-r--r--tests/rule_based_toolchain/features/BUILD1
-rw-r--r--tests/rule_based_toolchain/features/features_test.bzl52
-rw-r--r--tests/rule_based_toolchain/tool/BUILD3
-rw-r--r--tests/rule_based_toolchain/tool/tool_test.bzl18
-rw-r--r--tests/rule_based_toolchain/toolchain_config/BUILD18
-rw-r--r--tests/rule_based_toolchain/toolchain_config/toolchain_config_test.bzl69
9 files changed, 377 insertions, 12 deletions
diff --git a/cc/toolchains/impl/legacy_converter.bzl b/cc/toolchains/impl/legacy_converter.bzl
new file mode 100644
index 0000000..a216f66
--- /dev/null
+++ b/cc/toolchains/impl/legacy_converter.bzl
@@ -0,0 +1,190 @@
+# 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),
+ )
diff --git a/cc/toolchains/impl/toolchain_config.bzl b/cc/toolchains/impl/toolchain_config.bzl
index 551b0d0..185f242 100644
--- a/cc/toolchains/impl/toolchain_config.bzl
+++ b/cc/toolchains/impl/toolchain_config.bzl
@@ -23,6 +23,7 @@ load(
"ToolchainConfigInfo",
)
load(":collect.bzl", "collect_action_types")
+load(":legacy_converter.bzl", "convert_toolchain")
load(":toolchain_config_info.bzl", "toolchain_config_info")
visibility([
@@ -61,21 +62,54 @@ def _cc_toolchain_config_impl(ctx):
args = ctx.attr.args,
)
+ legacy = convert_toolchain(toolchain_config)
+
return [
- # TODO: Transform toolchain_config into legacy cc_toolchain_config_info
toolchain_config,
+ cc_common.create_cc_toolchain_config_info(
+ ctx = ctx,
+ action_configs = legacy.action_configs,
+ features = legacy.features,
+ cxx_builtin_include_directories = ctx.attr.cxx_builtin_include_directories,
+ toolchain_identifier = ctx.attr.toolchain_identifier,
+ target_system_name = ctx.attr.target_system_name,
+ target_cpu = ctx.attr.target_cpu,
+ target_libc = ctx.attr.target_libc,
+ compiler = ctx.attr.compiler,
+ abi_version = ctx.attr.abi_version,
+ abi_libc_version = ctx.attr.abi_libc_version,
+ builtin_sysroot = ctx.attr.sysroot or None,
+ ),
]
cc_toolchain_config = rule(
implementation = _cc_toolchain_config_impl,
# @unsorted-dict-items
attrs = {
+ # Attributes new to this rule.
"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"),
+
+ # Attributes from create_cc_toolchain_config_info.
+ # artifact_name_patterns is currently unused. Consider adding it later.
+ # TODO: Consider making this into a label_list that takes a
+ # cc_directory_marker rule as input.
+ "cxx_builtin_include_directories": attr.string_list(),
+ "toolchain_identifier": attr.string(mandatory = True),
+ "target_system_name": attr.string(mandatory = True),
+ "target_cpu": attr.string(mandatory = True),
+ "target_libc": attr.string(mandatory = True),
+ "compiler": attr.string(mandatory = True),
+ "abi_version": attr.string(),
+ "abi_libc_version": attr.string(),
+ # tool_paths currently unused.
+ # TODO: Consider making this into a label that takes a
+ # cc_directory_marker rule as an input.
+ "sysroot": attr.string(),
},
provides = [ToolchainConfigInfo],
)
diff --git a/cc/toolchains/tool.bzl b/cc/toolchains/tool.bzl
index 01ea481..797ef52 100644
--- a/cc/toolchains/tool.bzl
+++ b/cc/toolchains/tool.bzl
@@ -70,7 +70,7 @@ executable label.
doc = "Additional files that are required for this tool to run.",
),
"execution_requirements": attr.string_list(
- doc = "A list of strings that provide hints for execution environment compatibility (e.g. `requires-mac`).",
+ doc = "A list of strings that provide hints for execution environment compatibility (e.g. `requires-network`).",
),
"requires_any_of": attr.label_list(
providers = [FeatureConstraintInfo],
diff --git a/tests/rule_based_toolchain/features/BUILD b/tests/rule_based_toolchain/features/BUILD
index 1d83660..c7ea334 100644
--- a/tests/rule_based_toolchain/features/BUILD
+++ b/tests/rule_based_toolchain/features/BUILD
@@ -73,6 +73,7 @@ util.helper_target(
name = "direct_constraint",
all_of = [":simple"],
none_of = [":simple2"],
+ visibility = ["//tests/rule_based_toolchain:__subpackages__"],
)
util.helper_target(
diff --git a/tests/rule_based_toolchain/features/features_test.bzl b/tests/rule_based_toolchain/features/features_test.bzl
index 3406bdd..f0b15fd 100644
--- a/tests/rule_based_toolchain/features/features_test.bzl
+++ b/tests/rule_based_toolchain/features/features_test.bzl
@@ -11,9 +11,15 @@
# 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.
-"""Tests for actions for the rule based toolchain."""
+"""Tests for features for the rule based toolchain."""
load(
+ "//cc:cc_toolchain_config_lib.bzl",
+ legacy_feature_set = "feature_set",
+ legacy_flag_group = "flag_group",
+ legacy_flag_set = "flag_set",
+)
+load(
"//cc/toolchains:cc_toolchain_info.bzl",
"ArgsInfo",
"FeatureConstraintInfo",
@@ -21,6 +27,11 @@ load(
"FeatureSetInfo",
"MutuallyExclusiveCategoryInfo",
)
+load(
+ "//cc/toolchains/impl:legacy_converter.bzl",
+ "convert_feature",
+ "convert_feature_constraint",
+)
visibility("private")
@@ -41,13 +52,28 @@ def _simple_feature_test(env, targets):
c_compile_action.files().contains_exactly([_C_COMPILE_FILE])
c_compile_action.args().contains_exactly([targets.c_compile[ArgsInfo]])
+ legacy = convert_feature(simple.actual)
+ env.expect.that_str(legacy.name).equals("feature_name")
+ env.expect.that_bool(legacy.enabled).equals(False)
+ env.expect.that_collection(legacy.flag_sets).contains_exactly([
+ legacy_flag_set(
+ actions = ["c_compile"],
+ with_features = [],
+ flag_groups = [legacy_flag_group(flags = ["c"])],
+ ),
+ ])
+
def _feature_collects_requirements_test(env, targets):
- env.expect.that_target(targets.requires).provider(
- FeatureInfo,
- ).requires_any_of().contains_exactly([
+ ft = env.expect.that_target(targets.requires).provider(FeatureInfo)
+ ft.requires_any_of().contains_exactly([
targets.feature_set.label,
])
+ legacy = convert_feature(ft.actual)
+ env.expect.that_collection(legacy.requires).contains_exactly([
+ legacy_feature_set(features = ["feature_name", "simple2"]),
+ ])
+
def _feature_collects_implies_test(env, targets):
env.expect.that_target(targets.implies).provider(
FeatureInfo,
@@ -93,10 +119,24 @@ def _feature_constraint_collects_transitive_features_test(env, targets):
targets.implies.label,
])
+ legacy = convert_feature_constraint(constraint.actual)
+ env.expect.that_collection(legacy.features).contains_exactly([
+ "feature_name",
+ "requires",
+ ])
+ env.expect.that_collection(legacy.not_features).contains_exactly([
+ "simple2",
+ "implies",
+ ])
+
def _external_feature_is_a_feature_test(env, targets):
- env.expect.that_target(targets.builtin_feature).provider(
+ external_feature = env.expect.that_target(targets.builtin_feature).provider(
FeatureInfo,
- ).name().equals("builtin_feature")
+ )
+ external_feature.name().equals("builtin_feature")
+
+ # It's not a string, but we don't have a factory for the type.
+ env.expect.that_str(convert_feature(external_feature.actual)).equals(None)
def _feature_can_be_overridden_test(env, targets):
overrides = env.expect.that_target(targets.overrides).provider(FeatureInfo)
diff --git a/tests/rule_based_toolchain/tool/BUILD b/tests/rule_based_toolchain/tool/BUILD
index de026f8..31c2813 100644
--- a/tests/rule_based_toolchain/tool/BUILD
+++ b/tests/rule_based_toolchain/tool/BUILD
@@ -8,7 +8,8 @@ util.helper_target(
name = "tool",
data = ["//tests/rule_based_toolchain/testdata:bin"],
executable = "//tests/rule_based_toolchain/testdata:bin_wrapper.sh",
- execution_requirements = ["requires-mac"],
+ execution_requirements = ["requires-network"],
+ requires_any_of = ["//tests/rule_based_toolchain/features:direct_constraint"],
)
util.helper_target(
diff --git a/tests/rule_based_toolchain/tool/tool_test.bzl b/tests/rule_based_toolchain/tool/tool_test.bzl
index 840ae84..8e9b68a 100644
--- a/tests/rule_based_toolchain/tool/tool_test.bzl
+++ b/tests/rule_based_toolchain/tool/tool_test.bzl
@@ -13,8 +13,13 @@
# limitations under the License.
"""Tests for the cc_args rule."""
+load(
+ "//cc:cc_toolchain_config_lib.bzl",
+ legacy_with_feature_set = "with_feature_set",
+)
load("//cc/toolchains:cc_toolchain_info.bzl", "ToolInfo")
load("//cc/toolchains/impl:collect.bzl", _collect_tools = "collect_tools")
+load("//cc/toolchains/impl:legacy_converter.bzl", "convert_tool")
load("//tests/rule_based_toolchain:subjects.bzl", "result_fn_wrapper", "subjects")
visibility("private")
@@ -35,10 +40,22 @@ _BIN = "tests/rule_based_toolchain/testdata/bin"
def _tool_test(env, targets):
tool = env.expect.that_target(targets.tool).provider(ToolInfo)
tool.exe().short_path_equals(_BIN_WRAPPER)
+ tool.execution_requirements().contains_exactly(["requires-network"])
tool.runfiles().contains_exactly([
_BIN_WRAPPER,
_BIN,
])
+ tool.requires_any_of().contains_exactly([targets.direct_constraint.label])
+
+ legacy = convert_tool(tool.actual)
+ env.expect.that_file(legacy.tool).equals(tool.actual.exe)
+ env.expect.that_collection(legacy.execution_requirements).contains_exactly(["requires-network"])
+ env.expect.that_collection(legacy.with_features).contains_exactly([
+ legacy_with_feature_set(
+ features = ["feature_name"],
+ not_features = ["simple2"],
+ ),
+ ])
def _wrapped_tool_includes_runfiles_test(env, targets):
tool = env.expect.that_target(targets.wrapped_tool).provider(ToolInfo)
@@ -86,6 +103,7 @@ def _collect_tools_fails_on_non_binary_test(env, targets):
).err()
TARGETS = [
+ "//tests/rule_based_toolchain/features:direct_constraint",
"//tests/rule_based_toolchain/tool:tool",
"//tests/rule_based_toolchain/tool:wrapped_tool",
"//tests/rule_based_toolchain/testdata:bin_wrapper",
diff --git a/tests/rule_based_toolchain/toolchain_config/BUILD b/tests/rule_based_toolchain/toolchain_config/BUILD
index 56a0866..f7f194d 100644
--- a/tests/rule_based_toolchain/toolchain_config/BUILD
+++ b/tests/rule_based_toolchain/toolchain_config/BUILD
@@ -34,12 +34,25 @@ util.helper_target(
)
util.helper_target(
+ cc_args,
+ name = "cpp_compile_args",
+ actions = ["//tests/rule_based_toolchain/actions:cpp_compile"],
+ args = ["cpp_compile_args"],
+ env = {"CPP_COMPILE": "1"},
+)
+
+util.helper_target(
cc_toolchain_config,
name = "collects_files_toolchain_config",
action_type_configs = [":compile_config"],
args = [":c_compile_args"],
+ compiler = "gcc-4.1.1",
skip_experimental_flag_validation_for_test = True,
+ target_cpu = "k8",
+ target_libc = "glibc-2.2.2",
+ target_system_name = "local",
toolchain_features = [":compile_feature"],
+ toolchain_identifier = "collects_files_toolchain",
)
util.helper_target(
@@ -68,8 +81,9 @@ util.helper_target(
cc_action_type_config,
name = "compile_config",
action_types = ["//tests/rule_based_toolchain/actions:all_compile"],
+ args = [":cpp_compile_args"],
tools = [
- "//tests/rule_based_toolchain/testdata:bin",
+ "//tests/rule_based_toolchain/tool:wrapped_tool",
],
)
@@ -87,7 +101,7 @@ util.helper_target(
action_types = ["//tests/rule_based_toolchain/actions:c_compile"],
implies = [":simple_feature"],
tools = [
- "//tests/rule_based_toolchain/testdata:bin",
+ "//tests/rule_based_toolchain/tool:wrapped_tool",
],
)
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 83e453f..e188772 100644
--- a/tests/rule_based_toolchain/toolchain_config/toolchain_config_test.bzl
+++ b/tests/rule_based_toolchain/toolchain_config/toolchain_config_test.bzl
@@ -11,9 +11,20 @@
# 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.
-"""Tests for the cc_args rule."""
+"""Tests for the cc_toolchain_config rule."""
+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_flag_group = "flag_group",
+ legacy_flag_set = "flag_set",
+ legacy_tool = "tool",
+)
load("//cc/toolchains:cc_toolchain_info.bzl", "ActionTypeInfo", "ToolchainConfigInfo")
+load("//cc/toolchains/impl:legacy_converter.bzl", "convert_toolchain")
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")
@@ -24,6 +35,7 @@ toolchain_config_info = result_fn_wrapper(_toolchain_config_info)
_COLLECTED_CPP_COMPILE_FILES = [
# From :compile_config's tool
"tests/rule_based_toolchain/testdata/bin",
+ "tests/rule_based_toolchain/testdata/bin_wrapper",
# From :compile_feature's args
"tests/rule_based_toolchain/testdata/file2",
]
@@ -189,6 +201,61 @@ def _toolchain_collects_files_test(env, targets):
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(
+ name = "compile_feature",
+ enabled = True,
+ flag_sets = [legacy_flag_set(
+ actions = ["c_compile", "cpp_compile"],
+ flag_groups = [
+ legacy_flag_group(flags = ["compile_args"]),
+ ],
+ )],
+ ),
+ legacy_feature(
+ name = "implied_by_always_enabled",
+ enabled = True,
+ flag_sets = [legacy_flag_set(
+ actions = ["c_compile"],
+ flag_groups = [
+ legacy_flag_group(flags = ["c_compile_args"]),
+ ],
+ )],
+ ),
+ legacy_feature(
+ name = "implied_by_cpp_compile",
+ enabled = False,
+ flag_sets = [legacy_flag_set(
+ actions = ["cpp_compile"],
+ flag_groups = [
+ legacy_flag_group(flags = ["cpp_compile_args"]),
+ ],
+ )],
+ env_sets = [legacy_env_set(
+ actions = ["cpp_compile"],
+ env_entries = [legacy_env_entry(key = "CPP_COMPILE", value = "1")],
+ )],
+ ),
+ ]).in_order()
+
+ exe = tc.action_type_configs().get(
+ targets.c_compile[ActionTypeInfo],
+ ).actual.tools[0].exe
+ env.expect.that_collection(legacy.action_configs).contains_exactly([
+ legacy_action_config(
+ action_name = "c_compile",
+ enabled = True,
+ tools = [legacy_tool(tool = exe)],
+ ),
+ legacy_action_config(
+ action_name = "cpp_compile",
+ enabled = True,
+ tools = [legacy_tool(tool = exe)],
+ implies = ["implied_by_cpp_compile"],
+ ),
+ ]).in_order()
+
TARGETS = [
"//tests/rule_based_toolchain/actions:c_compile",
"//tests/rule_based_toolchain/actions:cpp_compile",