Platforms and Toolchains Rules

Report an issue View source

This set of rules exists to allow you to model specific hardware platforms you are building for and specify the specific tools you may need to compile code for those platforms. The user should be familiar with the concepts explained here.

Rules

constraint_setting

View rule source
constraint_setting(name, default_constraint_value, deprecation, distribs, features, licenses, tags, testonly, visibility)

This rule is used to introduce a new constraint type for which a platform may specify a value. For instance, you might define a constraint_setting named "glibc_version" to represent the capability for platforms to have different versions of the glibc library installed. For more details, see the Platforms page.

Each constraint_setting has an extensible set of associated constraint_values. Usually these are defined in the same package, but sometimes a different package will introduce new values for an existing setting. For instance, the predefined setting @platforms//cpu:cpu can be extended with a custom value in order to define a platform targeting an obscure cpu architecture.

Arguments

Attributes
name

Name; required

A unique name for this target.

default_constraint_value

Name; nonconfigurable; default is None

The label of the default value for this setting, to be used if no value is given. If this attribute is present, the constraint_value it points to must be defined in the same package as this constraint_setting.

If a constraint setting has a default value, then whenever a platform does not include any constraint value for that setting, it is the same as if the platform had specified the default value. Otherwise, if there is no default value, the constraint setting is considered to be unspecified by that platform. In that case, the platform would not match against any constraint list (such as for a config_setting) that requires a particular value for that setting.

constraint_value

View rule source
constraint_value(name, constraint_setting, deprecation, distribs, features, licenses, tags, testonly, visibility)
This rule introduces a new value for a given constraint type. For more details, see the Platforms page.

Example

The following creates a new possible value for the predefined constraint_value representing cpu architecture.

constraint_value(
    name = "mips",
    constraint_setting = "@platforms//cpu:cpu",
)
Platforms can then declare that they have the mips architecture as an alternative to x86_64, arm, and so on.

Arguments

Attributes
name

Name; required

A unique name for this target.

constraint_setting

Label; nonconfigurable; required

The constraint_setting for which this constraint_value is a possible choice.

platform

View rule source
platform(name, constraint_values, deprecation, distribs, exec_properties, features, flags, licenses, parents, remote_execution_properties, tags, testonly, visibility)

This rule defines a new platform -- a named collection of constraint choices (such as cpu architecture or compiler version) describing an environment in which part of the build may run. For more details, see the Platforms page.

Example

This defines a platform that describes any environment running Linux on ARM.

platform(
    name = "linux_arm",
    constraint_values = [
        "@platforms//os:linux",
        "@platforms//cpu:arm",
    ],
)

Platform Flags

Platforms may use the flags attribute to specify a list of flags that will be added to the configuration whenever the platform is used as the target platform (i.e., as the value of the --platforms flag).

Flags set from the platform effectively have the highest precedence and overwrite any previous value for that flag, from the command line, rc file, or transition.

Example

platform(
    name = "foo",
    flags = [
        "--dynamic_mode=fully",
        "--//bool_flag",
        "--no//package:other_bool_flag",
    ],
)

This defines a platform named foo. When this is the target platform (either because the user specified --platforms//:foo, because a transition set the //command_line_option:platforms flag to ["//:foo"], or because //:foo was used as an execution platform), then the given flags will be set in the configuration.

Platforms and Repeatable Flags

Some flags will accumulate values when they are repeated, such as --features, --copt, any Starlark flag created as config.string(repeatable = True). These flags are not compatible with setting the flags from the platform: instead, all previous values will be removed and overwritten with the values from the platform.

As an example, given the following platform, the invocation build --platforms=//:repeat_demo --features feature_a --features feature_b will end up with the value of the --feature flag being ["feature_c", "feature_d"], removing the features set on the command line.

platform(
    name = "repeat_demo",
    flags = [
        "--features=feature_c",
        "--features=feature_d",
    ],
)

For this reason, it is discouraged to use repeatable flags in the flags attribute.

Platform Inheritance

Platforms may use the parents attribute to specify another platform that they will inherit constraint values from. Although the parents attribute takes a list, no more than a single value is currently supported, and specifying multiple parents is an error.

When checking for the value of a constraint setting in a platform, first the values directly set (via the constraint_values attribute) are checked, and then the constraint values on the parent. This continues recursively up the chain of parent platforms. In this manner, any values set directly on a platform will override the values set on the parent.

Platforms inherit the exec_properties attribute from the parent platform. The dictionary entries in exec_properties of the parent and child platforms will be combined. If the same key appears in both the parent's and the child's exec_properties, the child's value will be used. If the child platform specifies an empty string as a value, the corresponding property will be unset.

Platforms can also inherit the (deprecated) remote_execution_properties attribute from the parent platform. Note: new code should use exec_properties instead. The logic described below is maintained to be compatible with legacy behavior but will be removed in the future. The logic for setting the remote_execution_platform is as follows when there is a parent platform:

  1. If remote_execution_property is not set on the child platform, the parent's remote_execution_properties will be used.
  2. If remote_execution_property is set on the child platform, and contains the literal string {PARENT_REMOTE_EXECUTION_PROPERTIES}, that macro will be replaced with the contents of the parent's remote_execution_property attribute.
  3. If remote_execution_property is set on the child platform, and does not contain the macro, the child's remote_execution_property will be used unchanged.

Since remote_execution_properties is deprecated and will be phased out, mixing remote_execution_properties and exec_properties in the same inheritance chain is not allowed. Prefer to use exec_properties over the deprecated remote_execution_properties.

Example: Constraint Values

platform(
    name = "parent",
    constraint_values = [
        "@platforms//os:linux",
        "@platforms//cpu:arm",
    ],
)
platform(
    name = "child_a",
    parents = [":parent"],
    constraint_values = [
        "@platforms//cpu:x86_64",
    ],
)
platform(
    name = "child_b",
    parents = [":parent"],
)

In this example, the child platforms have the following properties:

  • child_a has the constraint values @platforms//os:linux (inherited from the parent) and @platforms//cpu:x86_64 (set directly on the platform).
  • child_b inherits all constraint values from the parent, and doesn't set any of its own.

Example: Execution properties

platform(
    name = "parent",
    exec_properties = {
      "k1": "v1",
      "k2": "v2",
    },
)
platform(
    name = "child_a",
    parents = [":parent"],
)
platform(
    name = "child_b",
    parents = [":parent"],
    exec_properties = {
      "k1": "child"
    }
)
platform(
    name = "child_c",
    parents = [":parent"],
    exec_properties = {
      "k1": ""
    }
)
platform(
    name = "child_d",
    parents = [":parent"],
    exec_properties = {
      "k3": "v3"
    }
)

In this example, the child platforms have the following properties:

  • child_a inherits the "exec_properties" of the parent and does not set its own.
  • child_b inherits the parent's exec_properties and overrides the value of k1. Its exec_properties will be: { "k1": "child", "k2": "v2" }.
  • child_c inherits the parent's exec_properties and unsets k1. Its exec_properties will be: { "k2": "v2" }.
  • child_d inherits the parent's exec_properties and adds a new property. Its exec_properties will be: { "k1": "v1", "k2": "v2", "k3": "v3" }.

Arguments

Attributes
name

Name; required

A unique name for this target.

constraint_values

List of labels; nonconfigurable; default is []

The combination of constraint choices that this platform comprises. In order for a platform to apply to a given environment, the environment must have at least the values in this list.

Each constraint_value in this list must be for a different constraint_setting. For example, you cannot define a platform that requires the cpu architecture to be both @platforms//cpu:x86_64 and @platforms//cpu:arm.

exec_properties

Dictionary: String -> String; nonconfigurable; default is {}

A map of strings that affect the way actions are executed remotely. Bazel makes no attempt to interpret this, it is treated as opaque data that's forwarded via the Platform field of the remote execution protocol. This includes any data from the parent platform's exec_properties attributes. If the child and parent platform define the same keys, the child's values are kept. Any keys associated with a value that is an empty string are removed from the dictionary. This attribute is a full replacement for the deprecated remote_execution_properties.
flags

List of strings; nonconfigurable; default is []

A list of flags that will be enabled when this platform is used as the target platform in a configuration. Only flags that can be set in transitions are allowed to be used.
parents

List of labels; nonconfigurable; default is []

The label of a platform target that this platform should inherit from. Although the attribute takes a list, there should be no more than one platform present. Any constraint_settings not set directly on this platform will be found in the parent platform. See the section on Platform Inheritance for details.
remote_execution_properties

String; nonconfigurable; default is ""

DEPRECATED. Please use exec_properties attribute instead. A string used to configure a remote execution platform. Actual builds make no attempt to interpret this, it is treated as opaque data that can be used by a specific SpawnRunner. This can include data from the parent platform's "remote_execution_properties" attribute, by using the macro "{PARENT_REMOTE_EXECUTION_PROPERTIES}". See the section on Platform Inheritance for details.

toolchain

View rule source
toolchain(name, deprecation, distribs, exec_compatible_with, features, licenses, tags, target_compatible_with, target_settings, testonly, toolchain, toolchain_type, visibility)

This rule declares a specific toolchain's type and constraints so that it can be selected during toolchain resolution. See the Toolchains page for more details.

Arguments

Attributes
name

Name; required

A unique name for this target.

exec_compatible_with

List of labels; nonconfigurable; default is []

A list of constraint_values that must be satisfied by an execution platform in order for this toolchain to be selected for a target building on that platform.
target_compatible_with

List of labels; nonconfigurable; default is []

A list of constraint_values that must be satisfied by the target platform in order for this toolchain to be selected for a target building for that platform.
target_settings

List of labels; default is []

A list of config_settings that must be satisfied by the target configuration in order for this toolchain to be selected during toolchain resolution.
toolchain

Name; required

The target representing the actual tool or tool suite that is made available when this toolchain is selected.
toolchain_type

Label; nonconfigurable; required

The label of a toolchain_type target that represents the role that this toolchain serves.

toolchain_type

View rule source
toolchain_type(name, compatible_with, deprecation, features, restricted_to, tags, target_compatible_with, testonly, visibility)

This rule defines a new type of toolchain -- a simple target that represents a class of tools that serve the same role for different platforms.

See the Toolchains page for more details.

Example

This defines a toolchain type for a custom rule.

toolchain_type(
    name = "bar_toolchain_type",
)

This can be used in a bzl file.

bar_binary = rule(
    implementation = _bar_binary_impl,
    attrs = {
        "srcs": attr.label_list(allow_files = True),
        ...
        # No `_compiler` attribute anymore.
    },
    toolchains = ["//bar_tools:toolchain_type"]
)

Arguments

Attributes
name

Name; required

A unique name for this target.