Skip to content

Commit 8f4a0b2

Browse files
authored
Support exec platform different from host (#292)
Resolves #206.
1 parent dd35164 commit 8f4a0b2

File tree

5 files changed

+126
-3
lines changed

5 files changed

+126
-3
lines changed

README.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,9 @@ The following pairs have been tested to work for some hello-world binaries:
156156
A recommended approach would be to define two toolchains, one without sysroot
157157
for single-platform builds, and one with sysroot for cross-compilation builds.
158158
Then, when cross-compiling, explicitly specify the toolchain with the sysroot
159-
and the target platform. For example, see the [WORKSPACE](tests/WORKSPACE) file and
160-
the [test script](tests/scripts/run_xcompile_tests.sh) for cross-compilation.
159+
and the target platform. For example, see the [MODULE.bazel](tests/MODULE.bazel)
160+
file for `llvm_toolchain_with_sysroot` and the [test
161+
script](tests/scripts/run_xcompile_tests.sh) for cross-compilation.
161162

162163
```sh
163164
bazel build \
@@ -166,6 +167,25 @@ bazel build \
166167
//...
167168
```
168169

170+
### Multi-platform builds
171+
172+
The toolchain supports multi-platform builds through the combination of the
173+
`exec_os`, `exec_arch` attribute pair, and either the `distribution` attribute,
174+
or the `urls` attribute. This allows one to run their builds on one platform
175+
(e.g. macOS) and their build actions to run on another (e.g. Linux), enabling
176+
remote build execution (RBE). For example, see the [MODULE.bazel](tests/MODULE.bazel)
177+
file for `llvm_toolchain_linux_exec` and the [test
178+
script](tests/scripts/run_docker_exec_test.sh) for running the build actions on
179+
Linux even if the build is being run from macOS.
180+
181+
```sh
182+
bazel build \
183+
--platforms=@toolchains_llvm//platforms:linux-x86_64 \
184+
--extra_execution_platforms=@toolchains_llvm//platforms:linux-x86_64 \
185+
--extra_toolchains=@llvm_toolchain_linux_exec//:cc-toolchain-x86_64-linux \
186+
//...
187+
```
188+
169189
### Supporting New Target Platforms
170190

171191
The following is a rough (untested) list of steps:

tests/MODULE.bazel

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,17 @@ llvm.sysroot(
148148
label = "@@org_chromium_sysroot_linux_x64//:sysroot",
149149
)
150150
use_repo(llvm, "llvm_toolchain_with_sysroot")
151+
152+
llvm.toolchain(
153+
name = "llvm_toolchain_linux_exec",
154+
llvm_version = "17.0.6",
155+
# Option 1:
156+
sha256 = {"": "884ee67d647d77e58740c1e645649e29ae9e8a6fe87c1376be0f3a30f3cc9ab3"},
157+
strip_prefix = {"": "clang+llvm-17.0.6-x86_64-linux-gnu-ubuntu-22.04"},
158+
urls = {"": ["https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.6/clang+llvm-17.0.6-x86_64-linux-gnu-ubuntu-22.04.tar.xz"]},
159+
# Option 2:
160+
# distribution = "clang+llvm-17.0.6-x86_64-linux-gnu-ubuntu-22.04.tar.xz",
161+
exec_os = "linux",
162+
exec_arch = "amd64",
163+
)
164+
use_repo(llvm, "llvm_toolchain_linux_exec")

tests/scripts/run_docker_exec_test.sh

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/bin/bash
2+
# Copyright 2024 The Bazel Authors.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
set -euo pipefail
17+
18+
os="$(uname -s)"
19+
if [[ ${os} != "Darwin" ]]; then
20+
echo >&2 "Test, to be most effective, is meant to be run on Darwin."
21+
exit 1
22+
fi
23+
24+
if "${CI:-false}"; then
25+
# macOS GitHub Action Runners do not have docker installed on them.
26+
echo >&2 "Test can not be run on GitHub Actions"
27+
exit 1
28+
fi
29+
30+
scripts_dir="$(dirname "${BASH_SOURCE[0]}")"
31+
source "${scripts_dir}/bazel.sh"
32+
"${bazel}" version
33+
34+
cd "${scripts_dir}"
35+
36+
base_image="debian:stable-slim"
37+
binpath="$("${bazel}" info bazel-bin)/stdlib_test"
38+
39+
docker build --platform=linux/amd64 --pull --tag=bazel-docker-sandbox - <<-EOF
40+
FROM ${base_image}
41+
ENV DEBIAN_FRONTEND=noninteractive
42+
RUN apt-get -qq update && \
43+
apt-get -qq -y install libtinfo5 zlib1g-dev libxml2
44+
EOF
45+
46+
build_args=(
47+
# Platforms
48+
"--platforms=@toolchains_llvm//platforms:linux-x86_64"
49+
"--extra_execution_platforms=@toolchains_llvm//platforms:linux-x86_64"
50+
"--extra_toolchains=@llvm_toolchain_linux_exec//:cc-toolchain-x86_64-linux"
51+
# Docker sandbox
52+
"--experimental_enable_docker_sandbox"
53+
"--experimental_docker_verbose"
54+
"--experimental_docker_image=bazel-docker-sandbox"
55+
"--spawn_strategy=docker"
56+
# Verbosity of build actions
57+
"--copt=-v"
58+
"--linkopt=-v"
59+
"--linkopt=-Wl,-v"
60+
)
61+
62+
"${bazel}" --bazelrc=/dev/null build "${build_args[@]}" //:stdlib_test
63+
file "${binpath}" | tee /dev/stderr | grep -q ELF
64+
docker run --rm -it --platform=linux/amd64 \
65+
--mount "type=bind,source=${binpath},target=/stdlib_test" "${base_image}" /stdlib_test

toolchain/internal/common.bzl

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def os_version_arch(rctx):
9292
_os = os(rctx)
9393
_arch = arch(rctx)
9494

95-
if _os == "linux":
95+
if _os == "linux" and not rctx.attr.exec_os:
9696
(distname, version) = _linux_dist(rctx)
9797
return distname, version, _arch
9898

@@ -101,6 +101,13 @@ def os_version_arch(rctx):
101101
def os(rctx):
102102
# Less granular host OS name, e.g. linux.
103103

104+
name = rctx.attr.exec_os
105+
if name:
106+
if name in ("linux", "darwin"):
107+
return name
108+
else:
109+
fail("Unsupported value for exec_os: %s" % name)
110+
104111
name = rctx.os.name
105112
if name == "linux":
106113
return "linux"
@@ -115,6 +122,15 @@ def os_bzl(os):
115122
return {"darwin": "osx", "linux": "linux"}[os]
116123

117124
def arch(rctx):
125+
arch = rctx.attr.exec_arch
126+
if arch:
127+
if arch in ("arm64", "aarch64"):
128+
return "aarch64"
129+
elif arch in ("amd64", "x86_64"):
130+
return "x86_64"
131+
else:
132+
fail("Unsupported value for exec_arch: %s" % arch)
133+
118134
arch = rctx.os.arch
119135
if arch == "arm64":
120136
return "aarch64"

toolchain/internal/repo.bzl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ common_attrs = {
3535
"in the list of known llvm_distributions using the provided version. " +
3636
"If unset, a default value is set from the `llvm_version` attribute."),
3737
),
38+
"exec_os": attr.string(
39+
mandatory = False,
40+
doc = "Execution platform OS, if different from host OS.",
41+
),
42+
"exec_arch": attr.string(
43+
mandatory = False,
44+
doc = "Execution platform architecture, if different from host arch.",
45+
),
3846
}
3947

4048
llvm_repo_attrs = dict(common_attrs)

0 commit comments

Comments
 (0)