| "Rules for working with transitions." | |
| load("@bazel_skylib//lib:paths.bzl", "paths") | |
| def _transition_platform_impl(_, attr): | |
| return {"//command_line_option:platforms": str(attr.target_platform)} | |
| # Transition from any input configuration to one that includes the | |
| # --platforms command-line flag. | |
| _transition_platform = transition( | |
| implementation = _transition_platform_impl, | |
| inputs = [], | |
| outputs = ["//command_line_option:platforms"], | |
| ) | |
| def _platform_transition_filegroup_impl(ctx): | |
| files = [] | |
| runfiles = ctx.runfiles() | |
| for src in ctx.attr.srcs: | |
| files.append(src[DefaultInfo].files) | |
| runfiles = runfiles.merge_all([src[DefaultInfo].default_runfiles for src in ctx.attr.srcs]) | |
| return [DefaultInfo( | |
| files = depset(transitive = files), | |
| runfiles = runfiles, | |
| )] | |
| platform_transition_filegroup = rule( | |
| _platform_transition_filegroup_impl, | |
| attrs = { | |
| # Required to Opt-in to the transitions feature. | |
| "_allowlist_function_transition": attr.label( | |
| default = "@bazel_tools//tools/allowlists/function_transition_allowlist", | |
| ), | |
| "target_platform": attr.label( | |
| doc = "The target platform to transition the srcs.", | |
| mandatory = True, | |
| ), | |
| "srcs": attr.label_list( | |
| allow_empty = False, | |
| cfg = _transition_platform, | |
| doc = "The input to be transitioned to the target platform.", | |
| ), | |
| }, | |
| doc = "Transitions the srcs to use the provided platform. The filegroup will contain artifacts for the target platform.", | |
| ) | |
| def _platform_transition_binary_impl(ctx): | |
| # We need to forward the DefaultInfo provider from the underlying rule. | |
| # Unfortunately, we can't do this directly, because Bazel requires that the executable to run | |
| # is actually generated by this rule, so we need to symlink to it, and generate a synthetic | |
| # forwarding DefaultInfo. | |
| result = [] | |
| binary = ctx.attr.binary[0] | |
| default_info = binary[DefaultInfo] | |
| files = default_info.files | |
| new_executable = None | |
| original_executable = default_info.files_to_run.executable | |
| runfiles = default_info.default_runfiles | |
| if not original_executable: | |
| fail("Cannot transition a 'binary' that is not executable") | |
| new_executable_name = ctx.attr.basename if ctx.attr.basename else original_executable.basename | |
| # In order for the symlink to have the same basename as the original | |
| # executable (important in the case of proto plugins), put it in a | |
| # subdirectory named after the label to prevent collisions. | |
| new_executable = ctx.actions.declare_file(paths.join(ctx.label.name, new_executable_name)) | |
| ctx.actions.symlink( | |
| output = new_executable, | |
| target_file = original_executable, | |
| is_executable = True, | |
| ) | |
| files = depset(direct = [new_executable], transitive = [files]) | |
| runfiles = runfiles.merge(ctx.runfiles([new_executable])) | |
| result.append( | |
| DefaultInfo( | |
| files = files, | |
| runfiles = runfiles, | |
| executable = new_executable, | |
| ), | |
| ) | |
| return result | |
| _platform_transition_attrs = { | |
| "basename": attr.string(), | |
| "binary": attr.label(allow_files = True, cfg = _transition_platform), | |
| "target_platform": attr.label( | |
| doc = "The target platform to transition the binary.", | |
| mandatory = True, | |
| ), | |
| "_allowlist_function_transition": attr.label( | |
| default = "@bazel_tools//tools/allowlists/function_transition_allowlist", | |
| ), | |
| } | |
| platform_transition_binary = rule( | |
| implementation = _platform_transition_binary_impl, | |
| attrs = _platform_transition_attrs, | |
| executable = True, | |
| doc = "Transitions the binary to use the provided platform.", | |
| ) | |
| platform_transition_test = rule( | |
| implementation = _platform_transition_binary_impl, | |
| attrs = _platform_transition_attrs, | |
| test = True, | |
| doc = "Transitions the test to use the provided platform.", | |
| ) |