Last active
January 23, 2022 00:51
-
-
Save rrbutani/f5d80af864e67d873ae4491111d9dcce to your computer and use it in GitHub Desktop.
bazel toolchain_transition_test (non-native – not rules_cc)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
non-native – not rules_cc | |
the point is to see whether we can have a toolchain depend on another toolchain of the same type (using transitions) without Bazel thinking it's a cycle | |
i.e. bootstrapping | |
the answer appears to be yes; we can do this (without needing to resort to manually running commands from a repo rule or something) | |
this doesn't seem to work with rules_cc; a native ruleset | |
but it's not super clear why | |
this issue has a little context: https://github.com/bazelbuild/bazel/issues/11584 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
build --incompatible_enable_cc_toolchain_resolution |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
load(":defs.bzl", "foo", "foo_toolchain", "foo_transition") | |
toolchain_type(name = "foo_toolchain") | |
foo_toolchain( | |
name = "l1", | |
deps = [], | |
) | |
toolchain( | |
name = "l1_toolchain", | |
toolchain = ":l1", | |
toolchain_type = ":foo_toolchain", | |
) | |
foo( | |
name = "compiler", | |
src = ":defs.bzl", | |
) | |
foo_transition( | |
name = "compiler_pinned", | |
inner = ":compiler", | |
toolchain = ":l1_toolchain" | |
) | |
############################################## | |
# We can depend on `compiler` via `compiler_pinned` | |
# without creating a cycle because `compiler_pinned` | |
# is forced to use `l1`. | |
foo_toolchain( | |
name = "l2", | |
deps = [ | |
":compiler_pinned", | |
":l1", | |
], | |
) | |
toolchain( | |
name = "l2_toolchain", | |
toolchain = ":l2", | |
toolchain_type = ":foo_toolchain", | |
) | |
foo( | |
name = "test", | |
src = ":defs.bzl", | |
) | |
################################################ | |
cc_library( | |
name = "test_cc", | |
data = [ | |
":compiler_pinned", | |
] | |
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FooInfo = provider( | |
fields = [], | |
) | |
def foo_impl(ctx): | |
bin = ctx.actions.declare_file(ctx.label.name) | |
ctx.actions.write(bin, "#!/usr/bin/env bash", is_executable = True) | |
runfiles = ctx.runfiles(files = []) | |
return [DefaultInfo(runfiles = runfiles, executable = bin), FooInfo()] | |
foo = rule( | |
implementation = foo_impl, | |
executable = True, | |
toolchains = ["@t3//:foo_toolchain"], | |
incompatible_use_toolchain_transition = True, | |
provides = [FooInfo], | |
attrs = { | |
"src": attr.label( | |
allow_files = True, | |
), | |
} | |
) | |
FooToolchainInfo = provider( | |
fields = [], | |
) | |
def foo_toolchain_impl(ctx): | |
toolchain_info = platform_common.ToolchainInfo( | |
foo_toolchain = FooToolchainInfo(), | |
) | |
return [toolchain_info] | |
foo_toolchain = rule( | |
implementation = foo_toolchain_impl, | |
attrs = { | |
"deps": attr.label_list(), | |
} | |
) | |
################################################### | |
def foo_toolchain_transition_impl(settings, attr): | |
return { | |
"//command_line_option:extra_toolchains": [str(attr.toolchain)], | |
} | |
foo_toolchain_transition = transition( | |
implementation = foo_toolchain_transition_impl, | |
inputs = ["//command_line_option:extra_toolchains"], | |
outputs = ["//command_line_option:extra_toolchains"], | |
) | |
def foo_transition_impl(ctx): | |
# return [ctx.attr.inner[DefaultInfo], ctx.attr.inner[FooInfo]] | |
bin = ctx.actions.declare_file(ctx.label.name) | |
ctx.actions.write(bin, "#!/usr/bin/env bash", is_executable = True) | |
runfiles = ctx.runfiles(files = []) | |
return [DefaultInfo(runfiles = runfiles, executable = bin), FooInfo()] | |
foo_transition = rule( | |
implementation = foo_transition_impl, | |
cfg = foo_toolchain_transition, | |
provides = [FooInfo], | |
attrs = { | |
"inner": attr.label( | |
mandatory = True, | |
providers = [FooInfo], | |
), | |
"toolchain": attr.label( | |
mandatory = True, | |
# The inner toolchain (i.e. `//:l1`, the actual toolchain and not | |
# the "toolchain declaration", `//:l1_toolchain`) provides | |
# `platform_common.ToolchainInfo` with the `FooToolchainInfo` | |
# provider inside. | |
# | |
# The declaration (`//:l1_toolchain`) provides | |
# `DeclaredToolchainInfo` which is what we actually want. | |
# | |
# See this for more details about `DeclaredToolchainInfo`: | |
# https://github.com/bazelbuild/bazel/blob/master/src/main/java/com/google/devtools/build/lib/analysis/platform/DeclaredToolchainInfo.java | |
# | |
# Also note that we need to use `--experimental_platforms_api` to | |
# actually we able to use `platform_common.ToolchinInfo` as a | |
# required provider anyways. | |
# providers = [platform_common.ToolchainInfo], | |
# Unfortunately `DeclaredToolchainInfo` does not seem to be exposed | |
# to Starlark in any way; while there's code like this (https://github.com/bazelbuild/bazel/blob/09c621e4cf5b968f4c6cdf905ab142d5961f9ddc/src/main/java/com/google/devt | |
# for `ToolchainInfo` there is *not* for DeclaredToolchainInfo. | |
# | |
# This is ultimately okay though; Bazel correctly complains about | |
# the provided `toolchain` attr not having `DeclaredToolchainInfo` | |
# during toolchain resolution if a user passes in a label that's | |
# not a `toolchain` rule; this is more or less the same error we'd | |
# get if we were able to require `DeclaredToolchainInfo` as a | |
# provider. | |
), | |
"_allowlist_function_transition": attr.label( | |
default = "@bazel_tools//tools/allowlists/function_transition_allowlist" | |
), | |
} | |
) | |
#################################################### | |
def register(toolchains = []): | |
if type(toolchains) == "list": | |
native.register_toolchains(*toolchains) | |
else: | |
native.register_toolchains(toolchains) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
workspace(name = "t3") | |
load(":defs.bzl", "register") | |
# Note that we only register `l2` (though, we should be able to register `l1` | |
# without breaking anything). | |
register(toolchains = "l2_toolchain") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
update: in Bazel 5 this seems to work for native rulesets like
rules_cc
(!)(this was merged; older versions needed
--incompatible_override_toolchain_transition
)