API reference#

pw_toolchain_bazel: A modular toolkit for declaring C/C++ toolchains in Bazel

class pw_cc_toolchain#

This rule is the core of a C/C++ toolchain definition. Critically, it is intended to fully specify the following:

  • Which tools to use for various compile/link actions.

  • Which well-known features are supported.

  • Which flags to apply to various actions.

action_configs: List[label]#

List of pw_cc_action_config labels that bind tools to the appropriate actions. This is how Bazel knows which binaries to use when compiling, linking, or taking other actions like embedding data using objcopy.

flag_sets: List[label]#

List of flag sets to unconditionally apply to the respective pw_cc_action_configs. The labels listed here will point to pw_cc_flag_set rules.

extra_action_files: List[label]#

List of extra files to give to each different type of action. Replaces all_files, ar_files, compiler_files, … in the existing toolchain definition.

toolchain_identifier: str#

See cc_common.create_cc_toolchain_config_info().

host_system_name: str#

See cc_common.create_cc_toolchain_config_info().

target_system_name: str#

See cc_common.create_cc_toolchain_config_info().

target_cpu: str#

See cc_common.create_cc_toolchain_config_info().

target_libc: str#

See cc_common.create_cc_toolchain_config_info().

compiler: str#

See cc_common.create_cc_toolchain_config_info().

abi_version: str#

See cc_common.create_cc_toolchain_config_info().

abi_libc_version: str#

See cc_common.create_cc_toolchain_config_info().

cc_target_os: str#

See cc_common.create_cc_toolchain_config_info().

builtin_sysroot: str#

See cc_common.create_cc_toolchain_config_info().

cxx_builtin_include_directories: List[str]#

See cc_common.create_cc_toolchain_config_info().

class pw_cc_flag_set#

Declares an ordered set of flags bound to a set of actions.

Flag sets can be attached to a pw_cc_toolchain via pw_cc_toolchain.flag_sets.


    name = "warnings_as_errors",
    flags = ["-Werror"],

    name = "layering_check",
    flag_groups = [

Note: In the vast majority of cases, alphabetical sorting is not desirable for the pw_cc_flag_set.flags and pw_cc_flag_set.flag_groups attributes. Buildifier shouldn’t ever try to sort these, but in the off chance it starts to these members should be listed as exceptions in the SortableDenylist.

actions: List[str]#

A list of action names that this flag set applies to.

Valid choices are listed at @rules_cc//cc:action_names.bzl.

It is possible for some needed action names to not be enumerated in this list, so there is not rigid validation for these strings. Prefer using constants rather than manually typing action names.

flags: List[str]#

Flags that should be applied to the specified actions.

These are evaluated in order, with earlier flags appearing earlier in the invocation of the underlying tool. If you need expansion logic, prefer enumerating flags in a pw_cc_flag_group or create a custom rule that provides FlagGroupInfo.

Note: pw_cc_flag_set.flags and pw_cc_flag_set.flag_groups are mutually exclusive.

flag_groups: List[label]#

Labels pointing to pw_cc_flag_group rules.

This is intended to be compatible with any other rules that provide FlagGroupInfo. These are evaluated in order, with earlier flag groups appearing earlier in the invocation of the underlying tool.

Note: pw_cc_flag_set.flag_groups and pw_cc_flag_set.flags are mutually exclusive.

class pw_cc_flag_group#

Declares an (optionally parametric) ordered set of flags.

pw_cc_flag_group rules are expected to be consumed exclusively by pw_cc_flag_set rules. Though simple lists of flags can be expressed by populating flags on a pw_cc_flag_set, pw_cc_flag_group provides additional power in the following two ways:

  1. Iteration and conditional expansion. Using pw_cc_flag_group.iterate_over, pw_cc_flag_group.expand_if_available, and pw_cc_flag_group.expand_if_not_available, more complex flag expressions can be made. This is critical for implementing things like the libraries_to_link feature, where library names are transformed into flags that end up in the final link invocation.

    Note: expand_if_equal, expand_if_true, and expand_if_false are not yet supported.

  2. Flags are tool-independent. A pw_cc_flag_group expresses ordered flags that may be reused across various pw_cc_flag_set rules. This is useful for cases where multiple pw_cc_flag_set rules must be created to implement a feature for which flags are slightly different depending on the action (e.g. compile vs link). Common flags can be expressed in a shared pw_cc_flag_group, and the differences can be relegated to separate pw_cc_flag_group instances.


    name = "user_compile_flag_expansion",
    flags = ["%{user_compile_flags}"],
    iterate_over = "user_compile_flags",
    expand_if_available = "user_compile_flags",

# This flag_group might be referenced from various FDO-related
# `pw_cc_flag_set` rules. More importantly, the flag sets pulling this in
# may apply to different sets of actions.
    name = "fdo_profile_correction",
    flags = ["-fprofile-correction"],
    expand_if_available = "fdo_profile_path",
flags: List[str]#

List of flags provided by this rule.

For extremely complex expressions of flags that require nested flag groups with multiple layers of expansion, prefer creating a custom rule in Starlark that provides FlagGroupInfo or FlagSetInfo.

iterate_over: str#

Expands pw_cc_flag_group.flags for items in the named list.

Toolchain actions have various variables accessible as names that can be used to guide flag expansions. For variables that are lists, pw_cc_flag_group.iterate_over must be used to expand the list into a series of flags.

Note that pw_cc_flag_group.iterate_over is the string name of a build variable, and not an actual list. Valid options are listed in the C++ Toolchain Configuration reference.

Note that the flag expansion stamps out the entire list of flags in pw_cc_flag_group.flags once for each item in the list.


# Expands each path in ``system_include_paths`` to a series of
# ``-isystem`` includes.
# Example input:
#     system_include_paths = ["/usr/local/include", "/usr/include"]
# Expected result:
#     "-isystem /usr/local/include -isystem /usr/include"
    name = "system_include_paths",
    flags = ["-isystem", "%{system_include_paths}"],
    iterate_over = "system_include_paths",
expand_if_available: str#

Expands the expression in pw_cc_flag_group.flags if the specified build variable is set.

expand_if_not_available: str#

Expands the expression in pw_cc_flag_group.flags if the specified build variable is NOT set.

class pw_cc_tool#

Declares a singular tool that can be bound to action configs.

pw_cc_tool rules are intended to be consumed exclusively by pw_cc_action_config rules. These rules declare an underlying tool that can be used to fulfill various actions. Many actions may reuse a shared tool.


# A project-provided tool.
    name = "clang_tool",
    tool = "@llvm_toolchain//:bin/clang",

# A tool expected to be preinstalled on a user's machine.
    name = "clang_tool",
    path = "/usr/bin/clang",
tool: label#

The underlying tool that this rule represents.

This attribute is a label rather than a simple file path. This means that the file must be referenced relative to the BUILD file that exports it. For example:

^              ^  ^


  • @llvm_toolchain is the repository.

  • // is the directory of the BUILD file that exports the file of interest.

  • bin/clang is the path of the actual binary relative to the BUILD file of interest.

Note: pw_cc_tool.tool and pw_cc_tool.path are mutually exclusive.

path: Path#

An absolute path to a binary to use for this tool.

Relative paths are also supported, but they are relative to the pw_cc_toolchain that uses this tool rather than relative to this pw_cc_tool rule.

Note: pw_cc_tool.path and pw_cc_tool.tool are mutually exclusive.


This method of listing a tool is NOT recommended, and is provided as an escape hatch for edge cases. Prefer using pw_cc_tool.tool whenever possible.

execution_requirements: List[str]#

A list of strings that provide hints for execution environment compatibility (e.g. requires-darwin).

requires_any_of: List[label]#

This tool may only be enabled when at least one of the constraints are met.

If omitted, this tool will be enabled unconditionally.

additional_files: List[label]#

Additional files that are required for this tool to correctly operate. These files are propagated up to the pw_cc_toolchain so you typically won’t need to explicitly specify the *_files attributes on a pw_cc_toolchain.

class pw_cc_action_config#

Declares the configuration and selection of pw_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.

  • pw_cc_flag_sets that are unconditionally bound to a tool invocation.


    name = "ar",
    action_names = ["@pw_toolchain//actions:all_ar_actions"],
    implies = [
    tools = [":ar_tool"],

    name = "clang",
    action_names = [
    tools = [":clang_tool"],
action_names: List[str]#

A list of action names to apply this action to.

Valid choices are listed at @rules_cc//cc:action_names.bzl.

It is possible for some needed action names to not be enumerated in this list, so there is not rigid validation for these strings. Prefer using constants rather than manually typing action names.

enabled: bool#

Whether or not this action config is enabled by default.


This defaults to True since it’s assumed that most listed action configs will be enabled and used by default. This is the opposite of Bazel’s native default.

tools: List[label]#

The tool to use for the specified actions.

A tool can be a pw_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.

flag_sets: List[label]#

Labels that point to pw_cc_flag_sets that are unconditionally bound to the specified actions.


The flags in the pw_cc_flag_set are only bound to matching action names. If an action is listed in this rule’s pw_cc_action_config.action_names, but is NOT listed in the pw_cc_flag_set's pw_cc_flag_set.actions, the flag will not be applied to that action.

implies: List[str]#

Names of features that should be automatically enabled when this tool is used.


If this action config implies an unknown feature, this action config 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!

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 @rules_cc//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.

  • 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.

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.


# 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.
    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
    name = "link_object_files",
    enabled = True,
    feature_name = "supports_start_end_lib",
feature_name: 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.

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.


    name = "sysroot_macos",
    feature_name = "sysroot",

    name = "sysroot_linux",
    feature_name = "sysroot",

While two features with the same 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.

enabled: bool#

Whether or not this feature is enabled by default.

flag_sets: List[label]#

Flag sets that, when expanded, implement this feature.

requires_any_of: List[label]#

A list of feature sets that define toolchain compatibility.

If at least one of the listed pw_cc_features or pw_cc_feature_sets are satisfied (all features exist in the toolchain AND are currently enabled), this feature is deemed compatible and may be enabled.

If this feature cannot be enabled (such as if, in the first example below, thin_lto didn’t exist in the toolchain), it will throw an error.

    name = "requires_thin_lto_and_opt",
    feature_name = "requires_thin_lto_and_opt",
    requires_any_of = [":thin_lto_requirements"]

    name = "requires_thin_lto_or_opt",
    feature_name = "requires_thin_lto_or_opt",
    requires_any_of = [":thin_lto", ":opt"]


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

implies: List[label]#

List of features or action configs enabled along with this feature.


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

mutually_exclusive: List[Label]#

A list of feature or mutually exclusive categories that this feature is mutually exclusive with.


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

class pw_cc_feature_set#

Defines a group of features.

Semantically equivalent to “all of the specified features”, and may be used wherever you can provide multiple features.


    name = "thin_lto_requirements",
    all_of = [
features: List[label]#

Features that must be enabled for this feature set to be deemed compatible with the current toolchain configuration.