Skip to content

Commit

Permalink
feat: add platform_transition_binary rule
Browse files Browse the repository at this point in the history
  • Loading branch information
kormide committed Dec 9, 2022
1 parent b1ee367 commit 7ba024f
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 1 deletion.
21 changes: 21 additions & 0 deletions docs/transitions.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions lib/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@ bzl_library(
bzl_library(
name = "transitions",
srcs = ["transitions.bzl"],
deps = [
"@bazel_skylib//lib:paths",
],
)

bzl_library(
Expand Down
50 changes: 49 additions & 1 deletion lib/tests/transitions/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
load("@bazel_skylib//rules:write_file.bzl", "write_file")
load("//lib:transitions.bzl", "platform_transition_filegroup")
load("//lib:transitions.bzl", "platform_transition_binary", "platform_transition_filegroup")
load("//lib:diff_test.bzl", "diff_test")
load("@io_bazel_rules_go//go:def.bzl", "go_binary")

platform(
name = "armv7_linux",
Expand All @@ -18,6 +19,15 @@ platform(
],
)

platform(
name = "arm64_linux",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:arm64",
"@io_bazel_rules_go//go/toolchain:cgo_off", # https://github.com/bazelbuild/rules_go/pull/3390
],
)

config_setting(
name = "is_x86",
constraint_values = [
Expand Down Expand Up @@ -90,3 +100,41 @@ diff_test(
file1 = ":for_arm_path",
file2 = ":expected_arm_path",
)

go_binary(
name = "test_transition_binary",
srcs = ["main.go"],
tags = ["manual"],
)

platform_transition_binary(
name = "transitioned_go_binary_x86_64",
binary = ":test_transition_binary",
target_platform = "x86_64_linux",
)

platform_transition_binary(
name = "transitioned_go_binary_arm64",
binary = ":test_transition_binary",
target_platform = "arm64_linux",
)

sh_test(
name = "test_go_binary_is_x86_64",
srcs = ["test_file_type_contains.sh"],
args = [
"$(rootpath :transitioned_go_binary_x86_64)",
"x86-64",
],
data = [":transitioned_go_binary_x86_64"],
)

sh_test(
name = "test_go_binary_is_arm64",
srcs = ["test_file_type_contains.sh"],
args = [
"$(rootpath :transitioned_go_binary_arm64)",
"aarch64",
],
data = [":transitioned_go_binary_arm64"],
)
7 changes: 7 additions & 0 deletions lib/tests/transitions/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package main

import "fmt"

func main() {
fmt.Println("Hello World!")
}
9 changes: 9 additions & 0 deletions lib/tests/transitions/test_file_type_contains.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash

# Test whether the output of `file` contains a text string.
#
# Usage: test_file_type_contains.sh <filePath> <text>

set -o errexit -o nounset -o pipefail

file "$(realpath "$1")" | grep -q "$2"
59 changes: 59 additions & 0 deletions lib/transitions.bzl
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"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)}

Expand Down Expand Up @@ -42,3 +44,60 @@ platform_transition_filegroup = rule(
},
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]

new_executable = None
files = default_info.files
original_executable = default_info.files_to_run.executable
runfiles = default_info.default_runfiles
if original_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])
runfiles = runfiles.merge(ctx.runfiles([new_executable]))

result.append(
DefaultInfo(
files = files,
runfiles = runfiles,
executable = new_executable,
),
)

return result

platform_transition_binary = rule(
implementation = _platform_transition_binary_impl,
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",
),
},
executable = True,
doc = "Transitions the binary to use the provided platform.",
)

0 comments on commit 7ba024f

Please sign in to comment.