Rewrite Bazel platform and toolchain documentation for clarity and split into separate topics.

PiperOrigin-RevId: 174510719
diff --git a/site/_layouts/documentation.html b/site/_layouts/documentation.html
index 7b64038..402d713 100644
--- a/site/_layouts/documentation.html
+++ b/site/_layouts/documentation.html
@@ -123,6 +123,7 @@
               <li><a href="/versions/{{ site.version }}/best-practices.html">Best Practices</a></li>
               <li><a href="/versions/{{ site.version }}/build-event-protocol.html">Build Event Protocol</a></li>
               <li><a href="/versions/{{ site.version }}/platforms.html">Platforms</a></li>
+              <li><a href="/versions/{{ site.version }}/toolchains.html">Toolchains</a></li>
             </ul>
             {% include be-nav.html %}
             <h3>Extensions</h3>
diff --git a/site/docs/platforms.md b/site/docs/platforms.md
index ad630a4..bfd7fde 100644
--- a/site/docs/platforms.md
+++ b/site/docs/platforms.md
@@ -5,142 +5,62 @@
 
 # Platforms
 
-Bazel can build and test code on a variety of platforms, in a few different
-configurations. Some of configurations are:
+- [Overview](#overview)
+- [Defining a platform](#defining-a-platform)
+- [Built-in constraints and platforms](#built-in-constraints-and-platforms)
+- [Specifying a platform for a build](#specifying-a-platform-for-a-build)
 
-+  Single-platform builds - The default, where Bazel executes on the same
-    device as the compiler, and the executable will run on the same device.
-+  Cross-compile builds - In this case, Bazel and the compiler run on one
-    device, but the final executable is intended for another device. This
-    includes cases like building Android or iOS apps, among others.
-+  Multi-platform builds - A multi-platform build is where Bazel runs on one
-    device, but the compilers and other tools run on other devices.
+## Overview
 
-## Contents
+Bazel can build and test code on a variety of operating systems and hardware
+using many different build tools, such as linkers and compilers. These
+combinations of software and hardware are what Bazel considers *platforms*.
+One major use for specifying a platform for a build is automatic
+[toolchain](toolchains.html) selection.
 
-* [Types of Platforms](#types-of-platforms)
-* [Platforms](#platforms-1)
-  * [Overview](#overview)
-  * [Defining Platforms](#defining-platforms)
-    * [Constraint Settings and Values](#constraint-settings-and-values)
-    * [Platforms](#platforms-2)
-  * [Using Platforms](#using-platforms)
-    * [Flags](#flags)
-    * [Predefined Platforms](#predefined-platforms)
-* [Toolchains](#toolchains)
-  * [Overview](#overview-1)
-  * [Toolchain type](#toolchain-type)
-  * [Toolchain rules](#toolchain-rules)
-    * [Defining a toolchain rule in Skylark]()
-  * [Toolchain definition](#toolchain-definition)
-  * [Registering a toolchain](#registering-a-toolchain)
-  * [Toolchain Resolution](#toolchain-resolution)
-  * [Debugging toolchains](#debugging-toolchains)
-  * [Using toolchains in Skylark rules](#using-toolchains-in-skylark-rules)
-    * [Toolchains attribute on rule()](#toolchains-attribute-on-rule)
-    * [ctx.toolchains](#ctx-toolchains)
-* [Select and config\_setting](#select-and-config_setting)
+Bazel recognizes the following types of platforms:
 
+* **Host** - platforms on which Bazel runs.
+* **Execution** - platforms on which build tools execute build actions.
+* **Target** - platforms for which Bazel builds the output.
 
-## Types of Platforms
+Bazel supports the following build scenarios regarding platforms:
 
-To describe these different scenarios, Bazel has introduced the concept of
-"platforms". A platform is a device that can run a program, whether that program
-is Bazel itself, a compiler or other tool, or the final built output.
+*  **Single-platform builds** (default) - host, execution, and target platforms
+   are the same. For example, building a Linux executable on Ubuntu running on
+   an Intel x64 CPU.
 
-The terminology for these types of platforms are:
+*  **Cross-compilation builds** - host and execution platforms are the same, but
+   the target platform is different. For example, building an iOS app on macOS
+   running on a MacBook Pro.
 
-* Host Platform - Where Bazel itself is running
-* Execution Platform - Where build actions run
-* Target Platform - Where the final build outputs will run
+*  **Multi-platform builds** - host, execution, and target platforms are all
+   different.
 
-Typically, the host and execution platform are the same (except in the case of
-remote execution), since build actions are executed locally by Bazel. If you are
-building an executable that will run on the same computer where you are using
-Bazel, then the target platform is the same as the host platform. When you are
-cross-compiling (say, building an Android application), then the target platform
-is different from the host platform.
+## Defining a platform
 
-## Platforms
+A *Bazel platform* is a named collection of constraints that define a supported
+software and/or hardware configuration through name-value pairs. For example, a
+constraint can define the CPU architecture, GPU presence, or the specific
+version of a build tool, such as a linker or compiler.
 
-### Overview
+You define a platform in a `BUILD` file using the following Bazel rules:
 
-Conceptually in Bazel, a platform is a named collection of constraints.
-Constraints are just names and values used to define the features of a platform.
-Some examples of constraints are the CPU architecture, the operating system, the
-presence of a GPU, or the specific version of a compiler or other tool.
+* [`constraint_setting`](be/platform.html#constraint_setting) - defines a
+  constraint.
 
-### Defining Platforms
+* [`constraint_value`](be/platform.html#constraint_value) - defines an allowed
+  value for a constraint.
 
-Platforms are defined in Bazel BUILD files, using three new rules:
+* [`platform`](be/platform.html#platform) - defines a platform by specifying
+  a set of constraints and their values.
 
-* [constraint_setting](be/platform.html#constraint_setting) - Defines a new constraint
-* [constraint_value](be/platform.html#constraint_value) - Adds a possible value to an existing constraint
-* [platform](be/platform.html#platform) - Defines a set of constraints and names them as a platform
+The following example defines the `glibc_version` constraint and its two allowed
+values. It then defines a platform that uses the `glibc_version` constraint
+along with Bazel's [built-in constraints](#built-in-constraints-and-platforms)
+for operating systems and CPU architecture:
 
-#### Constraint Settings and Values
-
-Bazel automatically defines some constraints and values for you:
-
-TODO(katre): fix table formatting
-<table>
-<thead>
-<tr>
-<th>constraint\_setting</th>
-<th>constraint\_value</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td>@bazel\_tools//platforms:cpu</td>
-<td>@bazel\_tools//platforms:x86\_32</td>
-</tr>
-<tr>
-<td></td>
-<td>@bazel\_tools//platforms:x86\_64</td>
-</tr>
-<tr>
-<td></td>
-<td>@bazel\_tools//platforms:ppc</td>
-</tr>
-<tr>
-<td></td>
-<td>@bazel\_tools//platforms:arm</td>
-</tr>
-<tr>
-<td></td>
-<td>@bazel\_tools//platforms:s390x</td>
-</tr>
-<tr>
-<td>@bazel\_tools//platforms:os</td>
-<td>@bazel\_tools//platforms:osx</td>
-</tr>
-<tr>
-<td></td>
-<td>@bazel\_tools//platforms:freebsd</td>
-</tr>
-<tr>
-<td></td>
-<td>@bazel\_tools//platforms:linux</td>
-</tr>
-<tr>
-<td></td>
-<td>@bazel\_tools//platforms:windows</td>
-</tr>
-</tbody>
-</table>
-
-Here are some examples of defining additional constraints:
-
-```bash
-constraint_value(
-    name = 'aarm64',
-    constraint_setting = '@bazel_tools//platforms:cpu')
-
-constraint_value(
-    name = 'openbsd',
-    constraint_setting = '@bazel_tools//platforms:os')
-
+```python
 constraint_setting(name = 'glibc_version')
 
 constraint_value(
@@ -150,16 +70,7 @@
 constraint_value(
     name = 'glibc_2_26',
     constraint_setting = ':glibc_version')
-```
 
-Constraint values can be defined in any package, although constraint settings
-and values are subject to the usual rules on visibility.
-
-#### Platforms
-
-Here are some platforms defined using these constraints:
-
-```bash
 platform(
     name = 'linux_x86',
     constraint_values = [
@@ -167,251 +78,91 @@
       '@bazel_tools//platforms:x86_64',
       ':glibc_2_25',
     ])
-
-platform(
-    name = 'openbsd_arm',
-    constraint_values = [
-      ':openbsd',
-      '@bazel_tools//platforms:arm',
-    ])
 ```
 
-You can mix constraint values from multiple packages in a single platform. Be
-careful, however, because you cannot use two constraint values that share a
-constraint setting! This will be reported as an error.
+Keep the following in mind when defining constraints and platforms that use
+them:
 
-### Using Platforms
+*  You can define constraints in any Bazel package within the project.
 
-#### Flags
+*  Constraints follow the visibility settings of the package that contains them.
 
-Being able to define platforms is nice, but what can you do with them?
-Currently, the main use of platforms and constraints is to have Bazel
-automatically select the right toolchain for your build.
+*  You can use constraint values from multiple packages in the same platform
+   definition. However, using constraint values that share a constraint setting
+   will result in an error.
 
-Note: not all sets of rules support toolchains, notably the native C++ and Java
-rules do not work with this yet.
+## Built-in constraints and platforms
 
-The host and target platform can be set via command-line flags:
+Bazel ships with constraint definitions for the most popular CPU architectures
+and operating systems:
 
-TODO(katre): fix table formatting
 <table>
-<thead>
-<tr>
-<th>--experimental\_host\_platform</th>
-<th>Defaults to @bazel\_tools//platforms:host\_platform</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td>--experimental\_platforms</td>
-<td>Defaults to @bazel\_tools//platforms:target\_platform</td>
-</tr>
+  <thead>
+    <tr>
+      <th>constraint_setting</th>
+      <th>constraint_value</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+      <td>@bazel_tools//platforms:cpu</td>
+      <td>@bazel_tools//platforms:x86_32</td>
+    </tr>
+    <tr>
+      <td></td>
+      <td>@bazel_tools//platforms:x86_64</td>
+    </tr>
+    <tr>
+      <td></td>
+      <td>@bazel_tools//platforms:ppc</td>
+    </tr>
+    <tr>
+      <td></td>
+      <td>@bazel_tools//platforms:arm</td>
+    </tr>
+    <tr>
+      <td></td>
+    <td>@bazel_tools//platforms:s390x</td>
+    </tr>
+    <tr>
+      <td>@bazel_tools//platforms:os</td>
+      <td>@bazel_tools//platforms:osx</td>
+    </tr>
+    <tr>
+      <td></td>
+      <td>@bazel_tools//platforms:freebsd</td>
+    </tr>
+    <tr>
+     <td></td>
+     <td>@bazel_tools//platforms:linux</td>
+    </tr>
+    <tr>
+      <td></td>
+      <td>@bazel_tools//platforms:windows</td>
+    </tr>
 </tbody>
 </table>
 
-#### Predefined Platforms
+Bazel also ships with the following platform definitions:
 
-There is two special predefined platforms: @bazel\_tools//platforms:host\_platform
-and @bazel\_tools//platforms:target\_platform. These platforms automatically
-detect the current host and target CPU and OS (based on the "--host\_cpu" and
-"--cpu" flags) and sets those two constraint values. All other platforms that
-you want to use will need to be added to your BUILD files.
+*  `@bazel_tools//platforms:host_platform` - automatically detects the CPU
+   architecture and operating system for the host platform.
 
-## Toolchains
+*  `@bazel_tools//platforms:target_platform` - automatically detects the CPU
+   architecture and operating system for the target platform.
 
-### Overview
+In these definitions, the CPU architecture constraint values are pulled from the
+`--host_cpu` and `--cpu` flags.
 
-A toolchain is a configuration [provider](skylark/rules.html#providers) that allows
-you to tell a rule what compiler, compiler flags, etc to use. The set of
-available configuration parameters is up to the rule author.
+## Specifying a platform for a build
 
-There are three important definitions for every type of toolchain:
+To select a specific host and target platform for a build, use the following
+command-line flags:
 
-1. The rule-specific toolchain rule, such as go\_toolchain, that defines
-    the specific values of the configuration to be used by the rules.
-1. The toolchain definition, via the toolchain() rule, which tells Bazel
-    which constraints the toolchain meets.
-1. The toolchain registration, via the register\_toolchains() WORKSPACE
-    function, which tells Bazel that the toolchain is available.
+*  `--experimental_host_platform` - defaults to `@bazel_tools//platforms:host_platform`
 
-During a build, Bazel will use the current execution and target platforms to
-find an appropriate toolchain instance for each rule, based on the toolchain's
-declared constraints. This process is called Toolchain Resolution.
+*  `--experimental_platforms` - defaults to `@bazel_tools//platforms:target_platform`
 
-### Toolchain type
-
-Every set of rules that uses a toolchain needs to define a unique label, the
-toolchain type, that is used by the rules when requesting a valid toolchain. The
-toolchain type label is given when the toolchain is defined in the toolchain()
-rule, so that Bazel can use it as an input to Toolchain Resolution.
-
-### Toolchain rules
-
-To work with toolchains, a rule author needs to add a rule-specific toolchain
-rule, which defines the values of all configuration parameters the rule uses
-which change for different execution and target platforms. This rule should
-return a [ToolchainInfo provider](skylark/lib/ToolchainInfo.html).
-
-Instances of the toolchain rule will be lazily instantiated by Bazel only when
-needed. Because of this, a toolchain rule's dependencies can be as complex as
-needed, and even reply on remote repositories, and not affect builds where they
-are not used.
-
-#### Defining a toolchain rule in Skylark
-
-To define a new toolchain in Skylark, first you need to determine what
-information your rules need. Let's consider the case of a new programming
-language: the rules will need the path to the compiler, the path to the system
-libraries, and a flag that controls the generated binary's CPU architecture.
-
-Toolchain rules are ordinary Skylark rules that create and return providers.
-This example toolchain rule would look like this in Skylark:
-
-```bash
-def _my_toolchain_impl(ctx):
-  toolchain = platform.ToolchainInfo(
-    compiler = ctx.attr.compiler,
-    system_lib = ctx.attr.system_lib,
-    arch_flag = ctx.attr.arch_flag,
-  )
-  return [toolchain]
-
-my_toolchain = rule(
-    _my_toolchain_impl,
-    attrs = {
-        'compiler': attr.string(),
-        'system_lib': attr.string(),
-        'arch_flags': attr.string_list(),
-    })
-```
-
-And a sample usage would look like:
-
-```bash
-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
-  ]
-)
-```
-
-### Toolchain definition
-
-To accomplish the lazy loading of toolchains, a separate rule called toolchain()
-is used. This rule tells Bazel the toolchain type, the execution and target
-constraints, and the label of the actual rule-specific toolchain to be used.
-
-Example toolchain definitions:
-
-```bash
-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',
-)
-
-toolchain(name = 'darwin_toolchain',
-    toolchain_type = '//path/to:my_toolchain_type',
-    exec_compatible_with = [
-        '@bazel_tools//platforms:darwin',
-        '@bazel_tools//platforms:x86_64'],
-    target_compatible_with = [
-        '@bazel_tools//platforms:darwin',
-        '@bazel_tools//platforms:x86_64'],
-    toolchain = ':darwin_toolchain_impl',
-)
-```
-
-### Registering a toolchain
-
-Finally, Bazel needs to know about the toolchain definition, in order to use it.
-Registering a toolchain can be done in either the WORKSPACE, or via the
-"--experimental\_extra\_toolchains" flag.
-
-Example in the WORKSPACE:
-
-```bash
-register_toolchains(
-  '//path/to:linux_toolchain',
-  '//path/to:darwin_toolchain',
-)
-```
-
-### Toolchain Resolution
-
-When a target requires a toolchain, Bazel checks the list of registered
-toolchains to find the first one that is valid, and creates a dependency from
-the target to the specific toolchain that was selected. The process looks like
-this:
-
-1. Check every registered toolchain in order. First consider the
-    toolchains from the "--experimental\_extra\_toolchains" flag, and then the
-    "registered\_toolchains" calls in the WORKSPACE.
-1. Does the toolchain match the requested toolchain type? If no, skip this one.
-1. Do the execution and target constraints on the toolchain match the
-    current execution and target platforms? If not, skip this one.
-1. We have a matching toolchain, use it.
-
-Please note that this will always choose the first toolchain that is valid, so
-toolchains should be ordered by preference if it is possible that multiple could
-match.
-
-### Debugging toolchains
-
-When adding toolchain support to existing rules, it can be difficult to
-determine where errors are found and what causes problems with toolchain
-resolution. To help aid development, the "--toolchain\_resolution\_debug" flag has
-been added. This flag causes the Toolchain Resolution process to be very verbose
-about what toolchains are being considered, and why they are being skipped.
-
-### Using toolchains in Skylark rules
-
-#### Toolchains attribute on rule()
-
-In order for rules to use the toolchain, the rule author needs to add the
-toolchain type to the rule definition:
-
-```bash
-my_library = rule(
-    ...
-    toolchains = ['//path/to:my_toolchain_type']
-    ...)
-```
-
-#### ctx.toolchains
-
-When the rule is used, Bazel will check the execution and target platforms, and
-choose an appropriate toolchain that matches (or fail with an error message
-explaining the lack of toolchains). The rule implementation can then access the
-toolchain as:
-
-```bash
-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_flag)
-  ...
-```
-
-## Select and config_setting
-
-Platforms can also be used with the config\_setting rule to define configurable
+Platforms can also be used with the `config_setting` rule to define configurable
 attributes. See [config_setting](be/general.html#config_setting) for more
 details.
-
diff --git a/site/docs/toolchains.md b/site/docs/toolchains.md
new file mode 100644
index 0000000..7a10701
--- /dev/null
+++ b/site/docs/toolchains.md
@@ -0,0 +1,184 @@
+---
+layout: documentation
+title: Toolchains
+---
+
+# Toolchains
+
+- [Overview](#overview)
+- [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)
+- [Adding toolchain support to Skylark rules](#adding-toolchain-support-to-skylark-rules)
+- [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.
+
+**Note:** Some Bazel rules do not yet support toolchain resolution.
+
+When a target requests a toolchain, Bazel checks the list of registered
+toolchains and creates a dependency from the target to the first matching
+toolchain it finds. To find a matching toolchain, Bazel does the following:
+
+1.  Looks through the registered toolchains, first from the `--experimental_extra_toolchains`
+    flag, then from the `registered_toolchains` calls in the project's
+    `WORKSPACE` file.
+
+2.  For each registered toolchain, Bazel performs the following checks:
+
+    a. Does the toolchain match the requested toolchain type? If not, skip it.
+
+    b. Do the toolchain's execution and target constraints match the constraints
+       stated in the project's execution and target platforms? If yes, the
+       toolchain is a match.
+
+Because Bazel always selects the first matching toolchain, order the toolchains
+by preference if you expect the possibility of multiple matches.
+
+## 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/ToolchainInfo.html).
+   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 Skylark 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.ToolchainInfo(
+    compiler = ctx.attr.compiler,
+    system_lib = ctx.attr.system_lib,
+    arch_flag = ctx.attr.arch_flag,
+  )
+  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(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 `--experimental_extra_toolchains` flag.
+
+Below is an example toolchain registration in a `WORKSPACE` file:
+
+```python
+register_toolchains(
+  '//path/to:linux_toolchain',
+  '//path/to:darwin_toolchain',
+)
+```
+
+## Adding toolchain support to Skylark rules
+
+To use a toolchain in a Skylark 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_flag)
+  ...
+```
+
+## 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.