Skip to content

Commit 7cc6c1d

Browse files
committed
Transition container image target platform
Transition to the target platform associated with the `architecture` and `operating_system` attributes on container image rules. This change allows for container image rules to build the correct binary for the target platform, regardless of the host platform. Container image rules would require the use of the `target_compatible_with` attribute to prevent mismatching host and target platforms building dependencies incorrectly. Additionally, hosts which did not match the target platform had to explicitly specify the target platform with the `--platforms` command-line option. This change fixes the aforementioned issues and #690. Massive thank you to @joneshf for the initial source. It has been adapted to automatically select the target platform associated with the container image, as opposed to always using `@io_bazel_rules_go//go/toolchain:linux_amd64`.
1 parent 8f6a2aa commit 7cc6c1d

3 files changed

Lines changed: 80 additions & 5 deletions

File tree

lang/image.bzl

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ def _binary_name(ctx):
3434
# /app/foo/bar/baz/blah
3535
return "/".join([
3636
ctx.attr.directory,
37-
ctx.attr.binary.label.package,
38-
ctx.attr.binary.label.name,
37+
ctx.attr.binary[0].label.package,
38+
ctx.attr.binary[0].label.name,
3939
])
4040

4141
def _runfiles_dir(ctx):
@@ -148,7 +148,7 @@ def _app_layer_impl(ctx, runfiles = None, emptyfiles = None):
148148
parent_parts = _get_layers(ctx, ctx.attr.name, ctx.attr.base)
149149
filepath = _final_file_path if ctx.attr.binary else layer_file_path
150150
emptyfilepath = _final_emptyfile_path if ctx.attr.binary else _layer_emptyfile_path
151-
dep = ctx.attr.dep or ctx.attr.binary
151+
dep = (ctx.attr.dep or ctx.attr.binary)[0]
152152
top_layer = ctx.attr.binary and not ctx.attr.dep
153153

154154
if ctx.attr.create_empty_workspace_dir:
@@ -239,6 +239,27 @@ def _app_layer_impl(ctx, runfiles = None, emptyfiles = None):
239239
null_cmd = args == [],
240240
)
241241

242+
def _image_transition_impl(settings, attr):
243+
_ignore = (settings, attr)
244+
245+
# Architecture aliases.
246+
architecture = {
247+
"386": "x86_32",
248+
"amd64": "x86_64",
249+
"ppc64le": "ppc",
250+
}.get(attr.architecture, attr.architecture)
251+
return {
252+
"//command_line_option:platforms": "//platforms:{}_{}".format(attr.operating_system, architecture),
253+
}
254+
255+
_image_transition = transition(
256+
implementation = _image_transition_impl,
257+
inputs = [],
258+
outputs = [
259+
"//command_line_option:platforms",
260+
],
261+
)
262+
242263
image = struct(
243264
attrs = dicts.add(_container.image.attrs, {
244265
# The base image on which to overlay the dependency layers.
@@ -250,7 +271,7 @@ image = struct(
250271
# the runfiles dir.
251272
"binary": attr.label(
252273
executable = True,
253-
cfg = "target",
274+
cfg = _image_transition,
254275
),
255276
# Set this to true to create an empty workspace directory under the
256277
# app directory specified as the 'directory' attribute.
@@ -263,11 +284,14 @@ image = struct(
263284
# The dependency whose runfiles we're appending.
264285
# If not specified, then the layer will be treated as the top layer,
265286
# and all remaining deps of "binary" will be added under runfiles.
266-
"dep": attr.label(),
287+
"dep": attr.label(cfg = _image_transition),
267288
"directory": attr.string(default = "/app"),
268289
"entrypoint": attr.string_list(default = []),
269290
"legacy_run_behavior": attr.bool(default = False),
270291
"workdir": attr.string(default = ""),
292+
"_allowlist_function_transition": attr.label(
293+
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
294+
),
271295
}),
272296
outputs = _container.image.outputs,
273297
toolchains = ["@io_bazel_rules_docker//toolchains/docker:toolchain_type"],

nodejs/image.bzl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ load(
2525
load(
2626
"//lang:image.bzl",
2727
"app_layer",
28+
_lang_image_transition = "_image_transition",
2829
lang_image = "image",
2930
)
3031
load(
@@ -80,6 +81,7 @@ _dep_layer = rule(
8081
"dep": attr.label(
8182
mandatory = True,
8283
allow_files = True, # override
84+
cfg = _lang_image_transition,
8385
),
8486
}),
8587
executable = True,

platforms/BUILD

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,52 @@ platform(
5656
],
5757
parents = ["@buildkite_config//config:platform"],
5858
)
59+
60+
# All OSs known to Bazel.
61+
#
62+
# curl -Lfs https://raw.githubusercontent.com/bazelbuild/platforms/main/os/BUILD | grep -Eo 'name = "\w+"' | grep -Eo '"\w+"' | grep -Ev 'srcs|os|none' | tr -d '"' | sort -u -f | xargs -I '{}' echo '"@platforms//os:{}",'
63+
_OS_CONSTRAINTS = (
64+
"@platforms//os:android",
65+
"@platforms//os:freebsd",
66+
"@platforms//os:linux",
67+
"@platforms//os:netbsd",
68+
"@platforms//os:openbsd",
69+
"@platforms//os:qnx",
70+
"@platforms//os:wasi",
71+
"@platforms//os:windows",
72+
)
73+
74+
# All CPUs known to Bazel.
75+
#
76+
# curl -Lfs https://raw.githubusercontent.com/bazelbuild/platforms/main/cpu/BUILD | grep -Eo 'name = "\w+"' | grep -Eo '"\w+"' | grep -Ev 'cpu|srcs' | tr -d '"' | sort -u -f | xargs -I '{}' echo '"@platforms//cpu:{}",'
77+
_CPU_CONSTRAINTS = (
78+
"@platforms//cpu:aarch64",
79+
"@platforms//cpu:arm",
80+
"@platforms//cpu:arm64",
81+
"@platforms//cpu:arm64e",
82+
"@platforms//cpu:arm64_32",
83+
"@platforms//cpu:armv7",
84+
"@platforms//cpu:armv7k",
85+
"@platforms//cpu:i386",
86+
"@platforms//cpu:mips64",
87+
"@platforms//cpu:ppc",
88+
"@platforms//cpu:riscv32",
89+
"@platforms//cpu:riscv64",
90+
"@platforms//cpu:s390x",
91+
"@platforms//cpu:wasm32",
92+
"@platforms//cpu:wasm64",
93+
"@platforms//cpu:x86_32",
94+
"@platforms//cpu:x86_64",
95+
)
96+
97+
# Register all known Bazel platform combinations for use with transitions.
98+
[platform(
99+
name = "{}_{}".format(
100+
os.rsplit(":", 1)[1],
101+
cpu.rsplit(":", 1)[1],
102+
),
103+
constraint_values = [
104+
os,
105+
cpu,
106+
],
107+
) for os in _OS_CONSTRAINTS for cpu in _CPU_CONSTRAINTS]

0 commit comments

Comments
 (0)