mirror of https://github.com/bazelbuild/rules_cc
Create a concept of a tool capability.
This should make the concept of "sentinel features" work correctly with known_features and enabled_features, rather than enabling them directly in features. PiperOrigin-RevId: 681688437 Change-Id: I29184a2079ccfd0eb3a275439508a66ca61109af
This commit is contained in:
parent
1af2140e73
commit
f364500ba8
|
@ -0,0 +1,19 @@
|
||||||
|
load("//cc/toolchains:tool_capability.bzl", "cc_tool_capability")
|
||||||
|
|
||||||
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
|
cc_tool_capability(
|
||||||
|
name = "supports_start_end_lib",
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_tool_capability(
|
||||||
|
name = "supports_interface_shared_libraries",
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_tool_capability(
|
||||||
|
name = "supports_dynamic_linker",
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_tool_capability(
|
||||||
|
name = "supports_pic",
|
||||||
|
)
|
|
@ -156,6 +156,16 @@ ToolInfo = provider(
|
||||||
"runfiles": "(runfiles) The files required to run the tool",
|
"runfiles": "(runfiles) The files required to run the tool",
|
||||||
"execution_requirements": "(Sequence[str]) A set of execution requirements of the tool",
|
"execution_requirements": "(Sequence[str]) A set of execution requirements of the tool",
|
||||||
"allowlist_include_directories": "(depset[DirectoryInfo]) Built-in include directories implied by this tool that should be allowlisted in Bazel's include checker",
|
"allowlist_include_directories": "(depset[DirectoryInfo]) Built-in include directories implied by this tool that should be allowlisted in Bazel's include checker",
|
||||||
|
"capabilities": "(Sequence[ToolCapabilityInfo]) Capabilities supported by the tool.",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
ToolCapabilityInfo = provider(
|
||||||
|
doc = "A capability associated with a tool (eg. supports_pic).",
|
||||||
|
# @unsorted-dict-items
|
||||||
|
fields = {
|
||||||
|
"label": "(Label) The label defining this provider. Place in error messages to simplify debugging",
|
||||||
|
"feature": "(FeatureInfo) The feature this capability defines",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -41,36 +41,12 @@ cc_external_feature(
|
||||||
overridable = True,
|
overridable = True,
|
||||||
)
|
)
|
||||||
|
|
||||||
cc_external_feature(
|
|
||||||
name = "supports_start_end_lib",
|
|
||||||
feature_name = "supports_start_end_lib",
|
|
||||||
overridable = True,
|
|
||||||
)
|
|
||||||
|
|
||||||
cc_external_feature(
|
|
||||||
name = "supports_interface_shared_libraries",
|
|
||||||
feature_name = "supports_interface_shared_libraries",
|
|
||||||
overridable = True,
|
|
||||||
)
|
|
||||||
|
|
||||||
cc_external_feature(
|
|
||||||
name = "supports_dynamic_linker",
|
|
||||||
feature_name = "supports_dynamic_linker",
|
|
||||||
overridable = True,
|
|
||||||
)
|
|
||||||
|
|
||||||
cc_external_feature(
|
cc_external_feature(
|
||||||
name = "static_link_cpp_runtimes",
|
name = "static_link_cpp_runtimes",
|
||||||
feature_name = "static_link_cpp_runtimes",
|
feature_name = "static_link_cpp_runtimes",
|
||||||
overridable = True,
|
overridable = True,
|
||||||
)
|
)
|
||||||
|
|
||||||
cc_external_feature(
|
|
||||||
name = "supports_pic",
|
|
||||||
feature_name = "supports_pic",
|
|
||||||
overridable = True,
|
|
||||||
)
|
|
||||||
|
|
||||||
cc_feature_set(
|
cc_feature_set(
|
||||||
name = "all_non_legacy_builtin_features",
|
name = "all_non_legacy_builtin_features",
|
||||||
all_of = [
|
all_of = [
|
||||||
|
@ -80,11 +56,7 @@ cc_feature_set(
|
||||||
":static_linking_mode",
|
":static_linking_mode",
|
||||||
":dynamic_linking_mode",
|
":dynamic_linking_mode",
|
||||||
":per_object_debug_info",
|
":per_object_debug_info",
|
||||||
":supports_start_end_lib",
|
|
||||||
":supports_interface_shared_libraries",
|
|
||||||
":supports_dynamic_linker",
|
|
||||||
":static_link_cpp_runtimes",
|
":static_link_cpp_runtimes",
|
||||||
":supports_pic",
|
|
||||||
],
|
],
|
||||||
visibility = ["//visibility:private"],
|
visibility = ["//visibility:private"],
|
||||||
)
|
)
|
||||||
|
|
|
@ -107,6 +107,7 @@ def collect_tools(ctx, targets, fail = fail):
|
||||||
runfiles = collect_data(ctx, [target]),
|
runfiles = collect_data(ctx, [target]),
|
||||||
execution_requirements = tuple(),
|
execution_requirements = tuple(),
|
||||||
allowlist_include_directories = depset(),
|
allowlist_include_directories = depset(),
|
||||||
|
capabilities = tuple(),
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
fail("Expected %s to be a cc_tool or a binary rule" % target.label)
|
fail("Expected %s to be a cc_tool or a binary rule" % target.label)
|
||||||
|
|
|
@ -22,12 +22,14 @@ load("//cc/toolchains:feature_set.bzl", _cc_feature_set = "cc_feature_set")
|
||||||
load("//cc/toolchains:mutually_exclusive_category.bzl", _cc_mutually_exclusive_category = "cc_mutually_exclusive_category")
|
load("//cc/toolchains:mutually_exclusive_category.bzl", _cc_mutually_exclusive_category = "cc_mutually_exclusive_category")
|
||||||
load("//cc/toolchains:nested_args.bzl", _cc_nested_args = "cc_nested_args")
|
load("//cc/toolchains:nested_args.bzl", _cc_nested_args = "cc_nested_args")
|
||||||
load("//cc/toolchains:tool.bzl", _cc_tool = "cc_tool")
|
load("//cc/toolchains:tool.bzl", _cc_tool = "cc_tool")
|
||||||
|
load("//cc/toolchains:tool_capability.bzl", _cc_tool_capability = "cc_tool_capability")
|
||||||
load("//cc/toolchains:tool_map.bzl", _cc_tool_map = "cc_tool_map")
|
load("//cc/toolchains:tool_map.bzl", _cc_tool_map = "cc_tool_map")
|
||||||
load("//cc/toolchains/impl:external_feature.bzl", _cc_external_feature = "cc_external_feature")
|
load("//cc/toolchains/impl:external_feature.bzl", _cc_external_feature = "cc_external_feature")
|
||||||
load("//cc/toolchains/impl:variables.bzl", _cc_variable = "cc_variable")
|
load("//cc/toolchains/impl:variables.bzl", _cc_variable = "cc_variable")
|
||||||
|
|
||||||
cc_tool_map = _cc_tool_map
|
cc_tool_map = _cc_tool_map
|
||||||
cc_tool = _cc_tool
|
cc_tool = _cc_tool
|
||||||
|
cc_tool_capability = _cc_tool_capability
|
||||||
cc_args = _cc_args
|
cc_args = _cc_args
|
||||||
cc_nested_args = _cc_nested_args
|
cc_nested_args = _cc_nested_args
|
||||||
cc_args_list = _cc_args_list
|
cc_args_list = _cc_args_list
|
||||||
|
@ -46,6 +48,7 @@ cc_external_feature = _cc_external_feature
|
||||||
DOCUMENTED_TOOLCHAIN_RULES = [
|
DOCUMENTED_TOOLCHAIN_RULES = [
|
||||||
"cc_tool_map",
|
"cc_tool_map",
|
||||||
"cc_tool",
|
"cc_tool",
|
||||||
|
"cc_tool_capability",
|
||||||
"cc_args",
|
"cc_args",
|
||||||
"cc_nested_args",
|
"cc_nested_args",
|
||||||
"cc_args_list",
|
"cc_args_list",
|
||||||
|
|
|
@ -131,16 +131,30 @@ def convert_tool(tool):
|
||||||
with_features = [],
|
with_features = [],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def convert_capability(capability):
|
||||||
|
return legacy_feature(
|
||||||
|
name = capability.name,
|
||||||
|
enabled = False,
|
||||||
|
)
|
||||||
|
|
||||||
def _convert_tool_map(tool_map):
|
def _convert_tool_map(tool_map):
|
||||||
return [
|
action_configs = []
|
||||||
legacy_action_config(
|
caps = {}
|
||||||
|
for action_type, tool in tool_map.configs.items():
|
||||||
|
action_configs.append(legacy_action_config(
|
||||||
action_name = action_type.name,
|
action_name = action_type.name,
|
||||||
enabled = True,
|
enabled = True,
|
||||||
tools = [convert_tool(tool_map.configs[action_type])],
|
tools = [convert_tool(tool)],
|
||||||
implies = [],
|
implies = [cap.feature.name for cap in tool.capabilities],
|
||||||
)
|
))
|
||||||
for action_type in tool_map.configs.keys()
|
for cap in tool.capabilities:
|
||||||
|
caps[cap] = None
|
||||||
|
|
||||||
|
cap_features = [
|
||||||
|
legacy_feature(name = cap.feature.name, enabled = False)
|
||||||
|
for cap in caps
|
||||||
]
|
]
|
||||||
|
return action_configs, cap_features
|
||||||
|
|
||||||
def convert_toolchain(toolchain):
|
def convert_toolchain(toolchain):
|
||||||
"""Converts a rule-based toolchain into the legacy providers.
|
"""Converts a rule-based toolchain into the legacy providers.
|
||||||
|
@ -155,6 +169,8 @@ def convert_toolchain(toolchain):
|
||||||
convert_feature(feature, enabled = feature in toolchain.enabled_features)
|
convert_feature(feature, enabled = feature in toolchain.enabled_features)
|
||||||
for feature in toolchain.features
|
for feature in toolchain.features
|
||||||
]
|
]
|
||||||
|
action_configs, cap_features = _convert_tool_map(toolchain.tool_map)
|
||||||
|
features.extend(cap_features)
|
||||||
features.append(convert_feature(FeatureInfo(
|
features.append(convert_feature(FeatureInfo(
|
||||||
# We reserve names starting with implied_by. This ensures we don't
|
# We reserve names starting with implied_by. This ensures we don't
|
||||||
# conflict with the name of a feature the user creates.
|
# conflict with the name of a feature the user creates.
|
||||||
|
@ -167,7 +183,6 @@ def convert_toolchain(toolchain):
|
||||||
external = False,
|
external = False,
|
||||||
allowlist_include_directories = depset(),
|
allowlist_include_directories = depset(),
|
||||||
)))
|
)))
|
||||||
action_configs = _convert_tool_map(toolchain.tool_map)
|
|
||||||
|
|
||||||
cxx_builtin_include_directories = [
|
cxx_builtin_include_directories = [
|
||||||
d.path
|
d.path
|
||||||
|
|
|
@ -54,9 +54,9 @@ def _feature_key(feature):
|
||||||
# This should be sufficiently unique.
|
# This should be sufficiently unique.
|
||||||
return (feature.label, feature.name)
|
return (feature.label, feature.name)
|
||||||
|
|
||||||
def _get_known_features(features, fail):
|
def _get_known_features(features, capability_features, fail):
|
||||||
feature_names = {}
|
feature_names = {}
|
||||||
for ft in features:
|
for ft in capability_features + features:
|
||||||
if ft.name in feature_names:
|
if ft.name in feature_names:
|
||||||
other = feature_names[ft.name]
|
other = feature_names[ft.name]
|
||||||
if other.overrides != ft and ft.overrides != other:
|
if other.overrides != ft and ft.overrides != other:
|
||||||
|
@ -113,7 +113,10 @@ def _validate_feature(self, known_features, fail):
|
||||||
_validate_implies(self, known_features, fail = fail)
|
_validate_implies(self, known_features, fail = fail)
|
||||||
|
|
||||||
def _validate_toolchain(self, fail = fail):
|
def _validate_toolchain(self, fail = fail):
|
||||||
known_features = _get_known_features(self.features, fail = fail)
|
capabilities = []
|
||||||
|
for tool in self.tool_map.configs.values():
|
||||||
|
capabilities.extend([cap.feature for cap in tool.capabilities])
|
||||||
|
known_features = _get_known_features(self.features, capabilities, fail = fail)
|
||||||
|
|
||||||
for feature in self.features:
|
for feature in self.features:
|
||||||
_validate_feature(feature, known_features, fail = fail)
|
_validate_feature(feature, known_features, fail = fail)
|
||||||
|
|
|
@ -14,9 +14,10 @@
|
||||||
"""Implementation of cc_tool"""
|
"""Implementation of cc_tool"""
|
||||||
|
|
||||||
load("@bazel_skylib//rules/directory:providers.bzl", "DirectoryInfo")
|
load("@bazel_skylib//rules/directory:providers.bzl", "DirectoryInfo")
|
||||||
load("//cc/toolchains/impl:collect.bzl", "collect_data")
|
load("//cc/toolchains/impl:collect.bzl", "collect_data", "collect_provider")
|
||||||
load(
|
load(
|
||||||
":cc_toolchain_info.bzl",
|
":cc_toolchain_info.bzl",
|
||||||
|
"ToolCapabilityInfo",
|
||||||
"ToolInfo",
|
"ToolInfo",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -38,6 +39,7 @@ def _cc_tool_impl(ctx):
|
||||||
allowlist_include_directories = depset(
|
allowlist_include_directories = depset(
|
||||||
direct = [d[DirectoryInfo] for d in ctx.attr.allowlist_include_directories],
|
direct = [d[DirectoryInfo] for d in ctx.attr.allowlist_include_directories],
|
||||||
),
|
),
|
||||||
|
capabilities = tuple(collect_provider(ctx.attr.capabilities, ToolCapabilityInfo)),
|
||||||
)
|
)
|
||||||
|
|
||||||
link = ctx.actions.declare_file(ctx.label.name)
|
link = ctx.actions.declare_file(ctx.label.name)
|
||||||
|
@ -94,6 +96,13 @@ and/or `-fno-canonical-system-headers` arguments.
|
||||||
This can help work around errors like:
|
This can help work around errors like:
|
||||||
`the source file 'main.c' includes the following non-builtin files with absolute paths
|
`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)`.
|
(if these are builtin files, make sure these paths are in your toolchain)`.
|
||||||
|
""",
|
||||||
|
),
|
||||||
|
"capabilities": attr.label_list(
|
||||||
|
providers = [ToolCapabilityInfo],
|
||||||
|
doc = """Declares that a tool is capable of doing something.
|
||||||
|
|
||||||
|
For example, `//cc/toolchains/capabilities:supports_pic`.
|
||||||
""",
|
""",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -120,6 +129,7 @@ cc_tool(
|
||||||
# Suppose clang needs libc to run.
|
# Suppose clang needs libc to run.
|
||||||
data = ["@llvm_toolchain//:lib/x86_64-linux-gnu/libc.so.6"]
|
data = ["@llvm_toolchain//:lib/x86_64-linux-gnu/libc.so.6"]
|
||||||
tags = ["requires-network"],
|
tags = ["requires-network"],
|
||||||
|
capabilities = ["//cc/toolchains/capabilities:supports_pic"],
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
""",
|
""",
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
# 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_tool_capability rule."""
|
||||||
|
|
||||||
|
load(
|
||||||
|
":cc_toolchain_info.bzl",
|
||||||
|
"ArgsListInfo",
|
||||||
|
"FeatureConstraintInfo",
|
||||||
|
"FeatureInfo",
|
||||||
|
"ToolCapabilityInfo",
|
||||||
|
)
|
||||||
|
|
||||||
|
def _cc_tool_capability_impl(ctx):
|
||||||
|
ft = FeatureInfo(
|
||||||
|
name = ctx.attr.feature_name or ctx.label.name,
|
||||||
|
label = ctx.label,
|
||||||
|
enabled = False,
|
||||||
|
args = ArgsListInfo(
|
||||||
|
label = ctx.label,
|
||||||
|
args = (),
|
||||||
|
files = depset(),
|
||||||
|
by_action = (),
|
||||||
|
allowlist_include_directories = depset(),
|
||||||
|
),
|
||||||
|
implies = depset(),
|
||||||
|
requires_any_of = (),
|
||||||
|
mutually_exclusive = (),
|
||||||
|
# Mark it as external so that it doesn't complain if we say
|
||||||
|
# "requires" on a constraint that was never referenced elsewhere
|
||||||
|
# in the toolchain.
|
||||||
|
external = True,
|
||||||
|
overridable = True,
|
||||||
|
overrides = None,
|
||||||
|
allowlist_include_directories = depset(),
|
||||||
|
)
|
||||||
|
return [
|
||||||
|
ToolCapabilityInfo(label = ctx.label, feature = ft),
|
||||||
|
# Only give it a feature constraint info and not a feature info.
|
||||||
|
# This way you can't imply it - you can only require it.
|
||||||
|
FeatureConstraintInfo(label = ctx.label, all_of = depset([ft])),
|
||||||
|
]
|
||||||
|
|
||||||
|
cc_tool_capability = rule(
|
||||||
|
implementation = _cc_tool_capability_impl,
|
||||||
|
provides = [ToolCapabilityInfo, FeatureConstraintInfo],
|
||||||
|
doc = """A capability is an optional feature that a tool supports.
|
||||||
|
|
||||||
|
For example, not all compilers support PIC, so to handle this, we write:
|
||||||
|
|
||||||
|
```
|
||||||
|
cc_tool(
|
||||||
|
name = "clang",
|
||||||
|
src = "@host_tools/bin/clang",
|
||||||
|
capabilities = [
|
||||||
|
"//cc/toolchains/capabilities:supports_pic",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_args(
|
||||||
|
name = "pic",
|
||||||
|
requires = [
|
||||||
|
"//cc/toolchains/capabilities:supports_pic"
|
||||||
|
],
|
||||||
|
args = ["-fPIC"],
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
This ensures that `-fPIC` is added to the command-line only when we are using a
|
||||||
|
tool that supports PIC.
|
||||||
|
""",
|
||||||
|
attrs = {
|
||||||
|
"feature_name": attr.string(doc = "The name of the feature to generate for this capability"),
|
||||||
|
},
|
||||||
|
)
|
|
@ -380,7 +380,7 @@ cc_feature(
|
||||||
## cc_tool
|
## cc_tool
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
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>)
|
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-capabilities">capabilities</a>)
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
Declares a tool for use by toolchain actions.
|
Declares a tool for use by toolchain actions.
|
||||||
|
@ -405,6 +405,7 @@ cc_tool(
|
||||||
# Suppose clang needs libc to run.
|
# Suppose clang needs libc to run.
|
||||||
data = ["@llvm_toolchain//:lib/x86_64-linux-gnu/libc.so.6"]
|
data = ["@llvm_toolchain//:lib/x86_64-linux-gnu/libc.so.6"]
|
||||||
tags = ["requires-network"],
|
tags = ["requires-network"],
|
||||||
|
capabilities = ["@rules_cc//cc/toolchains/capabilities:supports_pic"],
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -417,6 +418,49 @@ cc_tool(
|
||||||
| <a id="cc_tool-src"></a>src | The underlying binary that this tool represents.<br><br>Usually just a single prebuilt (eg. @toolchain//:bin/clang), but may be any executable label. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
|
| <a id="cc_tool-src"></a>src | The underlying binary that this tool represents.<br><br>Usually just a single prebuilt (eg. @toolchain//:bin/clang), but may be any executable label. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
|
||||||
| <a id="cc_tool-data"></a>data | Additional files that are required for this tool to run.<br><br>Frequently, clang and gcc require additional files to execute as they often shell out to other binaries (e.g. `cc1`). | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
| <a id="cc_tool-data"></a>data | Additional files that are required for this tool to run.<br><br>Frequently, clang and gcc require additional files to execute as they often shell out to other binaries (e.g. `cc1`). | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||||
| <a id="cc_tool-allowlist_include_directories"></a>allowlist_include_directories | Include paths implied by using this tool.<br><br>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>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)`. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
| <a id="cc_tool-allowlist_include_directories"></a>allowlist_include_directories | Include paths implied by using this tool.<br><br>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>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)`. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||||
|
| <a id="cc_tool-capabilities"></a>capabilities | Declares that a tool is capable of doing something.<br><br>For example, `@rules_cc//cc/toolchains/capabilities:supports_pic`. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
|
||||||
|
|
||||||
|
|
||||||
|
<a id="cc_tool_capability"></a>
|
||||||
|
|
||||||
|
## cc_tool_capability
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
cc_tool_capability(<a href="#cc_tool_capability-name">name</a>, <a href="#cc_tool_capability-feature_name">feature_name</a>)
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
A capability is an optional feature that a tool supports.
|
||||||
|
|
||||||
|
For example, not all compilers support PIC, so to handle this, we write:
|
||||||
|
|
||||||
|
```
|
||||||
|
cc_tool(
|
||||||
|
name = "clang",
|
||||||
|
src = "@host_tools/bin/clang",
|
||||||
|
capabilities = [
|
||||||
|
"@rules_cc//cc/toolchains/capabilities:supports_pic",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_args(
|
||||||
|
name = "pic",
|
||||||
|
requires = [
|
||||||
|
"@rules_cc//cc/toolchains/capabilities:supports_pic"
|
||||||
|
],
|
||||||
|
args = ["-fPIC"],
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
This ensures that `-fPIC` is added to the command-line only when we are using a
|
||||||
|
tool that supports PIC.
|
||||||
|
|
||||||
|
**ATTRIBUTES**
|
||||||
|
|
||||||
|
|
||||||
|
| Name | Description | Type | Mandatory | Default |
|
||||||
|
| :------------- | :------------- | :------------- | :------------- | :------------- |
|
||||||
|
| <a id="cc_tool_capability-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
|
||||||
|
| <a id="cc_tool_capability-feature_name"></a>feature_name | The name of the feature to generate for this capability | String | optional | `""` |
|
||||||
|
|
||||||
|
|
||||||
<a id="cc_args"></a>
|
<a id="cc_args"></a>
|
||||||
|
|
|
@ -67,7 +67,7 @@ def generate_factory(type, name, attrs):
|
||||||
meta.add_failure("Wanted a %s but got" % name, value)
|
meta.add_failure("Wanted a %s but got" % name, value)
|
||||||
got_keys = sorted(structs.to_dict(value).keys())
|
got_keys = sorted(structs.to_dict(value).keys())
|
||||||
subjects.collection(got_keys, meta = meta.derive(details = [
|
subjects.collection(got_keys, meta = meta.derive(details = [
|
||||||
"Value was not a %s - it has a different set of fields" % name,
|
"Value %r was not a %s - it has a different set of fields" % (value, name),
|
||||||
])).contains_exactly(want_keys).in_order()
|
])).contains_exactly(want_keys).in_order()
|
||||||
|
|
||||||
def type_factory(value, *, meta):
|
def type_factory(value, *, meta):
|
||||||
|
|
|
@ -26,6 +26,7 @@ load(
|
||||||
"FeatureSetInfo",
|
"FeatureSetInfo",
|
||||||
"MutuallyExclusiveCategoryInfo",
|
"MutuallyExclusiveCategoryInfo",
|
||||||
"NestedArgsInfo",
|
"NestedArgsInfo",
|
||||||
|
"ToolCapabilityInfo",
|
||||||
"ToolConfigInfo",
|
"ToolConfigInfo",
|
||||||
"ToolInfo",
|
"ToolInfo",
|
||||||
"ToolchainConfigInfo",
|
"ToolchainConfigInfo",
|
||||||
|
@ -178,6 +179,15 @@ _FeatureFactory = generate_factory(
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# buildifier: disable=name-conventions
|
||||||
|
_ToolCapabilityFactory = generate_factory(
|
||||||
|
ToolCapabilityInfo,
|
||||||
|
"ToolCapabilityInfo",
|
||||||
|
dict(
|
||||||
|
name = _subjects.str,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
# buildifier: disable=name-conventions
|
# buildifier: disable=name-conventions
|
||||||
_ToolFactory = generate_factory(
|
_ToolFactory = generate_factory(
|
||||||
ToolInfo,
|
ToolInfo,
|
||||||
|
@ -187,6 +197,7 @@ _ToolFactory = generate_factory(
|
||||||
runfiles = runfiles_subject,
|
runfiles = runfiles_subject,
|
||||||
execution_requirements = _subjects.collection,
|
execution_requirements = _subjects.collection,
|
||||||
allowlist_include_directories = _FakeDirectoryDepset,
|
allowlist_include_directories = _FakeDirectoryDepset,
|
||||||
|
capabilities = ProviderSequence(_ToolCapabilityFactory),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ load(":tool_test.bzl", "TARGETS", "TESTS")
|
||||||
cc_tool(
|
cc_tool(
|
||||||
name = "tool",
|
name = "tool",
|
||||||
src = "//tests/rule_based_toolchain/testdata:bin_wrapper.sh",
|
src = "//tests/rule_based_toolchain/testdata:bin_wrapper.sh",
|
||||||
|
capabilities = ["//cc/toolchains/capabilities:supports_pic"],
|
||||||
data = ["//tests/rule_based_toolchain/testdata:bin"],
|
data = ["//tests/rule_based_toolchain/testdata:bin"],
|
||||||
tags = ["requires-network"],
|
tags = ["requires-network"],
|
||||||
)
|
)
|
||||||
|
|
|
@ -47,6 +47,7 @@ cc_tool(
|
||||||
name = "c_compile_tool",
|
name = "c_compile_tool",
|
||||||
src = "//tests/rule_based_toolchain/testdata:bin_wrapper",
|
src = "//tests/rule_based_toolchain/testdata:bin_wrapper",
|
||||||
allowlist_include_directories = ["//tests/rule_based_toolchain/testdata:subdirectory_3"],
|
allowlist_include_directories = ["//tests/rule_based_toolchain/testdata:subdirectory_3"],
|
||||||
|
capabilities = ["//cc/toolchains/capabilities:supports_pic"],
|
||||||
)
|
)
|
||||||
|
|
||||||
cc_sysroot(
|
cc_sysroot(
|
||||||
|
|
|
@ -207,6 +207,10 @@ def _toolchain_collects_files_test(env, targets):
|
||||||
],
|
],
|
||||||
)],
|
)],
|
||||||
),
|
),
|
||||||
|
legacy_feature(
|
||||||
|
name = "supports_pic",
|
||||||
|
enabled = False,
|
||||||
|
),
|
||||||
legacy_feature(
|
legacy_feature(
|
||||||
name = "implied_by_always_enabled",
|
name = "implied_by_always_enabled",
|
||||||
enabled = True,
|
enabled = True,
|
||||||
|
@ -252,6 +256,7 @@ def _toolchain_collects_files_test(env, targets):
|
||||||
action_name = "c_compile",
|
action_name = "c_compile",
|
||||||
enabled = True,
|
enabled = True,
|
||||||
tools = [legacy_tool(tool = exe)],
|
tools = [legacy_tool(tool = exe)],
|
||||||
|
implies = ["supports_pic"],
|
||||||
),
|
),
|
||||||
legacy_action_config(
|
legacy_action_config(
|
||||||
action_name = "cpp_compile",
|
action_name = "cpp_compile",
|
||||||
|
|
Loading…
Reference in New Issue