Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions cc/toolchains/cc_toolchain_info.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,15 @@ MakeVariableInfo = provider(
},
)

ExecutionRequirementsInfo = provider(
doc = "Provider for execution requirements attached to tool actions.",
# @unsorted-dict-items
fields = {
"label": "(Label) The label defining this provider. Place in error messages to simplify debugging",
"requirements": "(Sequence[str]) The execution requirements to apply.",
},
)

MutuallyExclusiveCategoryInfo = provider(
doc = "Multiple features with the category will be mutally exclusive",
# @unsorted-dict-items
Expand Down
20 changes: 20 additions & 0 deletions cc/toolchains/providers.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright 2026 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.
"""Public providers for rule-based toolchain configuration."""

load(":cc_toolchain_info.bzl", _ExecutionRequirementsInfo = "ExecutionRequirementsInfo")

visibility("public")

ExecutionRequirementsInfo = _ExecutionRequirementsInfo
18 changes: 17 additions & 1 deletion cc/toolchains/tool.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ load("//cc/toolchains/impl:label_utils.bzl", "deduplicate_label_list")
load("//cc/toolchains/impl:nested_args.bzl", "format_dict_values")
load(
":cc_toolchain_info.bzl",
"ExecutionRequirementsInfo",
"ToolCapabilityInfo",
"ToolInfo",
)
Expand All @@ -40,13 +41,16 @@ def _cc_tool_impl(ctx):
format = format_targets,
must_use = format_targets.keys(),
)
execution_requirements = []
for info in collect_provider(ctx.attr.execution_requirements, ExecutionRequirementsInfo):
execution_requirements.extend(info.requirements)

runfiles = collect_data(ctx, ctx.attr.data + [ctx.attr.src])
tool = ToolInfo(
label = ctx.label,
exe = exe,
runfiles = runfiles,
execution_requirements = tuple(ctx.attr.tags),
execution_requirements = tuple(ctx.attr.tags + execution_requirements),
env = env,
allowlist_include_directories = depset(
direct = [d[DirectoryInfo] for d in ctx.attr.allowlist_include_directories],
Expand Down Expand Up @@ -116,6 +120,13 @@ This can help work around errors like:
doc = """Environment variables to apply when running this tool.

Format expansion is performed on values using the format attribute.
""",
),
"execution_requirements": attr.label_list(
providers = [ExecutionRequirementsInfo],
doc = """Additional execution requirements for actions that run this tool.

Each label must provide `ExecutionRequirementsInfo`. For fixed execution requirements, use `tags`.
""",
),
"format_keys": attr.string_list(
Expand Down Expand Up @@ -181,6 +192,7 @@ def cc_tool(
data = None,
allowlist_include_directories = None,
env = None,
execution_requirements = None,
format = {},
capabilities = None,
**kwargs):
Expand Down Expand Up @@ -235,6 +247,9 @@ def cc_tool(
(if these are builtin files, make sure these paths are in your toolchain)`.
env: (Dict[str, str]) Environment variables to apply when running this tool.
Format expansion is performed on values using `format`.
execution_requirements: (List[Label]) Additional execution requirements for actions that
run this tool. Each label must provide `ExecutionRequirementsInfo`. For fixed
execution requirements, use `tags`.
format: (Dict[str, Label]) A mapping of format strings to the label of a corresponding
target. This target can be a `directory`, `subdirectory`, or a single file that the
value should be pulled from. All instances of `{variable_name}` in the `env` dictionary
Expand All @@ -255,6 +270,7 @@ def cc_tool(
data = data,
allowlist_include_directories = allowlist_include_directories,
env = env,
execution_requirements = execution_requirements,
format_keys = format_keys,
format_values = format_values.labels,
format_value_indexes = format_values.indexes,
Expand Down
4 changes: 3 additions & 1 deletion docs/toolchain_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,8 @@ use this rule.
<pre>
load("@rules_cc//cc/toolchains/impl:documented_api.bzl", "cc_tool")

cc_tool(*, <a href="#cc_tool-name">name</a>, <a href="#cc_tool-src">src</a>, <a href="#cc_tool-data">data</a>, <a href="#cc_tool-allowlist_include_directories">allowlist_include_directories</a>, <a href="#cc_tool-env">env</a>, <a href="#cc_tool-format">format</a>, <a href="#cc_tool-capabilities">capabilities</a>, <a href="#cc_tool-kwargs">**kwargs</a>)
cc_tool(*, <a href="#cc_tool-name">name</a>, <a href="#cc_tool-src">src</a>, <a href="#cc_tool-data">data</a>, <a href="#cc_tool-allowlist_include_directories">allowlist_include_directories</a>, <a href="#cc_tool-env">env</a>, <a href="#cc_tool-execution_requirements">execution_requirements</a>, <a href="#cc_tool-format">format</a>,
<a href="#cc_tool-capabilities">capabilities</a>, <a href="#cc_tool-kwargs">**kwargs</a>)
</pre>

Declares a tool for use by toolchain actions.
Expand Down Expand Up @@ -724,6 +725,7 @@ cc_tool(
| <a id="cc_tool-data"></a>data | (List[Label]) Additional files that are required for this tool to run. Frequently, clang and gcc require additional files to execute as they often shell out to other binaries (e.g. `cc1`). | `None` |
| <a id="cc_tool-allowlist_include_directories"></a>allowlist_include_directories | (List[Label]) Include paths implied by using this tool. Compilers may include a set of built-in headers that are implicitly available unless flags like `-nostdinc` are provided. Bazel checks that all included headers are properly provided by a dependency or allowlisted through this mechanism.<br><br>As a rule of thumb, only use this if Bazel is complaining about absolute paths in your toolchain and you've ensured that the toolchain is compiling with the `-no-canonical-prefixes` and/or `-fno-canonical-system-headers` arguments.<br><br>These files are not automatically passed to each action. If they need to be, add them to 'data' as well.<br><br>This can help work around errors like: `the source file 'main.c' includes the following non-builtin files with absolute paths (if these are builtin files, make sure these paths are in your toolchain)`. | `None` |
| <a id="cc_tool-env"></a>env | (Dict[str, str]) Environment variables to apply when running this tool. Format expansion is performed on values using `format`. | `None` |
| <a id="cc_tool-execution_requirements"></a>execution_requirements | (List[Label]) Additional execution requirements for actions that run this tool. Each label must provide `ExecutionRequirementsInfo`. For fixed execution requirements, use `tags`. | `None` |
| <a id="cc_tool-format"></a>format | (Dict[str, Label]) A mapping of format strings to the label of a corresponding target. This target can be a `directory`, `subdirectory`, or a single file that the value should be pulled from. All instances of `{variable_name}` in the `env` dictionary values will be replaced with the expanded value in this dictionary. | `{}` |
| <a id="cc_tool-capabilities"></a>capabilities | (List[Label]) Declares that a tool is capable of doing something. For example, `@rules_cc//cc/toolchains/capabilities:supports_pic`. | `None` |
| <a id="cc_tool-kwargs"></a>kwargs | [common attributes](https://bazel.build/reference/be/common-definitions#common-attributes) that should be applied to this rule. | none |
Expand Down
17 changes: 17 additions & 0 deletions tests/rule_based_toolchain/tool/BUILD
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
load("//cc/toolchains:directory_tool.bzl", "cc_directory_tool")
load("//cc/toolchains:tool.bzl", "cc_tool")
load("//tests/rule_based_toolchain:analysis_test_suite.bzl", "analysis_test_suite")
load(":execution_requirements.bzl", "test_execution_requirements")
load(":tool_test.bzl", "TARGETS", "TESTS")

cc_tool(
Expand Down Expand Up @@ -44,6 +45,22 @@ cc_tool(
visibility = ["//tests/rule_based_toolchain:__subpackages__"],
)

test_execution_requirements(
name = "execution_requirements",
requirements = [
"example-requires-network",
"example-requires-darwin",
],
)

cc_tool(
name = "tool_with_execution_requirements",
src = "//tests/rule_based_toolchain/testdata:bin_wrapper.sh",
execution_requirements = [":execution_requirements"],
tags = ["example-hardcoded-tag"],
visibility = ["//tests/rule_based_toolchain:__subpackages__"],
)

cc_directory_tool(
name = "directory_tool",
data = ["bin"],
Expand Down
34 changes: 34 additions & 0 deletions tests/rule_based_toolchain/tool/execution_requirements.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright 2026 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.
"""Test helper for tool execution requirements."""

load("//cc/toolchains:providers.bzl", "ExecutionRequirementsInfo")

visibility("private")

def _test_execution_requirements_impl(ctx):
return [
ExecutionRequirementsInfo(
label = ctx.label,
requirements = tuple(ctx.attr.requirements),
),
]

test_execution_requirements = rule(
implementation = _test_execution_requirements_impl,
attrs = {
"requirements": attr.string_list(),
},
provides = [ExecutionRequirementsInfo],
)
17 changes: 17 additions & 0 deletions tests/rule_based_toolchain/tool/tool_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,21 @@ def _tool_env_expansion_test(env, targets):
"TOOL_ENV_AGAIN": path_pattern("tests/rule_based_toolchain/testdata/file1"),
})

def _tool_execution_requirements_test(env, targets):
tool = env.expect.that_target(targets.tool_with_execution_requirements).provider(ToolInfo)
tool.execution_requirements().contains_exactly([
"example-hardcoded-tag",
"example-requires-darwin",
"example-requires-network",
])

legacy = convert_tool(tool.actual)
env.expect.that_collection(legacy.execution_requirements).contains_exactly([
"example-hardcoded-tag",
"example-requires-darwin",
"example-requires-network",
])

def _collect_tools_collects_tools_test(env, targets):
env.expect.that_value(
value = collect_tools(env.ctx, [targets.tool, targets.wrapped_tool]),
Expand Down Expand Up @@ -118,6 +133,7 @@ TARGETS = [
"//tests/rule_based_toolchain/tool:directory_tool",
"//tests/rule_based_toolchain/tool:tool_with_allowlist_include_directories",
"//tests/rule_based_toolchain/tool:tool_with_env",
"//tests/rule_based_toolchain/tool:tool_with_execution_requirements",
"//tests/rule_based_toolchain/testdata:bin_wrapper",
"//tests/rule_based_toolchain/testdata:multiple",
"//tests/rule_based_toolchain/testdata:bin_filegroup",
Expand All @@ -135,4 +151,5 @@ TESTS = {
"collect_tools_fails_on_non_binary_test": _collect_tools_fails_on_non_binary_test,
"tool_with_allowlist_include_directories_test": _tool_with_allowlist_include_directories_test,
"tool_env_expansion_test": _tool_env_expansion_test,
"tool_execution_requirements_test": _tool_execution_requirements_test,
}