Repository navigation
No way to use toolchains correctly in executable rule output #19645
Description
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
-
Examples of (incorrect) toolchains used for executable rules in rules_js, rules_docker, rules_oci, gazelle ↩
Activity
[-]Wanted: Easy and correct way to use toolchains in executable rule output[/-][+]There is no way to use toolchains correctly in executable rule output[/+][-]There is no way to use toolchains correctly in executable rule output[/-][+]No way to use toolchains correctly in executable rule output[/+]moroten commentedon Jan 25, 2024
Any updates on this?
47 remaining items
BoleynSu commentedon Sep 7, 2024
@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?
lberki commentedon Sep 9, 2024
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).
katre commentedon Sep 17, 2024
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.
lberki commentedon Sep 18, 2024
@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,
DefaultInfois 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?
katre commentedon Sep 18, 2024
I would be very happy to read and discuss a concrete proposal.
BoleynSu commentedon Nov 16, 2024
Related issue bazel-contrib/rules_shell#4 (comment)
fix: Use target tar toolchain for cross-platform execution (#844)
github-actions commentedon Jan 20, 2026
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.
archshift commentedon Jan 20, 2026
This is so important!
katre commentedon Jan 20, 2026
@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.
BoleynSu commentedon Jan 20, 2026
Let me draft one but it may take some time.
Improve cross exec platform toolchain selection
Improve cross exec platform toolchain selection (#146)