| --- | |
| layout: documentation | |
| title: Toolchains | |
| --- | |
| # Toolchains | |
| - [Overview](#overview) | |
| - [Toolchain Resolution](#toolchain-resolution) | |
| - [Defining a toolchain](#defining-a-toolchain) | |
| - [Creating a toolchain rule](#creating-a-toolchain-rule) | |
| - [Creating a toolchain definition](#creating-a-toolchain-definition) | |
| - [Registering a toolchain](#registering-a-toolchain) | |
| - [Using a toolchain in a new rule](#using-a-toolchain-in-a-rule) | |
| - [Debugging a toolchain](#debugging-a-toolchain) | |
| ## Overview | |
| A *Bazel toolchain* is a configuration | |
| [provider](skylark/rules.html#providers) | |
| that tells a build rule what build tools, such as compilers and linkers, to use | |
| and how to configure them using parameters defined by the rule's creator. | |
| When a build runs, Bazel performs toolchain resolution based on the specified | |
| [execution and target platforms](platforms.html) | |
| to determine and apply the | |
| toolchain most appropriate to that build. It does so by matching the | |
| [constraints](platforms.html#defining-a-platform) | |
| specified in the project's | |
| `BUILD` file(s) with the constraints specified in the toolchain definition. | |
| ## Toolchain Resolution | |
| Inputs to the resolution mechanism include the required toolchain types (including | |
| none) and the target platform. The resolution mechanism outputs a single execution | |
| platform and a toolchain type-to-toolchain map. Toolchain resolution works as follows: | |
| 1. Collect all available execution platforms, including the host. This is an ordered list. | |
| - Execution platforms are collected from the following sources: | |
| 1. Any extra execution platforms given on the command line via the | |
| [`--extra_execution_platforms`](https://docs.bazel.build/versions/master/command-line-reference.html#flag--extra_execution_platforms) | |
| flag. | |
| 2. Any execution platforms in the `WORKSPACE` file, via the | |
| [`register_execution_platforms`](https://docs.bazel.build/versions/master/skylark/lib/globals.html#register_execution_platforms) | |
| function. | |
| 3. The host platform. | |
| 2. Collect all available toolchains. This is also an ordered list. | |
| - Toolchains are collected from the following sources: | |
| 1. Any extra toolchains given on the command line via the | |
| [`--extra_toolchains`](https://docs.bazel.build/versions/master/command-line-reference.html#flag--extra_toolchains) | |
| flag. | |
| 2. Any toolchains in the `WORKSPACE` file, via the | |
| [`register_toolchains`](https://docs.bazel.build/versions/master/skylark/lib/globals.html#register_toolchains) | |
| function. | |
| 3. For each toolchain type and execution platform, select the first toolchain that matches the execution platform and target platform. | |
| 4. With the full set of toolchains and execution platforms for each type, select the first execution platform that can satisfy all toolchain types. | |
| Execution platforms listed first are preferred, and toolchains listed first are preferred. | |
| Every configured target has the same execution platform for all actions that target generates. | |
| Because Bazel always selects the first matching toolchain, order the toolchains | |
| by preference if you expect the possibility of multiple matches. | |
| **Note:** Some Bazel rules do not yet support toolchain resolution. | |
| ## Defining a toolchain | |
| Defining a toolchain requires the following: | |
| * **Toolchain rule** - a rule invoked in a custom build or test rule that | |
| specifies the build tool configuration options particular to the toolchain | |
| and supported | |
| [platforms](platforms.html) | |
| (for example, [`go_toolchain`](https://github.com/bazelbuild/rules_go/blob/master/go/private/go_toolchain.bzl)). | |
| This rule must return a | |
| [`ToolchainInfo` provider](skylark/lib/platform_common.html#ToolchainInfo). | |
| The toolchain rule is lazily instantiated by Bazel on an as-needed basis. | |
| Because of this, a toolchain rule's dependencies can be as complex as needed, | |
| including reliance on remote repositories, without affecting builds that do | |
| not use them. | |
| * **Toolchain definition** - tells Bazel which | |
| [platform constraints](platforms.html#defining-a-platform) | |
| apply to the toolchain using the `toolchain()` rule. This rule must specify a | |
| unique toolchain type label, which is used as input during toolchain | |
| resolution. | |
| * **Toolchain registration** - makes the toolchain available to a Bazel project | |
| using the `register_toolchains()` function in the project's `WORKSPACE` file. | |
| ### Creating a toolchain rule | |
| Toolchain rules are rules that create and return providers. To define a | |
| toolchain rule, first determine the information that the new rule will require. | |
| In the example below, we are adding support for a new programming language, so | |
| we need to specify paths to the compiler and the system libraries, plus a flag | |
| that determines the CPU architecture for which Bazel builds the output. | |
| ```python | |
| def _my_toolchain_impl(ctx): | |
| toolchain = platform_common.ToolchainInfo( | |
| compiler = ctx.attr.compiler, | |
| system_lib = ctx.attr.system_lib, | |
| arch_flags = ctx.attr.arch_flags, | |
| ) | |
| return [toolchain] | |
| my_toolchain = rule( | |
| _my_toolchain_impl, | |
| attrs = { | |
| 'compiler': attr.string(), | |
| 'system_lib': attr.string(), | |
| 'arch_flags': attr.string_list(), | |
| }) | |
| ``` | |
| An example invocation of the rule looks as follows: | |
| ```python | |
| my_toolchain( | |
| name = 'linux_toolchain_impl', | |
| compiler = '@remote_linux_repo//compiler:compiler_binary', | |
| system_lib = '@remote_linux_repo//library:system_library', | |
| arch_flags = [ | |
| '--arch=Linux', | |
| '--debug_everything', | |
| ] | |
| ) | |
| my_toolchain( | |
| name = 'darwin_toolchain_impl', | |
| compiler = '@remote_darwin_repo//compiler:compiler_binary', | |
| system_lib = '@remote_darwin_repo//library:system_library', | |
| arch_flags = [ | |
| '--arch=Darwin', | |
| #'--debug_everything', # --debug_everything currently broken on Darwin | |
| ] | |
| ) | |
| ``` | |
| ### Creating a toolchain definition | |
| The toolchain definition is an instance of the `toolchain()` rule that specifies | |
| the toolchain type, execution and target constraints, and the label of the | |
| actual rule-specific toolchain. The use of the `toolchain()` rule enables the | |
| lazy loading of toolchains. | |
| Below is an example toolchain definition: | |
| ```python | |
| toolchain_type(name = 'my_toolchain_type') | |
| toolchain( | |
| name = 'linux_toolchain', | |
| toolchain_type = '//path/to:my_toolchain_type', | |
| exec_compatible_with = [ | |
| '@bazel_tools//platforms:linux', | |
| '@bazel_tools//platforms:x86_64'], | |
| target_compatible_with = [ | |
| '@bazel_tools//platforms:linux', | |
| '@bazel_tools//platforms:x86_64'], | |
| toolchain = ':linux_toolchain_impl', | |
| ) | |
| ``` | |
| ### Registering a toolchain | |
| Once the toolchain rule and definition exist, register the toolchain to make | |
| Bazel aware of it. You can register a toolchain either via the project's | |
| `WORKSPACE` file or specify it in the `--extra_toolchains` flag. | |
| Below is an example toolchain registration in a `WORKSPACE` file: | |
| ```python | |
| register_toolchains( | |
| '//path/to:linux_toolchain', | |
| '//path/to:darwin_toolchain', | |
| ) | |
| ``` | |
| ## Using a toolchain in a rule | |
| To use a toolchain in a rule, add the toolchain type to the rule | |
| definition. For example: | |
| ```python | |
| my_library = rule( | |
| ... | |
| toolchains = ['//path/to:my_toolchain_type'] | |
| ...) | |
| ``` | |
| When using the `ctx.toolchains` rule, Bazel checks the execution and target | |
| platforms, and select the first toolchain that matches. The rule implementation | |
| can then access the toolchain as follows: | |
| ```python | |
| def _my_library_impl(ctx): | |
| toolchain = ctx.toolchains['//path/to:my_toolchain_type'] | |
| command = '%s -l %s %s' % (toolchain.compiler, toolchain.system_lib, toolchain.arch_flags) | |
| ... | |
| ``` | |
| ## Debugging a toolchain | |
| When adding toolchain support to an existing rule, use the | |
| `--toolchain_resolution_debug` flag to make toolchain resolution verbose. Bazel | |
| will output names of toolchains it is checking and skipping during the | |
| resolution process. |