Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions .github/workflows/release_build_tools.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Builds `//dev/release_artifacts:artifacts_for_release` natively for each
# platform; see dev/release_artifacts/build.sh.
# Builds `//dev/release_artifacts:artifacts_for_release` for each platform; see
# dev/release_artifacts/build.sh. Linux x86_64 runners cross-compile the files
# for other Linux CPUs. macOS and Windows files need those OSes' SDKs, so
# they're built natively.
#
# For now, this only verifies that the artifacts build; they aren't attached to
# releases yet.
Expand Down Expand Up @@ -40,8 +42,9 @@ jobs:
runner: macos-15
- triple: aarch64-pc-windows-msvc
runner: windows-11-arm
- triple: aarch64-unknown-linux-gnu
runner: ubuntu-24.04-arm
# Cross-compiled; see dev/platforms/BUILD.bazel.
- triple: aarch64-unknown-linux-musl
runner: ubuntu-24.04
- triple: x86_64-apple-darwin
runner: macos-15-intel
- triple: x86_64-pc-windows-msvc
Expand All @@ -66,11 +69,12 @@ jobs:
bazelisk-version: 1.29.0

# Release commands run main's workflows, even for patch releases of older
# release branches, which don't have the script; skip those.
# release branches. Skip refs without the platforms that build.sh takes,
# since their scripts don't build for the job's platform, or don't exist.
- name: Build artifacts
id: build
if: hashFiles('dev/release_artifacts/build.sh') != ''
run: dev/release_artifacts/build.sh "$REF"
if: hashFiles('dev/platforms/BUILD.bazel') != ''
run: dev/release_artifacts/build.sh "$REF" "$TRIPLE"

# build.sh only sets `files` if the build succeeded. Otherwise, it adds a
# warning instead of failing, since releases don't use the files yet.
Expand Down
38 changes: 38 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,44 @@ rust_crates.spec(
rust_crates.from_specs()
use_repo(rust_crates, "crates")

# A Rust toolchain to cross-compile the release artifacts for Linux aarch64
# from Linux x86_64; see dev/release_artifacts. It targets musl, which Rust can
# link statically with its bundled rust-lld, so no C cross toolchain is needed.
rust = use_extension(
"@rules_rust//rust:extensions.bzl",
"rust",
dev_dependency = True,
)
rust.repository_set(
# rules_rust also registers an x86_64 to x86_64 toolchain from this set, in
# name order with its default ones, so the name must sort after
# rust_linux_x86_64 for the default x86_64 toolchain to take precedence.
name = "rust_release_linux_x86_64",
# The default allocator library needs a C toolchain for the target platform,
# but there isn't one. This one is what rules_rust uses for e.g. Windows.
allocator_library = "@rules_rust//rust/private/cc:empty",
edition = "2021",
exec_triple = "x86_64-unknown-linux-gnu",
target_compatible_with = [
"@platforms//cpu:aarch64",
"@platforms//os:linux",
"//dev/platforms:musl",
],
target_triple = "aarch64-unknown-linux-musl",
# rules_rust 0.73.0's default version; update it with rules_rust. The
# default toolchain builds proc-macros, which rustc only loads if they were
# built by the same version.
versions = ["1.97.1"],
)
use_repo(rust, "rust_release_linux_x86_64__aarch64-unknown-linux-musl__stable")

# Registered here so that it takes precedence over rules_rust's default
# toolchains, whose Linux x86_64 to aarch64 one also matches the musl platform.
register_toolchains(
"@rust_release_linux_x86_64__aarch64-unknown-linux-musl__stable//:toolchain",
dev_dependency = True,
)

# Use the Rust-based build tools when developing rules_python itself.
register_toolchains(
"//dev/dev_only_toolchains:exe_zip_maker_toolchain",
Expand Down
67 changes: 67 additions & 0 deletions dev/platforms/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Platforms that rules_python's release artifacts are built for, named after
# their Rust target triples; see dev/release_artifacts/build.sh. Linux x86_64
# hosts cross-compile for the musl one with the musl Rust toolchain in
# MODULE.bazel. The others are built on hosts that match them.

package(default_visibility = ["//:__subpackages__"])

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

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

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

platform(
name = "x86_64-apple-darwin",
constraint_values = [
"@platforms//cpu:x86_64",
"@platforms//os:macos",
],
)

platform(
name = "x86_64-pc-windows-msvc",
constraint_values = [
"@platforms//cpu:x86_64",
"@platforms//os:windows",
],
)

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

# The libc of Linux platforms. Only musl is a constraint value: platforms
# without it, like the host, use glibc. It also keeps the musl Rust toolchain
# in MODULE.bazel from being used for glibc platforms.
constraint_setting(name = "libc")

constraint_value(
name = "musl",
constraint_setting = ":libc",
# The musl Rust toolchain's repo, generated by rules_rust, refers to it.
visibility = ["//visibility:public"],
)
3 changes: 2 additions & 1 deletion dev/release_artifacts/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ load(":release_files.bzl", "release_files")

package(default_visibility = ["//:__subpackages__"])

# Files that the release workflow builds for each platform; see build.sh.
# Files that the release workflow builds for each platform in dev/platforms;
# see build.sh.
release_files(
name = "artifacts_for_release",
srcs = ["//crates/exe_zip_maker"],
Expand Down
15 changes: 9 additions & 6 deletions dev/release_artifacts/build.sh
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
#!/usr/bin/env bash
# Builds //dev/release_artifacts:artifacts_for_release for the host platform.
# The target applies the release settings; see release_files.bzl. In GitHub
# Actions, the paths of the built files, relative to the workspace root, are
# set as the step's `files` output, one per line.
# Builds //dev/release_artifacts:artifacts_for_release for the platform with
# the Rust target triple TRIPLE; see dev/platforms. The target applies the
# release settings for the platform's OS and libc; see release_files.bzl. In
# GitHub Actions, the paths of the built files, relative to the workspace root,
# are set as the step's `files` output, one per line.
#
# Usage: dev/release_artifacts/build.sh EMBED_LABEL
# Usage: dev/release_artifacts/build.sh EMBED_LABEL TRIPLE
set -euo pipefail

embed_label="$1"
triple="$2"

# The paths below are relative to the workspace root.
cd "$(dirname "$0")/../.."
Expand All @@ -16,7 +18,8 @@ cd "$(dirname "$0")/../.."
export MSYS_NO_PATHCONV=1 MSYS2_ARG_CONV_EXCL="*"

if ! bazel build --verbose_failures --compilation_mode=opt --stamp \
--embed_label="$embed_label" //dev/release_artifacts:artifacts_for_release; then
--embed_label="$embed_label" --platforms="//dev/platforms:$triple" \
//dev/release_artifacts:artifacts_for_release; then
# Releases don't use the files yet, so don't fail the release over them.
echo "::warning::Building the release artifacts failed. Releases don't use them yet."
exit 0
Expand Down
18 changes: 13 additions & 5 deletions dev/release_artifacts/release_files.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ _RUSTC_FLAGS = "@rules_rust//rust/settings:extra_rustc_flags"
def _release_transition_impl(settings, attr):
features = []
rustc_flags = []
if attr.target_os == "linux":
if attr.target_os == "linux" and attr.target_libc != "musl":
# Rust links glibc dynamically, so the files would require at least
# the build machine's glibc version. Link it statically so they run on
# older distros too. The gold linker can't link static glibc, so use
# bfd.
# bfd. Rust already links musl statically.
rustc_flags = [
"-Ctarget-feature=+crt-static",
"-Clink-arg=-fuse-ld=bfd",
Expand Down Expand Up @@ -60,6 +60,9 @@ _release_files = rule(
cfg = _release_transition,
doc = "The files to build and list.",
),
"target_libc": attr.string(
doc = "The libc that the files are built for. Set by the macro.",
),
"target_os": attr.string(
doc = "The OS that the files are built for. Set by the macro.",
),
Expand All @@ -69,9 +72,10 @@ _release_files = rule(
def release_files(name, srcs, **kwargs):
"""Builds files for a release and writes their paths to `<name>.txt`.

The files are built with release settings: optimized, and linked so that
they run on older OS versions than the build machine's, without extra
runtime libraries.
The files are built for the target platform (`--platforms`), with release
settings for its OS and libc: optimized, and linked so that they run on
older OS versions than the build machine's, without extra runtime
libraries.

The paths, one per line, are relative to the execroot, e.g.
`bazel-out/k8-opt-ST-1234/bin/foo/foo`. Paths of generated files also
Expand All @@ -87,6 +91,10 @@ def release_files(name, srcs, **kwargs):
_release_files(
name = name,
srcs = srcs,
target_libc = select({
"//dev/platforms:musl": "musl",
"//conditions:default": "",
}),
target_os = select({
Label("@platforms//os:linux"): "linux",
labels.PLATFORMS_OS_WINDOWS: "windows",
Expand Down
34 changes: 27 additions & 7 deletions dev/release_artifacts/verify.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#!/usr/bin/env bash
# Checks that the files built by build.sh don't require a newer OS than users
# may have. Only Linux and macOS files are checked.
# Checks the files built by build.sh for the platform with the Rust target
# triple TRIPLE: that Linux files are statically linked for the right CPU, and
# that macOS files don't require a newer macOS than users may have. Windows
# files aren't checked.
#
# Usage: dev/release_artifacts/verify.sh TRIPLE
set -euo pipefail
Expand All @@ -13,11 +15,24 @@ cd "$(dirname "$0")/../.."
# The target lists the paths of its files in a manifest; see release_files.bzl.
while IFS= read -r bin; do
case "$triple" in
*-linux-gnu)
linkage="$(file "$bin")"
if [[ "$linkage" != *"statically linked"* &&
"$linkage" != *"static-pie linked"* ]]; then
echo "::error::$bin isn't statically linked: $linkage"
*-linux-*)
info="$(file -L -b "$bin")"
if [[ "$info" != *"statically linked"* && "$info" != *"static-pie linked"* ]]; then
echo "::error::$bin isn't statically linked: $info"
exit 1
fi
# Some Linux files are cross-compiled, so check that they're for the
# right CPU.
case "$triple" in
aarch64-*) cpu="ARM aarch64" ;;
x86_64-*) cpu="x86-64" ;;
*)
echo "::error::$bin: no CPU check for $triple"
exit 1
;;
esac
if [[ "$info" != *", $cpu,"* ]]; then
echo "::error::$bin isn't for $cpu: $info"
exit 1
fi
;;
Expand All @@ -32,5 +47,10 @@ while IFS= read -r bin; do
exit 1
fi
;;
*-windows-*) ;; # Not checked.
*)
echo "::error::$bin: no checks for $triple"
exit 1
;;
esac
done < bazel-bin/dev/release_artifacts/artifacts_for_release.txt
Loading