Skip to content

Commit

Permalink
pw_toolchain_bazel: Add pw_cc_feature
Browse files Browse the repository at this point in the history
Introduces initial support for pw_cc_feature, which completes the
initial set of rules required to build toolchains using this module.

Bug: b/309533028
Change-Id: I66e0e7bbb1ee5011efd299683b3cb86c144d1112
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/181755
Reviewed-by: Ted Pudlik <tpudlik@google.com>
Presubmit-Verified: CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>
Commit-Queue: Armando Montanez <amontanez@google.com>
  • Loading branch information
armandomontanez authored and CQ Bot Account committed Jan 20, 2024
1 parent f841613 commit 9425a61
Show file tree
Hide file tree
Showing 5 changed files with 428 additions and 4 deletions.
24 changes: 24 additions & 0 deletions pw_toolchain/host_clang/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@

load(
"@pw_toolchain//cc_toolchain:defs.bzl",
"ALL_ASM_ACTIONS",
"ALL_CPP_COMPILER_ACTIONS",
"ALL_C_COMPILER_ACTIONS",
"ALL_LINK_ACTIONS",
"pw_cc_feature",
"pw_cc_flag_set",
"pw_cc_toolchain",
)
Expand Down Expand Up @@ -73,6 +75,24 @@ pw_cc_flag_set(
],
)

pw_cc_flag_set(
name = "verbose_compiler_flags",
actions = ALL_ASM_ACTIONS + ALL_C_COMPILER_ACTIONS + ALL_CPP_COMPILER_ACTIONS + ALL_LINK_ACTIONS,
flags = ["-v"],
)

# A feature that can be easily toggled to include extra compiler output to help
# debug things like include search path ordering and showing all the flags
# passed to the compiler.
#
# Add `--features=verbose_compiler_output` to your Bazel invocation to enable.
pw_cc_feature(
name = "verbose_compiler_output",
enabled = False,
feature_name = "verbose_compiler_output",
flag_sets = [":verbose_compiler_flags"],
)

pw_cc_flag_set(
name = "no_unknown_warning_option",
actions = ALL_C_COMPILER_ACTIONS + ALL_CPP_COMPILER_ACTIONS,
Expand Down Expand Up @@ -158,6 +178,10 @@ pw_cc_toolchain(
"@platforms//os:macos": "macosx",
"//conditions:default": None,
}),
target_system_name = "unknown",
toolchain_features = [
":verbose_compiler_output",
],
toolchain_identifier = "host-toolchain",
)

Expand Down
185 changes: 185 additions & 0 deletions pw_toolchain_bazel/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -581,3 +581,188 @@ API reference
will silently be disabled. This behavior is native to Bazel itself, and
there's no way to detect this and emit an error instead. For this
reason, be very cautious when listing implied features!

.. py:class:: pw_cc_feature
Defines the implemented behavior of a C/C++ toolchain feature.


This rule is effectively a wrapper for the ``feature`` constructor in
`@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl <https://github.com/bazelbuild/rules_cc/blob/main/cc/cc_toolchain_config_lib.bzl>`_.

A feature is basically a dynamic flag set. There are a variety of
dependencies and compatibility requirements that must be satisfied for the
listed flag sets to be applied.

A feature may be enabled or disabled through the following mechanisms:\

* Via command-line flags, or a
`.bazelrc file <https://bazel.build/run/bazelrc>`_\.
* Through inter-feature relationships (enabling one feature may implicitly
enable another).
* Individual rules may elect to manually enable or disable features through
the
`builtin features attribute <https://bazel.build/reference/be/common-definitions#common.features>`_\.

Because of the dynamic nature of toolchain features, it's generally best to
avoid enumerating features as part of your toolchain with the following
exceptions:

* You want the flags to be controllable via Bazel's CLI. For example, adding
``-v`` to a compiler invocation is often too verbose to be useful for most
workflows, but can be instrumental when debugging obscure errors. By
expressing compiler verbosity as a feature, users may opt-in when
necessary.
* You need to carry forward Starlark toolchain behaviors. If you're migrating
a complex Starlark-based toolchain definition to these rules, many of the
workflows and flags were likely based on features. This rule exists to
support those existing structures.

For more details about how Bazel handles features, see the official Bazel
documentation at
https://bazel.build/docs/cc-toolchain-config-reference#features.

Note: ``env_sets`` are not yet supported.

Examples:

.. code-block:: py
# A feature that can be easily toggled to include extra compiler output to
# help debug things like include search path ordering and showing all the
# flags passed to the compiler.
#
# Add `--features=verbose_compiler_output` to your Bazel invocation to
# enable.
pw_cc_feature(
name = "verbose_compiler_output",
enabled = False,
feature_name = "verbose_compiler_output",
flag_sets = [":verbose_compiler_flags"],
)
# This feature signals a capability, and doesn't have associated flags.
#
# For a list of well-known features, see:
# https://bazel.build/docs/cc-toolchain-config-reference#wellknown-features
pw_cc_feature(
name = "link_object_files",
enabled = True,
feature_name = "supports_start_end_lib",
)
.. py:attribute:: feature_name
:type: str

The name of the feature that this rule implements.

Feature names are used to express feature dependencies and compatibility.
Because features are tracked by string names rather than labels, there's
great flexibility in swapping out feature implementations or overriding
the built-in legacy features that Bazel silently binds to every
toolchain.

:py:attr:`pw_cc_feature.feature_name` is used rather than ``name`` to
distinguish between the rule name, and the intended final feature name.
This allows similar rules to exist in the same package, even if slight
differences are required.

Example:

.. code-block:: py
pw_cc_feature(
name = "sysroot_macos",
feature_name = "sysroot",
...
)
pw_cc_feature(
name = "sysroot_linux",
feature_name = "sysroot",
...
)
While two features with the same :py:attr:`pw_cc_feature.feature_name` may
not be bound to the same toolchain, they can happily live alongside each
other in the same BUILD file.

.. py:attribute:: enabled
:type: bool

Whether or not this feature is enabled by default.

.. py:attribute:: flag_sets
:type: List[label]

Flag sets that, when expanded, implement this feature.

.. py:attribute:: requires
:type: List[label]

A list of feature sets that define toolchain compatibility.

If **at least one** of the listed :py:class:`pw_cc_feature_set`\s are
satisfied (all features exist in the toolchain AND are currently enabled),
this feature is deemed compatible and may be enabled.

.. admonition:: Note

Even if :py:attr:`pw_cc_feature.requires` is satisfied, a feature is
not enabled unless another mechanism (e.g. command-line flags,
:py:attr:`pw_cc_feature.implies`, or :py:attr:`pw_cc_feature.enabled`\)
signals that the feature should actually be enabled.

.. py:attribute:: implies
:type: List[str]

Names of features enabled along with this feature.

.. admonition:: Note
:class: warning

If any of the named features cannot be enabled, this feature is
silently disabled.

.. py:attribute:: provides
:type: List[str]

A list of additional feature names this feature fulfills.

.. admonition:: Note

This feature cannot be enabled if another feature also provides the
listed feature names.


.. py:class:: pw_cc_feature_set
Defines a set of required features.

This rule is effectively a wrapper for the ``feature_set`` constructor in
`@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl <https://github.com/bazelbuild/rules_cc/blob/main/cc/cc_toolchain_config_lib.bzl>`_.

This rule is used to express a group of features that may satisfy a
:py:attr:`pw_cc_feature.requires` list. If **all** of the specified features
in a :py:class:`pw_cc_feature_set` are enabled, the :py:class:`pw_cc_feature`
that lists the feature set *can* also be enabled. Note that **this does cause
the feature to be enabled**; it only means it is possible for the feature to
be enabled.

Example:

.. code-block:: py
pw_cc_feature_set(
name = "thin_lto_requirements",
feature_names = [
"thin_lto",
"opt",
],
)
.. py:attribute:: feature_names
:type: List[str]

Features that must be enabled for this feature set to be deemed compatible
with the current toolchain configuration.
8 changes: 8 additions & 0 deletions pw_toolchain_bazel/cc_toolchain/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ load(
"//cc_toolchain/private:cc_toolchain.bzl",
_pw_cc_toolchain = "pw_cc_toolchain",
)
load(
"//cc_toolchain/private:feature.bzl",
_pw_cc_feature = "pw_cc_feature",
_pw_cc_feature_set = "pw_cc_feature_set",
)
load(
"//cc_toolchain/private:flag_set.bzl",
_pw_cc_flag_group = "pw_cc_flag_group",
Expand Down Expand Up @@ -66,6 +71,9 @@ ALL_STRIP_ACTIONS = [STRIP_ACTION_NAME]
pw_cc_action_config = _pw_cc_action_config
pw_cc_tool = _pw_cc_tool

pw_cc_feature = _pw_cc_feature
pw_cc_feature_set = _pw_cc_feature_set

pw_cc_flag_group = _pw_cc_flag_group
pw_cc_flag_set = _pw_cc_flag_set

Expand Down
9 changes: 5 additions & 4 deletions pw_toolchain_bazel/cc_toolchain/private/cc_toolchain.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES")
load(
"@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl",
"ActionConfigInfo",
"FeatureInfo",
"FlagSetInfo",
"action_config",
"feature",
Expand Down Expand Up @@ -53,6 +54,7 @@ PW_CC_TOOLCHAIN_DEPRECATED_TOOL_ATTRS = {
PW_CC_TOOLCHAIN_CONFIG_ATTRS = {
"action_configs": "List of `pw_cc_action_config` labels that bind tools to the appropriate actions",
"action_config_flag_sets": "List of `pw_cc_flag_set`s to apply to their respective action configs",
"toolchain_features": "List of `pw_cc_feature`s that this toolchain supports",

# Attributes originally part of create_cc_toolchain_config_info.
"toolchain_identifier": "See documentation for cc_common.create_cc_toolchain_config_info()",
Expand All @@ -73,7 +75,7 @@ PW_CC_TOOLCHAIN_SHARED_ATTRS = ["toolchain_identifier"]
PW_CC_TOOLCHAIN_BLOCKED_ATTRS = {
"toolchain_config": "pw_cc_toolchain includes a generated toolchain config",
"artifact_name_patterns": "pw_cc_toolchain does not yet support artifact name patterns",
"features": "pw_cc_toolchain does not yet support features",
"features": "Use toolchain_features to add pw_cc_toolchain_feature deps to the toolchain",
"tool_paths": "pw_cc_toolchain does not support tool_paths, use \"action_configs\" to set toolchain tools",
"make_variables": "pw_cc_toolchain does not yet support make variables",
}
Expand Down Expand Up @@ -239,9 +241,7 @@ def _pw_cc_toolchain_config_impl(ctx):
all_actions = _collect_action_configs(ctx, flag_sets_by_action)
builtin_include_dirs = ctx.attr.cxx_builtin_include_directories if ctx.attr.cxx_builtin_include_directories else []
sysroot_dir = ctx.attr.builtin_sysroot if ctx.attr.builtin_sysroot else None

# TODO: b/309533028 - Support features.
features = []
features = [dep[FeatureInfo] for dep in ctx.attr.toolchain_features]

# TODO: b/297413805 - This could be externalized.
features.append(_archiver_flags_feature(ctx.attr.target_libc == "macosx"))
Expand Down Expand Up @@ -269,6 +269,7 @@ pw_cc_toolchain_config = rule(
# Attributes new to this rule.
"action_configs": attr.label_list(),
"action_config_flag_sets": attr.label_list(providers = [FlagSetInfo]),
"toolchain_features": attr.label_list(providers = [FeatureInfo]),

# Attributes from create_cc_toolchain_config_info.
"toolchain_identifier": attr.string(),
Expand Down
Loading

0 comments on commit 9425a61

Please sign in to comment.