| --- | |
| title: 'Toolchains' | |
| --- | |
| This page describes the toolchain framework, which is a way for rule authors to | |
| decouple their rule logic from platform-based selection of tools. It is | |
| recommended to read the [rules](/versions/9.3.0/extending/rules) and [platforms](/versions/9.3.0/extending/platforms) | |
| pages before continuing. This page covers why toolchains are needed, how to | |
| define and use them, and how Bazel selects an appropriate toolchain based on | |
| platform constraints. | |
| ## Motivation {#motivation} | |
| Let's first look at the problem toolchains are designed to solve. Suppose you | |
| are writing rules to support the "bar" programming language. Your `bar_binary` | |
| rule would compile `*.bar` files using the `barc` compiler, a tool that itself | |
| is built as another target in your workspace. Since users who write `bar_binary` | |
| targets shouldn't have to specify a dependency on the compiler, you make it an | |
| implicit dependency by adding it to the rule definition as a private attribute. | |
| ```python | |
| bar_binary = rule( | |
| implementation = _bar_binary_impl, | |
| attrs = { | |
| "srcs": attr.label_list(allow_files = True), | |
| ... | |
| "_compiler": attr.label( | |
| default = "//bar_tools:barc_linux", # the compiler running on linux | |
| providers = [BarcInfo], | |
| ), | |
| }, | |
| ) | |
| ``` | |
| `//bar_tools:barc_linux` is now a dependency of every `bar_binary` target, so | |
| it'll be built before any `bar_binary` target. It can be accessed by the rule's | |
| implementation function just like any other attribute: | |
| ```python | |
| BarcInfo = provider( | |
| doc = "Information about how to invoke the barc compiler.", | |
| # In the real world, compiler_path and system_lib might hold File objects, | |
| # but for simplicity they are strings for this example. arch_flags is a list | |
| # of strings. | |
| fields = ["compiler_path", "system_lib", "arch_flags"], | |
| ) | |
| def _bar_binary_impl(ctx): | |
| ... | |
| info = ctx.attr._compiler[BarcInfo] | |
| command = "%s -l %s %s" % ( | |
| info.compiler_path, | |
| info.system_lib, | |
| " ".join(info.arch_flags), | |
| ) | |
| ... | |
| ``` | |
| The issue here is that the compiler's label is hardcoded into `bar_binary`, yet | |
| different targets may need different compilers depending on what platform they | |
| are being built for and what platform they are being built on -- called the | |
| *target platform* and *execution platform*, respectively. Furthermore, the rule | |
| author does not necessarily even know all the available tools and platforms, so | |
| it is not feasible to hardcode them in the rule's definition. | |
| A less-than-ideal solution would be to shift the burden onto users, by making | |
| the `_compiler` attribute non-private. Then individual targets could be | |
| hardcoded to build for one platform or another. | |
| ```python | |
| bar_binary( | |
| name = "myprog_on_linux", | |
| srcs = ["mysrc.bar"], | |
| compiler = "//bar_tools:barc_linux", | |
| ) | |
| bar_binary( | |
| name = "myprog_on_windows", | |
| srcs = ["mysrc.bar"], | |
| compiler = "//bar_tools:barc_windows", | |
| ) | |
| ``` | |
| You can improve on this solution by using `select` to choose the `compiler` | |
| [based on the platform](/versions/9.3.0/docs/configurable-attributes): | |
| ```python | |
| config_setting( | |
| name = "on_linux", | |
| constraint_values = [ | |
| "@platforms//os:linux", | |
| ], | |
| ) | |
| config_setting( | |
| name = "on_windows", | |
| constraint_values = [ | |
| "@platforms//os:windows", | |
| ], | |
| ) | |
| bar_binary( | |
| name = "myprog", | |
| srcs = ["mysrc.bar"], | |
| compiler = select({ | |
| ":on_linux": "//bar_tools:barc_linux", | |
| ":on_windows": "//bar_tools:barc_windows", | |
| }), | |
| ) | |
| ``` | |
| But this is tedious and a bit much to ask of every single `bar_binary` user. | |
| If this style is not used consistently throughout the workspace, it leads to | |
| builds that work fine on a single platform but fail when extended to | |
| multi-platform scenarios. It also does not address the problem of adding support | |
| for new platforms and compilers without modifying existing rules or targets. | |
| The toolchain framework solves this problem by adding an extra level of | |
| indirection. Essentially, you declare that your rule has an abstract dependency | |
| on *some* member of a family of targets (a toolchain type), and Bazel | |
| automatically resolves this to a particular target (a toolchain) based on the | |
| applicable platform constraints. Neither the rule author nor the target author | |
| need know the complete set of available platforms and toolchains. | |
| ## Writing rules that use toolchains {#writing-rules-toolchains} | |
| Under the toolchain framework, instead of having rules depend directly on tools, | |
| they instead depend on *toolchain types*. A toolchain type is a simple target | |
| that represents a class of tools that serve the same role for different | |
| platforms. For instance, you can declare a type that represents the bar | |
| compiler: | |
| ```python | |
| # By convention, toolchain_type targets are named "toolchain_type" and | |
| # distinguished by their package path. So the full path for this would be | |
| # //bar_tools:toolchain_type. | |
| toolchain_type(name = "toolchain_type") | |
| ``` | |
| The rule definition in the previous section is modified so that instead of | |
| taking in the compiler as an attribute, it declares that it consumes a | |
| `//bar_tools:toolchain_type` toolchain. | |
| ```python | |
| bar_binary = rule( | |
| implementation = _bar_binary_impl, | |
| attrs = { | |
| "srcs": attr.label_list(allow_files = True), | |
| ... | |
| # No `_compiler` attribute anymore. | |
| }, | |
| toolchains = ["//bar_tools:toolchain_type"], | |
| ) | |
| ``` | |
| The implementation function now accesses this dependency under `ctx.toolchains` | |
| instead of `ctx.attr`, using the toolchain type as the key. | |
| ```python | |
| def _bar_binary_impl(ctx): | |
| ... | |
| info = ctx.toolchains["//bar_tools:toolchain_type"].barcinfo | |
| # The rest is unchanged. | |
| command = "%s -l %s %s" % ( | |
| info.compiler_path, | |
| info.system_lib, | |
| " ".join(info.arch_flags), | |
| ) | |
| ... | |
| ``` | |
| `ctx.toolchains["//bar_tools:toolchain_type"]` returns the | |
| [`ToolchainInfo` provider](/versions/9.3.0/rules/lib/toplevel/platform_common#ToolchainInfo) | |
| of whatever target Bazel resolved the toolchain dependency to. The fields of the | |
| `ToolchainInfo` object are set by the underlying tool's rule; in the next | |
| section, this rule is defined such that there is a `barcinfo` field that wraps | |
| a `BarcInfo` object. | |
| Bazel's procedure for resolving toolchains to targets is described | |
| [below](#toolchain-resolution). Only the resolved toolchain target is actually | |
| made a dependency of the `bar_binary` target, not the whole space of candidate | |
| toolchains. | |
| ### Mandatory and Optional Toolchains {#optional-toolchains} | |
| By default, when a rule expresses a toolchain type dependency using a bare label | |
| (as shown above), the toolchain type is considered to be **mandatory**. If Bazel | |
| is unable to find a matching toolchain (see | |
| [Toolchain resolution](#toolchain-resolution) below) for a mandatory toolchain | |
| type, this is an error and analysis halts. | |
| It is possible instead to declare an **optional** toolchain type dependency, as | |
| follows: | |
| ```python | |
| bar_binary = rule( | |
| ... | |
| toolchains = [ | |
| config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = False), | |
| ], | |
| ) | |
| ``` | |
| When an optional toolchain type cannot be resolved, analysis continues, and the | |
| result of `ctx.toolchains["//bar_tools:toolchain_type"]` is `None`. | |
| The [`config_common.toolchain_type`](/versions/9.3.0/rules/lib/toplevel/config_common#toolchain_type) | |
| function defaults to mandatory. | |
| The following forms can be used: | |
| - Mandatory toolchain types: | |
| - `toolchains = ["//bar_tools:toolchain_type"]` | |
| - `toolchains = [config_common.toolchain_type("//bar_tools:toolchain_type")]` | |
| - `toolchains = [config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = True)]` | |
| - Optional toolchain types: | |
| - `toolchains = [config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = False)]` | |
| ```python | |
| bar_binary = rule( | |
| ... | |
| toolchains = [ | |
| "//foo_tools:toolchain_type", | |
| config_common.toolchain_type("//bar_tools:toolchain_type", mandatory = False), | |
| ], | |
| ) | |
| ``` | |
| You can mix and match forms in the same rule, also. However, if the same | |
| toolchain type is listed multiple times, it will take the most strict version, | |
| where mandatory is more strict than optional. | |
| ### Writing aspects that use toolchains {#writing-aspects-toolchains} | |
| Aspects have access to the same toolchain API as rules: you can define required | |
| toolchain types, access toolchains via the context, and use them to generate new | |
| actions using the toolchain. | |
| ```py | |
| bar_aspect = aspect( | |
| implementation = _bar_aspect_impl, | |
| attrs = {}, | |
| toolchains = ['//bar_tools:toolchain_type'], | |
| ) | |
| def _bar_aspect_impl(target, ctx): | |
| toolchain = ctx.toolchains['//bar_tools:toolchain_type'] | |
| # Use the toolchain provider like in a rule. | |
| return [] | |
| ``` | |
| ## Defining toolchains {#toolchain-definitions} | |
| To define some toolchains for a given toolchain type, you need three things: | |
| 1. A language-specific rule representing the kind of tool or tool suite. By | |
| convention this rule's name is suffixed with "\_toolchain". | |
| 1. **Note:** The `\_toolchain` rule cannot create any build actions. | |
| Rather, it collects artifacts from other rules and forwards them to the | |
| rule that uses the toolchain. That rule is responsible for creating all | |
| build actions. | |
| 2. Several targets of this rule type, representing versions of the tool or tool | |
| suite for different platforms. | |
| 3. For each such target, an associated target of the generic | |
| [`toolchain`](/versions/9.3.0/reference/be/platforms-and-toolchains#toolchain) | |
| rule, to provide metadata used by the toolchain framework. This `toolchain` | |
| target also refers to the `toolchain_type` associated with this toolchain. | |
| This means that a given `_toolchain` rule could be associated with any | |
| `toolchain_type`, and that only in a `toolchain` instance that uses | |
| this `_toolchain` rule that the rule is associated with a `toolchain_type`. | |
| For our running example, here's a definition for a `bar_toolchain` rule. Our | |
| example has only a compiler, but other tools such as a linker could also be | |
| grouped underneath it. | |
| ```python | |
| def _bar_toolchain_impl(ctx): | |
| toolchain_info = platform_common.ToolchainInfo( | |
| barcinfo = BarcInfo( | |
| compiler_path = ctx.attr.compiler_path, | |
| system_lib = ctx.attr.system_lib, | |
| arch_flags = ctx.attr.arch_flags, | |
| ), | |
| ) | |
| return [toolchain_info] | |
| bar_toolchain = rule( | |
| implementation = _bar_toolchain_impl, | |
| attrs = { | |
| "compiler_path": attr.string(), | |
| "system_lib": attr.string(), | |
| "arch_flags": attr.string_list(), | |
| }, | |
| ) | |
| ``` | |
| The rule must return a `ToolchainInfo` provider, which becomes the object that | |
| the consuming rule retrieves using `ctx.toolchains` and the label of the | |
| toolchain type. `ToolchainInfo`, like `struct`, can hold arbitrary field-value | |
| pairs. The specification of exactly what fields are added to the `ToolchainInfo` | |
| should be clearly documented at the toolchain type. In this example, the values | |
| return wrapped in a `BarcInfo` object to reuse the schema defined above; this | |
| style may be useful for validation and code reuse. | |
| Now you can define targets for specific `barc` compilers. | |
| ```python | |
| bar_toolchain( | |
| name = "barc_linux", | |
| arch_flags = [ | |
| "--arch=Linux", | |
| "--debug_everything", | |
| ], | |
| compiler_path = "/path/to/barc/on/linux", | |
| system_lib = "/usr/lib/libbarc.so", | |
| ) | |
| bar_toolchain( | |
| name = "barc_windows", | |
| arch_flags = [ | |
| "--arch=Windows", | |
| # Different flags, no debug support on windows. | |
| ], | |
| compiler_path = "C:\\path\\on\\windows\\barc.exe", | |
| system_lib = "C:\\path\\on\\windows\\barclib.dll", | |
| ) | |
| ``` | |
| Finally, you create `toolchain` definitions for the two `bar_toolchain` targets. | |
| These definitions link the language-specific targets to the toolchain type and | |
| provide the constraint information that tells Bazel when the toolchain is | |
| appropriate for a given platform. | |
| ```python | |
| toolchain( | |
| name = "barc_linux_toolchain", | |
| exec_compatible_with = [ | |
| "@platforms//os:linux", | |
| "@platforms//cpu:x86_64", | |
| ], | |
| target_compatible_with = [ | |
| "@platforms//os:linux", | |
| "@platforms//cpu:x86_64", | |
| ], | |
| toolchain = ":barc_linux", | |
| toolchain_type = ":toolchain_type", | |
| ) | |
| toolchain( | |
| name = "barc_windows_toolchain", | |
| exec_compatible_with = [ | |
| "@platforms//os:windows", | |
| "@platforms//cpu:x86_64", | |
| ], | |
| target_compatible_with = [ | |
| "@platforms//os:windows", | |
| "@platforms//cpu:x86_64", | |
| ], | |
| toolchain = ":barc_windows", | |
| toolchain_type = ":toolchain_type", | |
| ) | |
| ``` | |
| The use of relative path syntax above suggests these definitions are all in the | |
| same package, but there's no reason the toolchain type, language-specific | |
| toolchain targets, and `toolchain` definition targets can't all be in separate | |
| packages. | |
| See the [`go_toolchain`](https://github.com/bazelbuild/rules_go/blob/master/go/private/go_toolchain.bzl) | |
| for a real-world example. | |
| ### Toolchains and configurations | |
| An important question for rule authors is, when a `bar_toolchain` target is | |
| analyzed, what [configuration](/versions/9.3.0/reference/glossary#configuration) does it see, and what transitions | |
| should be used for dependencies? The example above uses string attributes, but | |
| what would happen for a more complicated toolchain that depends on other targets | |
| in the Bazel repository? | |
| Let's see a more complex version of `bar_toolchain`: | |
| ```python | |
| def _bar_toolchain_impl(ctx): | |
| # The implementation is mostly the same as above, so skipping. | |
| pass | |
| bar_toolchain = rule( | |
| implementation = _bar_toolchain_impl, | |
| attrs = { | |
| "compiler": attr.label( | |
| executable = True, | |
| mandatory = True, | |
| cfg = "exec", | |
| ), | |
| "system_lib": attr.label( | |
| mandatory = True, | |
| cfg = "target", | |
| ), | |
| "arch_flags": attr.string_list(), | |
| }, | |
| ) | |
| ``` | |
| The use of [`attr.label`](/versions/9.3.0/rules/lib/toplevel/attr#label) is the same as for a standard rule, | |
| but the meaning of the `cfg` parameter is slightly different. | |
| When a target (the "parent") depends on a toolchain via toolchain resolution, | |
| Bazel applies a special configuration transition called the "toolchain transition". | |
| In this transition Bazel keeps the overall configuration identical, but forces | |
| the toolchain to use the same execution platform as the parent. Without this, | |
| toolchain resolution could pick a different execution platform for the | |
| toolchain, and the tools it provides might not be runnable for the parent's | |
| actions. | |
| This alignment of execution platforms guarantees that any dependencies of the | |
| toolchain declared with `cfg = "exec"` are built so they can run where the | |
| parent's actions run. | |
| Dependencies declared with `cfg = "target"` (or which omit `cfg`, since | |
| "target" is the default) are built for the parent's target platform. This lets | |
| the toolchain contribute both runtime libraries and build-time tools. | |
| In practice: | |
| - `cfg = "exec"`: build artifacts intended to run during the build (e.g. | |
| the `compiler` tool) and therefore for the execution platform. | |
| - `cfg = "target"`: build artifacts intended to be linked into or shipped with | |
| the final output (e.g. the `system_lib`) and therefore for the target | |
| platform. | |
| The system libraries must be built for the same target platform as the final | |
| artifact, while the compiler must be runnable on the execution platform. | |
| ### Selecting `exec` dependencies | |
| For toolchain config rules, adding a `select()` to an attribute with `cfg = "exec"` | |
| does **not** make the `select()` use the exec configuration. | |
| It will still be resolved under the **target** configuration. | |
| Assuming the target platform is not matching any of these constraints, the select for the compiler | |
| will fail to analyze. | |
| ```python | |
| bar_toolchain( | |
| name = "barc_omni", | |
| compiler = select({ | |
| "@platforms//os:linux": Label(":linux_compiler"), | |
| "@platforms//os:windows": Label(":windows_compiler"), | |
| "//some/exec:platform": Label(":special_compiler"), | |
| }, | |
| no_match_error = "No compiler for this execution platform", | |
| }), | |
| # <...> | |
| ) | |
| ``` | |
| A known workaround for this is to defer the evaluation behind another target, | |
| e.g. [`alias()`](/versions/9.3.0/reference/be/general#alias). | |
| This analyzes the `select` inside the alias under the exec configuration. | |
| ```python | |
| alias( | |
| name = "host_specific_compiler", | |
| actual = select({ | |
| "@platforms//os:linux": Label(":linux_compiler"), | |
| "@platforms//os:windows": Label(":windows_compiler"), | |
| "//some/exec:platform": Label(":special_compiler"), | |
| }, | |
| no_match_error = "No compiler for this execution platform", | |
| ), | |
| ) | |
| bar_toolchain( | |
| name = "barc_omni", | |
| compiler = ":host_specific_compiler", | |
| # <...> | |
| ) | |
| ``` | |
| ## Registering and building with toolchains {#registering-building-toolchains} | |
| At this point all the building blocks are assembled, and you just need to make | |
| the toolchains available to Bazel's resolution procedure. This is done by | |
| registering the toolchain, either in a `MODULE.bazel` file using | |
| `register_toolchains()`, or by passing the toolchains' labels on the command | |
| line using the `--extra_toolchains` flag. | |
| ```python | |
| register_toolchains( | |
| "//bar_tools:barc_linux_toolchain", | |
| "//bar_tools:barc_windows_toolchain", | |
| # Target patterns are also permitted, so you could have also written: | |
| # "//bar_tools:all", | |
| # or even | |
| # "//bar_tools/...", | |
| ) | |
| ``` | |
| When using target patterns to register toolchains, the order in which the | |
| individual toolchains are registered is determined by the following rules: | |
| * The toolchains defined in a subpackage of a package are registered before the | |
| toolchains defined in the package itself. | |
| * Within a package, toolchains are registered in the lexicographical order of | |
| their names. | |
| Now when you build a target that depends on a toolchain type, an appropriate | |
| toolchain will be selected based on the target and execution platforms. | |
| ```python | |
| # my_pkg/BUILD | |
| platform( | |
| name = "my_target_platform", | |
| constraint_values = [ | |
| "@platforms//os:linux", | |
| ], | |
| ) | |
| bar_binary( | |
| name = "my_bar_binary", | |
| ... | |
| ) | |
| ``` | |
| ```sh | |
| bazel build //my_pkg:my_bar_binary --platforms=//my_pkg:my_target_platform | |
| ``` | |
| Bazel will see that `//my_pkg:my_bar_binary` is being built with a platform that | |
| has `@platforms//os:linux` and therefore resolve the | |
| `//bar_tools:toolchain_type` reference to `//bar_tools:barc_linux_toolchain`. | |
| This will end up building `//bar_tools:barc_linux` but not | |
| `//bar_tools:barc_windows`. | |
| ## Toolchain resolution {#toolchain-resolution} | |
| Note: [Some Bazel rules](/versions/9.3.0/concepts/platforms#status) do not yet support | |
| toolchain resolution. | |
| For each target that uses toolchains, Bazel's toolchain resolution procedure | |
| determines the target's concrete toolchain dependencies. The procedure takes as | |
| input a set of required toolchain types, the target platform, the list of | |
| available execution platforms, and the list of available toolchains. Its outputs | |
| are a selected toolchain for each toolchain type as well as a selected execution | |
| platform for the current target. | |
| The available execution platforms and toolchains are gathered from the | |
| external dependency graph via | |
| [`register_execution_platforms`](/versions/9.3.0/rules/lib/globals/module#register_execution_platforms) | |
| and | |
| [`register_toolchains`](/versions/9.3.0/rules/lib/globals/module#register_toolchains) calls in | |
| `MODULE.bazel` files. | |
| Additional execution platforms and toolchains may also be specified on the | |
| command line via | |
| [`--extra_execution_platforms`](/versions/9.3.0/reference/command-line-reference#flag--extra_execution_platforms) | |
| and | |
| [`--extra_toolchains`](/versions/9.3.0/reference/command-line-reference#flag--extra_toolchains). | |
| The host platform is automatically included as an available execution platform. | |
| Available platforms and toolchains are tracked as ordered lists for determinism, | |
| with preference given to earlier items in the list. | |
| The set of available toolchains, in priority order, is created from | |
| `--extra_toolchains` and `register_toolchains`: | |
| 1. Toolchains registered using `--extra_toolchains` are added first. (Within | |
| these, the **last** toolchain has highest priority.) | |
| 2. Toolchains registered using `register_toolchains` in the transitive external | |
| dependency graph, in the following order: (Within these, the **first** | |
| mentioned toolchain has highest priority.) | |
| 1. Toolchains registered by the root module (as in, the `MODULE.bazel` at the | |
| workspace root); | |
| 2. Toolchains registered in the user's `WORKSPACE` file, including in any | |
| macros invoked from there; | |
| 3. Toolchains registered by non-root modules (as in, dependencies specified by | |
| the root module, and their dependencies, and so forth); | |
| 4. Toolchains registered in the "WORKSPACE suffix"; this is only used by | |
| certain native rules bundled with the Bazel installation. | |
| **NOTE:** [Pseudo-targets like `:all`, `:*`, and | |
| `/...`](/versions/9.3.0/run/build#specifying-build-targets) are ordered by Bazel's package | |
| loading mechanism, which uses a lexicographic ordering. | |
| The resolution steps are as follows. | |
| 1. A `target_compatible_with` or `exec_compatible_with` clause *matches* a | |
| platform if, for each `constraint_value` in its list, the platform also has | |
| that `constraint_value` (either explicitly or as a default). | |
| If the platform has `constraint_value`s from `constraint_setting`s not | |
| referenced by the clause, these do not affect matching. | |
| 1. If the target being built specifies the | |
| [`exec_compatible_with` attribute](/versions/9.3.0/reference/be/common-definitions#common.exec_compatible_with) | |
| (or its rule definition specifies the | |
| [`exec_compatible_with` argument](/versions/9.3.0/rules/lib/globals/bzl#rule.exec_compatible_with)), | |
| the list of available execution platforms is filtered to remove | |
| any that do not match the execution constraints. | |
| 1. The list of available toolchains is filtered to remove any toolchains | |
| specifying `target_settings` that don't match the current configuration. | |
| 1. For each available execution platform, you associate each toolchain type with | |
| the first available toolchain, if any, that is compatible with this execution | |
| platform and the target platform. | |
| 1. Any execution platform that failed to find a compatible mandatory toolchain | |
| for one of its toolchain types is ruled out. Of the remaining platforms, the | |
| first one becomes the current target's execution platform, and its associated | |
| toolchains (if any) become dependencies of the target. | |
| The chosen execution platform is used to run all actions that the target | |
| generates. | |
| In cases where the same target can be built in multiple configurations (such as | |
| for different CPUs) within the same build, the resolution procedure is applied | |
| independently to each version of the target. | |
| If the rule uses [execution groups](/versions/9.3.0/extending/exec-groups), each execution | |
| group performs toolchain resolution separately, and each has its own execution | |
| platform and toolchains. | |
| ## Debugging toolchains {#debugging-toolchains} | |
| If you are adding toolchain support to an existing rule, use the | |
| `--toolchain_resolution_debug=regex` flag. During toolchain resolution, the flag | |
| provides verbose output for toolchain types or target names that match the regex variable. You | |
| can use `.*` to output all information. Bazel will output names of toolchains it | |
| checks and skips during the resolution process. | |
| For example, to debug toolchain selection for all actions created directly by | |
| `//my:target`: | |
| ```sh | |
| $ bazel build //my:all --toolchain_resolution_debug=//my:target | |
| ``` | |
| To debug toolchain selection for all actions over all build targets: | |
| ```sh | |
| $ bazel build //my:all --toolchain_resolution_debug=.* | |
| ``` | |
| If you'd like to see which [`cquery`](/versions/9.3.0/query/cquery) dependencies are from toolchain | |
| resolution, use `cquery`'s [`--transitions`](/versions/9.3.0/query/cquery#transitions) flag: | |
| ``` | |
| # Find all direct dependencies of //cc:my_cc_lib. This includes explicitly | |
| # declared dependencies, implicit dependencies, and toolchain dependencies. | |
| $ bazel cquery 'deps(//cc:my_cc_lib, 1)' | |
| //cc:my_cc_lib (96d6638) | |
| @bazel_tools//tools/cpp:toolchain (96d6638) | |
| @bazel_tools//tools/def_parser:def_parser (HOST) | |
| //cc:my_cc_dep (96d6638) | |
| @local_config_platform//:host (96d6638) | |
| @bazel_tools//tools/cpp:toolchain_type (96d6638) | |
| //:default_host_platform (96d6638) | |
| @local_config_cc//:cc-compiler-k8 (HOST) | |
| //cc:my_cc_lib.cc (null) | |
| @bazel_tools//tools/cpp:grep-includes (HOST) | |
| # Which of these are from toolchain resolution? | |
| $ bazel cquery 'deps(//cc:my_cc_lib, 1)' --transitions=lite | grep "toolchain dependency" | |
| [toolchain dependency]#@local_config_cc//:cc-compiler-k8#HostTransition -> b6df211 | |
| ``` |