Skip to content

Commit

Permalink
BEGIN_PUBLIC
Browse files Browse the repository at this point in the history
Implement cc_action_type_config.

Rename it from cc_action_config, to make it clear that we are not configuring an action, but rather configuring a type of action.
END_PUBLIC

PiperOrigin-RevId: 610518142
Change-Id: Ic10755952ee786d30a3a5564aa09a8dc16499f3a
  • Loading branch information
Googler authored and copybara-github committed Feb 26, 2024
1 parent 0d68da5 commit c5493f9
Show file tree
Hide file tree
Showing 11 changed files with 368 additions and 42 deletions.
8 changes: 4 additions & 4 deletions cc/toolchains/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ An action config is a mapping from action to:
* A set of additional files required for the action

Each action can only be specified once in the toolchain. Specifying multiple
actions in a single `cc_action_config` is just a shorthand for specifying the
actions in a single `cc_action_type_config` is just a shorthand for specifying the
same config for every one of those actions.

If you're already familiar with how to define toolchains, the additional files
Expand All @@ -50,15 +50,15 @@ Additionally, to replace `all_files`, we add `cc_additional_files_for_actions`.
This allows you to specify that particular files are required for particular
actions.

We provide `additional_files` on the `cc_action_config` as a shorthand for
We provide `additional_files` on the `cc_action_type_config` as a shorthand for
specifying `cc_additional_files_for_actions`

Warning: Implying a feature that is not listed directly in the toolchain will throw
an error. This is to ensure you don't accidentally add a feature to the
toolchain.

```
cc_action_config(
cc_action_type_config(
name = "c_compile",
actions = ["@rules_cc//actions:all_c_compile"],
tools = ["@sysroot//:clang"],
Expand Down Expand Up @@ -196,7 +196,7 @@ cc_toolchain(
name = "toolchain",
features = [":my_feature"]
unconditional_args = [":all_warnings"],
action_configs = [":c_compile"],
action_type_configs = [":c_compile"],
additional_files = [":all_action_files"],
)
```
Expand Down
137 changes: 137 additions & 0 deletions cc/toolchains/action_type_config.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# 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 cc_action_type_config."""

load("//cc/toolchains/impl:args_utils.bzl", "get_action_type")
load(
"//cc/toolchains/impl:collect.bzl",
"collect_action_types",
"collect_args_lists",
"collect_features",
"collect_files",
"collect_tools",
)
load(
":cc_toolchain_info.bzl",
"ActionTypeConfigInfo",
"ActionTypeConfigSetInfo",
"ActionTypeSetInfo",
"ArgsListInfo",
"FeatureSetInfo",
)

def _cc_action_type_config_impl(ctx):
if not ctx.attr.action_types:
fail("At least one action type is required for cc_action_type_config")
if not ctx.attr.tools:
fail("At least one tool is required for cc_action_type_config")

tools = tuple(collect_tools(ctx, ctx.attr.tools))
implies = collect_features(ctx.attr.implies)
args_list = collect_args_lists(ctx.attr.args, ctx.label)
files = collect_files(ctx.attr.additional_files)

configs = {}
for action_type in collect_action_types(ctx.attr.action_types).to_list():
for_action = get_action_type(args_list, action_type)
configs[action_type] = ActionTypeConfigInfo(
label = ctx.label,
action_type = action_type,
tools = tools,
args = for_action.args,
implies = implies,
files = ctx.runfiles(
transitive_files = depset(transitive = [files, for_action.files]),
).merge_all([tool.runfiles for tool in tools]),
)

return [ActionTypeConfigSetInfo(label = ctx.label, configs = configs)]

cc_action_type_config = rule(
implementation = _cc_action_type_config_impl,
# @unsorted-dict-items
attrs = {
"action_types": attr.label_list(
providers = [ActionTypeSetInfo],
mandatory = True,
doc = """A list of action names to apply this action to.
See @toolchain//actions:all for valid options.
""",
),
"tools": attr.label_list(
mandatory = True,
cfg = "exec",
allow_files = True,
doc = """The tool to use for the specified actions.
A tool can be a `cc_tool`, or a binary.
If multiple tools are specified, the first tool that has `with_features` that
satisfy the currently enabled feature set is used.
""",
),
"args": attr.label_list(
providers = [ArgsListInfo],
doc = """Labels that point to `cc_arg`s / `cc_arg_list`s that are
unconditionally bound to the specified actions.
""",
),
"implies": attr.label_list(
providers = [FeatureSetInfo],
doc = "Features that should be enabled when this action is used.",
),
"additional_files": attr.label_list(
allow_files = True,
doc = """Files required for this action type.
For example, the c-compile action type might add the C standard library header
files from the sysroot.
""",
),
},
provides = [ActionTypeConfigSetInfo],
doc = """Declares the configuration and selection of `cc_tool` rules.
Action configs are bound to a toolchain through `action_configs`, and are the
driving mechanism for controlling toolchain tool invocation/behavior.
Action configs define three key things:
* Which tools to invoke for a given type of action.
* Tool features and compatibility.
* `cc_args`s that are unconditionally bound to a tool invocation.
Examples:
cc_action_config(
name = "ar",
action_types = ["@toolchain//actions:all_ar_actions"],
implies = [
"@toolchain//features/legacy:archiver_flags",
"@toolchain//features/legacy:linker_param_file",
],
tools = [":ar_tool"],
)
cc_action_config(
name = "clang",
action_types = [
"@toolchain//actions:all_asm_actions",
"@toolchain//actions:all_c_compiler_actions",
],
tools = [":clang_tool"],
)
""",
)
2 changes: 2 additions & 0 deletions cc/toolchains/actions.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ cc_action_type(
)

def _cc_action_type_set_impl(ctx):
if not ctx.attr.actions:
fail("Each cc_action_type_set must contain at least one action type.")
return [ActionTypeSetInfo(
label = ctx.label,
actions = collect_action_types(ctx.attr.actions),
Expand Down
9 changes: 4 additions & 5 deletions cc/toolchains/cc_toolchain_info.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -133,25 +133,24 @@ ToolInfo = provider(
},
)

ActionConfigInfo = provider(
ActionTypeConfigInfo = provider(
doc = "Configuration of a Bazel action.",
# @unsorted-dict-items
fields = {
"label": "(Label) The label defining this provider. Place in error messages to simplify debugging",
"action": "(ActionTypeInfo) The name of the action",
"enabled": "(bool) If True, this action is enabled unless a rule type explicitly marks it as unsupported",
"action_type": "(ActionTypeInfo) The type of the action",
"tools": "(Sequence[ToolInfo]) The tool applied to the action will be the first tool in the sequence with a feature set that matches the feature configuration",
"args": "(Sequence[ArgsInfo]) Set of flag sets the action sets",
"implies": "(depset[FeatureInfo]) Set of features implied by this action config",
"files": "(depset[File]) The files required to run these actions",
},
)

ActionConfigSetInfo = provider(
ActionTypeConfigSetInfo = provider(
doc = "A set of action configs",
# @unsorted-dict-items
fields = {
"label": "(Label) The label defining this provider. Place in error messages to simplify debugging",
"action_configs": "(depset[ActionConfigInfo]) A set of action configs",
"configs": "(dict[ActionTypeInfo, ActionTypeConfigInfo]) A set of action configs",
},
)
30 changes: 30 additions & 0 deletions cc/toolchains/impl/args_utils.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# 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.
"""."""

def get_action_type(args_list, action_type):
"""Returns the corresponding entry in ArgsListInfo.by_action.
Args:
args_list: (ArgsListInfo) The args list to look through
action_type: (ActionTypeInfo) The action type to look up.
Returns:
The information corresponding to this action type.
"""
for args in args_list.by_action:
if args.action == action_type:
return args

return struct(action = action_type, args = tuple(), files = depset([]))
22 changes: 22 additions & 0 deletions cc/toolchains/impl/collect.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@

load(
"//cc/toolchains:cc_toolchain_info.bzl",
"ActionTypeConfigSetInfo",
"ActionTypeSetInfo",
"ArgsListInfo",
"FeatureSetInfo",
"ToolInfo",
)

Expand Down Expand Up @@ -57,6 +59,7 @@ def _make_collector(provider, field):
return collector

collect_action_types = _make_collector(ActionTypeSetInfo, "actions")
collect_features = _make_collector(FeatureSetInfo, "features")
collect_files = _make_collector(DefaultInfo, "files")

def collect_data(ctx, targets):
Expand Down Expand Up @@ -145,3 +148,22 @@ def collect_args_lists(targets, label):
for k, v in by_action.items()
]),
)

def collect_action_type_config_sets(targets, label, fail = fail):
"""Collects several `cc_action_type_config` labels together.
Args:
targets: (List[Target]) A list of targets providing ActionTypeConfigSetInfo
label: The label to apply to the resulting config.
fail: (function) The fail function. Should only be used in tests.
Returns:
A combined ActionTypeConfigSetInfo representing a variety of action
types.
"""
configs = {}
for atcs in collect_provider(targets, ActionTypeConfigSetInfo):
for action_type, config in atcs.configs.items():
if action_type in configs:
fail("The action type %s is configured by both %s and %s. Each action type may only be configured once." % (action_type.label, config.label, configs[action_type].label))
configs[action_type] = config
return ActionTypeConfigSetInfo(label = label, configs = configs)
42 changes: 42 additions & 0 deletions tests/rule_based_toolchain/action_type_config/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
load("@rules_testing//lib:util.bzl", "util")
load("//cc/toolchains:action_type_config.bzl", "cc_action_type_config")
load("//tests/rule_based_toolchain:analysis_test_suite.bzl", "analysis_test_suite")
load(":action_type_config_test.bzl", "TARGETS", "TESTS")

util.helper_target(
cc_action_type_config,
name = "file_map",
action_types = ["//tests/rule_based_toolchain/actions:all_compile"],
additional_files = [
"//tests/rule_based_toolchain/testdata:multiple2",
],
args = ["//tests/rule_based_toolchain/args_list"],
tools = [
"//tests/rule_based_toolchain/testdata:bin_wrapper.sh",
"//tests/rule_based_toolchain/tool:wrapped_tool",
],
)

util.helper_target(
cc_action_type_config,
name = "c_compile_config",
action_types = ["//tests/rule_based_toolchain/actions:c_compile"],
tools = [
"//tests/rule_based_toolchain/testdata:bin_wrapper.sh",
],
)

util.helper_target(
cc_action_type_config,
name = "cpp_compile_config",
action_types = ["//tests/rule_based_toolchain/actions:cpp_compile"],
tools = [
"//tests/rule_based_toolchain/testdata:bin_wrapper.sh",
],
)

analysis_test_suite(
name = "test_suite",
targets = TARGETS,
tests = TESTS,
)
Loading

0 comments on commit c5493f9

Please sign in to comment.