Skip to content

Commit

Permalink
Make cross-compiling with bzlmod possible, added example (#2419)
Browse files Browse the repository at this point in the history
Before it wasn't possible to add your desired cross-compilation targets
to `extra_target_triples` if they also happened to be in
`DEFAULT_TOOLCHAIN_TRIPLES`.
  • Loading branch information
jondo2010 authored Feb 2, 2024
1 parent 0f777e1 commit c06564d
Show file tree
Hide file tree
Showing 11 changed files with 177 additions and 1 deletion.
1 change: 1 addition & 0 deletions examples/bzlmod/cross_compile/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build --experimental_enable_bzlmod
2 changes: 2 additions & 0 deletions examples/bzlmod/cross_compile/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/bazel-*
/MODULE.bazel.lock
54 changes: 54 additions & 0 deletions examples/bzlmod/cross_compile/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
load("@rules_rust//rust:defs.bzl", "rust_binary")

package(default_visibility = ["//visibility:public"])

rust_binary(
name = "hello_world_aarch64",
srcs = ["src/main.rs"],
platform = ":linux-aarch64",
deps = [],
)

rust_binary(
name = "hello_world_x86_64",
srcs = ["src/main.rs"],
platform = ":linux-x86_64",
deps = [],
)

[
sh_test(
name = "hello_world_{}_test".format(target),
srcs = ["hello_world_test.sh"],
args = [
"$(rlocationpath :hello_world_{})".format(target),
arch_string,
],
data = [
":hello_world_{}".format(target),
],
deps = [
"@bazel_tools//tools/bash/runfiles",
],
)
for (target, arch_string) in [
("aarch64", "AArch64"),
("x86_64", "X86-64"),
]
]

platform(
name = "linux-aarch64",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:aarch64",
],
)

platform(
name = "linux-x86_64",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
],
)
39 changes: 39 additions & 0 deletions examples/bzlmod/cross_compile/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""bazelbuild/rules_rust - bzlmod cross-compilation example"""

module(
name = "cross_compile_example",
version = "0.0.0",
)

bazel_dep(name = "bazel_skylib", version = "1.5.0")
bazel_dep(name = "platforms", version = "0.0.8")
bazel_dep(name = "toolchains_llvm", version = "0.10.3")

# rules_rust still needs a cpp toolchain, so provide a cross-compiling one here
llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm")
llvm.toolchain(
name = "llvm_toolchain",
llvm_version = "16.0.0",
sysroot = {"linux-aarch64": "@@org_chromium_sysroot_linux_aarch64//:sysroot"},
)
use_repo(llvm, "llvm_toolchain", "llvm_toolchain_llvm")

register_toolchains("@llvm_toolchain//:all")

bazel_dep(name = "rules_rust", version = "0.0.0")
local_path_override(
module_name = "rules_rust",
path = "../../..",
)

rust = use_extension("@rules_rust//rust:extensions.bzl", "rust")
rust.toolchain(
edition = "2021",
extra_target_triples = [
"aarch64-unknown-linux-gnu",
"x86_64-unknown-linux-gnu",
],
)
use_repo(rust, "rust_toolchains")

register_toolchains("@rust_toolchains//:all")
6 changes: 6 additions & 0 deletions examples/bzlmod/cross_compile/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# bzlmod cross-compile example

This example shows how to use `rules_rust` through bzlmod to invoke Rust cross-compilation.

It should be possible to `bazel build //:hello_world_aarch64` and `bazel build //:hello_world_x86_64` regardless of your
host platform (as long as it is supported by Bazel and rustc).
1 change: 1 addition & 0 deletions examples/bzlmod/cross_compile/WORKSPACE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Intentionally blank; using bzlmod
17 changes: 17 additions & 0 deletions examples/bzlmod/cross_compile/WORKSPACE.bzlmod
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

_BUILD_FILE_CONTENT = """filegroup(
name = "{name}",
srcs = glob(["*/**"]),
visibility = ["//visibility:public"],
)
"""

http_archive(
name = "org_chromium_sysroot_linux_aarch64",
sha256 = "902d1a40a5fd8c3764a36c8d377af5945a92e3d264c6252855bda4d7ef81d3df",
url = "https://commondatastorage.googleapis.com/chrome-linux-sysroot/toolchain/{}".format(
"41a6c8dec4c4304d6509e30cbaf9218dffb4438e/debian_bullseye_arm64_sysroot.tar.xz",
),
build_file_content = _BUILD_FILE_CONTENT.format(name = "sysroot"),
)
38 changes: 38 additions & 0 deletions examples/bzlmod/cross_compile/hello_world_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/usr/bin/env bash

# --- begin runfiles.bash initialization v3 ---
# Copy-pasted from the Bazel Bash runfiles library v3.
set -uo pipefail; set +e; f=bazel_tools/tools/bash/runfiles/runfiles.bash
source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \
source "$0.runfiles/$f" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \
{ echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e
# --- end runfiles.bash initialization v3 ---


set -euo pipefail

# MARK - Functions

fail() {
echo >&2 "$@"
exit 1
}

# MARK - Args

if [[ "$#" -ne 2 ]]; then
fail "Usage: $0 /path/to/hello_world expected_arch"
fi
HELLO_WORLD="$(rlocation "$1")"
ARCH_STRING="$2"

# MARK - Test

OUTPUT="$(readelf -h "${HELLO_WORLD}")"

# Match the architecture string with grep.
echo "${OUTPUT}" | grep -E "Machine:(.+)${ARCH_STRING}" ||
fail "Expected '${ARCH_STRING}' in ${OUTPUT}"
17 changes: 17 additions & 0 deletions examples/bzlmod/cross_compile/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2015 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

fn main() {
println!("Hello, world!");
}
1 change: 1 addition & 0 deletions examples/bzlmod/hello_world/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module(
version = "0.0.0",
)

bazel_dep(name = "platforms", version = "0.0.8")
bazel_dep(
name = "bazel_skylib",
version = "1.5.0",
Expand Down
2 changes: 1 addition & 1 deletion rust/repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@ rust_toolchain_set_repository = repository_rule(
def _get_toolchain_repositories(name, exec_triple, extra_target_triples, versions, iso_date):
toolchain_repos = []

for target_triple in [exec_triple] + extra_target_triples:
for target_triple in depset([exec_triple] + extra_target_triples).to_list():
# Parse all provided versions while checking for duplicates
channels = {}
for version in versions:
Expand Down

0 comments on commit c06564d

Please sign in to comment.