Implement cc_toolchain_config rule and cc_legacy_file_group rule.

BEGIN_PUBLIC
Implement cc_toolchain_config rule and cc_legacy_file_group rule.

Note that this rule is in the impl/ directory because we require users to use the cc_toolchain_config rule via the cc_toolchain macro that we will define later, to ensure that parameters such as `compile_files` are passed correctly.
END_PUBLIC

PiperOrigin-RevId: 612998387
Change-Id: I986d11775e368c4386a930ab2ce8663956a57f9d
This commit is contained in:
Googler 2024-03-05 15:57:21 -08:00 committed by Copybara-Service
parent 7250ef4352
commit 94d4760a89
5 changed files with 142 additions and 22 deletions

View File

@ -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"],
)

View File

@ -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],
)

View File

@ -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)),
),
)

View File

@ -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",

View File

@ -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",