Skip to content

No way to use toolchains correctly in executable rule output #19645

Open

Description

@anguslees

Description of the feature request:

A common pattern1 I see in rules is toolchain declarations that effectively capture a tool path, and templated executable/test rules that resolve the toolchain and substitute the tool path into the executable file output.

Unfortunately this is incorrect! When the exec and target platforms differ, the toolchain will be resolved for the exec platform, but the executable/test output needs to be for the target platform.

As far as I can see, there is no way to make toolchain resolution / platform transitions do the correct thing here. Since executable rules are how bazel tests work, this is a pretty major gap in the toolchains/platforms story. I can't file bugs against rules, because there is no reasonable solution to suggest. This is a feature request for a solution that is (a) correct, and also ideally (b) easy/obvious.

One onerous current workaround is to declare two toolchains for all such cases. One that uses exec_compatible_with/target_compatible_with as usual, and is used when the toolchain is invoked by an action directly. And a second toolchain that uses target_compatible_with only, which can be used in executable rule output. This is moderately terrible, since this duplicates work for everybody, confuses the meaning of exec_compatible_with vs target_compatible_with, and toolchain authors can't anticipate when their toolchain needs to be used in this way - undoing the loose coupling between author and consumer that is kind of the point of toolchains.

An incorrect (afaics) version of the two-toolchains approach is to only declare target_compatible_with toolchain, then create a "current_foo_toolchain" rule that resolves the toolchain for a particular target, and returns the toolchain provider through a rule attribute - see eg python toolchain. This is incorrect in general because another toolchain that depends on this toolchain cannot be resolved at the same time for the same exec+target combination (ie: toolchains=[foo] with a dependency on another rule with toolchains=[bar], is not the same as toolchains=[foo, bar]).

As a possible implementation, I'd love to be able to do exec_group(cfg='target'), since I think ctx.exec_groups["target"].toolchains is an intuitive and 'obvious' way to address the above.

Another option is to not use toolchains for what are effectively artifacts. Rule authors obviously like the loose coupling between toolchain declaration and use however, so this potential path would require widespread advocacy/documentation, and perhaps a canonical meta-library for an "artifact toolchain".

See also slack thread: https://bazelbuild.slack.com/archives/CA31HN1T3/p1690176577746239

Which category does this issue belong to?

Core

What underlying problem are you trying to solve with this feature?

It should be possible to resolve and refer to the correct toolchain for an executable rule output.

Which operating system are you running Bazel on?

macos and Linux

What is the output of bazel info release?

6.3.2

If bazel info release returns development version or (@non-git), tell us how you built Bazel.

No response

What's the output of git remote get-url origin; git rev-parse master; git rev-parse HEAD ?

No response

Have you found anything relevant by searching the web?

No response

Any other information, logs, or outputs that you want to share?

No response

Footnotes

  1. Examples of (incorrect) toolchains used for executable rules in rules_js, rules_docker, rules_oci, gazelle ↩

Activity

  1. changed the title [-]Wanted: Easy and correct way to use toolchains in executable rule output[/-] [+]There is no way to use toolchains correctly in executable rule output[/+] on Sep 27, 2023
  2. changed the title [-]There is no way to use toolchains correctly in executable rule output[/-] [+]No way to use toolchains correctly in executable rule output[/+] on Sep 27, 2023
  3. added
    team-CoreSkyframe, bazel query, BEP, options parsing, bazelrc
    on Sep 27, 2023
  4. moroten commented on Jan 25, 2024

    @moroten
    Contributor

    Any updates on this?

  5. added
    team-Rules-APIAPI for writing rules/aspects: providers, runfiles, actions, artifacts
    on Jan 25, 2024
  6. removed
    team-CoreSkyframe, bazel query, BEP, options parsing, bazelrc
    team-Rules-APIAPI for writing rules/aspects: providers, runfiles, actions, artifacts
    on Feb 8, 2024
  7. 47 remaining items

  8. BoleynSu commented on Sep 7, 2024

    @BoleynSu
    Contributor

    @katre @lberki I would prefer to make no changes to Bazel if these can be implemented as library (to make Bazel less complex). I can write some docs and would be great if @fmeum can also help.

    There is no need to ask very toolchain to be usable with the wrapper. For example, if I define a cc_toolchain, I may or may not want to expose the compiler to user of the toolchain, i.e., CcToolchainInfo(compile=a function to use the binary). Only if I do want to expose the binary, we can register the compiler binary to "//gcc:toolchain_type" and use "//gcc:resolved_binary" with cfg="exec" in cc_toolchain.

    Also I want to emphasis that the transition_exec_to_target approach is broken. See bazel-contrib/rules_oci#590 (comment)

    There are aleady a few PRs based on such hack merged and some pendding. @EdSchouten could you hold on pending PRs?

  9. lberki commented on Sep 9, 2024

    @lberki
    Contributor

    I'm not sure "making Bazel less complex" is the right thing to optimze for here.

    It's a good idea to optimize for "less complexity is seen by the people who use Bazel", but that complexity is not just that of Bazel, but also that of all external Bazel code they depend on and that includes toolchain type definitions and their implementations. IOW, if we can buy simplicity in many toolchains with a little additional wrinkle in Bazel, that's a good deal.

    That said, your argument that toolchains are not necessarily single groups of files is a good one for arguing against finding a solution in Bazel (for example, even the C++ compiler is not just a single group of file because Bazel has the ability to take different sets of inputs for e.g. compile and link actions).

  10. katre commented on Sep 17, 2024

    @katre
    Collaborator

    Coming back to this: @lberki, I can see your point, but I'm very unclear if there's an actual request besides "make this easier".

    I'm happy to review and discuss a concrete proposal, but I'm not sure the Configurability team can actually spend any time on this in the near future.

  11. lberki commented on Sep 18, 2024

    @lberki
    Contributor

    @katre fair enough; I think the insight above that a toolchain doesn't even necessarily need to provide any files to be a toolchain (which manifests in the code as toolchains being free to provider any provider, DefaultInfo is not necessarily needed) makes it undesirable that we provide a general "put the files comprising this toolchain on the inputs of that action" functionality.

    I think what may make sense is being able to ask Bazel "give me a toolchain whose host configuration matches my target configuration", but given that it has a workaround in Starlark (declaring two toolchains and two toolchain types) and that we'd have to decide what target configuration that toolchain should have, I don't think we should treat this as a priority.

    I guess if there was a concrete proposal to do so, @katre would entertain it, wouldn't he?

  12. katre commented on Sep 18, 2024

    @katre
    Collaborator

    I would be very happy to read and discuss a concrete proposal.

  13. BoleynSu commented on Nov 16, 2024

    @BoleynSu
    Contributor
  14. github-actions commented on Jan 20, 2026

    @github-actions

    Thank you for contributing to the Bazel repository! This issue has been marked as stale since it has not had any activity in the last 1+ years. It will be closed in the next 90 days unless any other activity occurs. If you think this issue is still relevant and should stay open, please post any comment here and the issue will no longer be marked as stale.

  15. added
    staleIssues or PRs that are stale (no activity for 30 days)
    on Jan 20, 2026
  16. archshift commented on Jan 20, 2026

    @archshift

    This is so important!

  17. katre commented on Jan 20, 2026

    @katre
    Collaborator

    @archshift Did anyone ever submit a concrete proposal for what needs to be changed? I'm still happy to review such a thing and make recommendations to the Bazel team.

  18. BoleynSu commented on Jan 20, 2026

    @BoleynSu
    Contributor

    Let me draft one but it may take some time.

  19. removed
    staleIssues or PRs that are stale (no activity for 30 days)
    on Jan 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3We're not considering working on this, but happy to review a PR. (No assignee)team-Configurabilityplatforms, toolchains, cquery, select(), config transitionstype: feature request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions