Repository navigation
build(release): build prebuilt tools in the release workflow #4217
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
rickeylev
merged 2 commits into
bazel-contrib:main
from
rickeylev:build_rust_exe_artifacts
Oct 8, 2026
+288
−0
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| # Builds `//dev/release_artifacts:artifacts_for_release` natively for each | ||
| # platform; see dev/release_artifacts/build.sh. | ||
| # | ||
| # For now, this only verifies that the artifacts build; they aren't attached to | ||
| # releases yet. | ||
| name: "Release: Build Tools" | ||
|
|
||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| ref: | ||
| description: "The git ref (e.g. release tag) to build" | ||
| required: true | ||
| type: string | ||
| workflow_dispatch: | ||
| inputs: | ||
| ref: | ||
| description: "The git ref (e.g. release tag) to build. Defaults to the selected ref." | ||
| required: false | ||
| type: string | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| defaults: | ||
| run: | ||
| shell: bash | ||
|
|
||
| jobs: | ||
| build: | ||
| name: Build ${{ matrix.triple }} | ||
| runs-on: ${{ matrix.runner }} | ||
| strategy: | ||
| # Report the result of every platform instead of stopping at the first | ||
| # failure. | ||
| fail-fast: false | ||
| matrix: | ||
| include: | ||
| - triple: aarch64-apple-darwin | ||
| runner: macos-15 | ||
| - triple: aarch64-pc-windows-msvc | ||
| runner: windows-11-arm | ||
| - triple: aarch64-unknown-linux-gnu | ||
| runner: ubuntu-24.04-arm | ||
| - triple: x86_64-apple-darwin | ||
| runner: macos-15-intel | ||
| - triple: x86_64-pc-windows-msvc | ||
| runner: windows-2022 | ||
| - triple: x86_64-unknown-linux-gnu | ||
| runner: ubuntu-24.04 | ||
| env: | ||
| REF: ${{ inputs.ref || github.ref_name }} | ||
| TRIPLE: ${{ matrix.triple }} | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v7 | ||
| with: | ||
| ref: ${{ inputs.ref }} | ||
| persist-credentials: false | ||
|
|
||
| - name: Setup Bazel | ||
| uses: bazel-contrib/setup-bazel@0.19.0 | ||
| with: | ||
| # Windows images also have a fixed-version `bazel` on PATH. 1.20.0, | ||
| # used by the other workflows, has no windows-arm64 build. | ||
| 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. | ||
| - name: Build artifacts | ||
| id: build | ||
| if: hashFiles('dev/release_artifacts/build.sh') != '' | ||
| run: dev/release_artifacts/build.sh "$REF" | ||
|
|
||
| # 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. | ||
| - name: Verify artifacts | ||
| if: steps.build.outputs.files != '' | ||
| run: dev/release_artifacts/verify.sh "$TRIPLE" | ||
|
|
||
| # Stores the files with this workflow run so they can be downloaded from | ||
| # the run's page. Nothing is added to the GitHub release. | ||
| - name: Upload artifacts | ||
| if: steps.build.outputs.files != '' | ||
| uses: actions/upload-artifact@v7 | ||
| with: | ||
| name: release-tools-${{ matrix.triple }} | ||
| path: ${{ steps.build.outputs.files }} | ||
| if-no-files-found: error | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| load("@bazel_skylib//:bzl_library.bzl", "bzl_library") | ||
| load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED") # buildifier: disable=bzl-visibility | ||
| load(":release_files.bzl", "release_files") | ||
|
|
||
| package(default_visibility = ["//:__subpackages__"]) | ||
|
|
||
| # Files that the release workflow builds for each platform; see build.sh. | ||
| release_files( | ||
| name = "artifacts_for_release", | ||
| srcs = ["//crates/exe_zip_maker"], | ||
| # Under WORKSPACE, rules_rust is a stub without the rustc flags setting | ||
| # that release_files sets, so building this would fail. | ||
| tags = [] if BZLMOD_ENABLED else ["manual"], | ||
| ) | ||
|
|
||
| bzl_library( | ||
| name = "release_files", | ||
| srcs = ["release_files.bzl"], | ||
| deps = ["//python/private:common_labels"], | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| #!/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. | ||
| # | ||
| # Usage: dev/release_artifacts/build.sh EMBED_LABEL | ||
| set -euo pipefail | ||
|
|
||
| embed_label="$1" | ||
|
|
||
| # The paths below are relative to the workspace root. | ||
| cd "$(dirname "$0")/../.." | ||
|
|
||
| # Keep Git Bash on Windows from rewriting `//foo` labels into paths. | ||
| 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 | ||
| # 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 | ||
| fi | ||
|
|
||
| # The target lists the paths of its files in a manifest; see release_files.bzl. | ||
| if [[ -n "${GITHUB_OUTPUT:-}" ]]; then | ||
| { | ||
| echo "files<<EOF" | ||
| cat bazel-bin/dev/release_artifacts/artifacts_for_release.txt | ||
| echo "EOF" | ||
| } >> "$GITHUB_OUTPUT" | ||
| fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| """Macro to build the files for a release and list where they are.""" | ||
|
|
||
| load("//python/private:common_labels.bzl", "labels") # buildifier: disable=bzl-visibility | ||
|
|
||
| _FEATURES = "//command_line_option:features" | ||
| _RUSTC_FLAGS = "@rules_rust//rust/settings:extra_rustc_flags" | ||
|
|
||
| def _release_transition_impl(settings, attr): | ||
| features = [] | ||
| rustc_flags = [] | ||
| if attr.target_os == "linux": | ||
| # 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. | ||
| rustc_flags = [ | ||
| "-Ctarget-feature=+crt-static", | ||
| "-Clink-arg=-fuse-ld=bfd", | ||
| ] | ||
| elif attr.target_os == "windows": | ||
| # Statically link the C runtime so that the VC++ redistributable isn't | ||
| # required. | ||
| features = ["static_link_msvcrt"] | ||
| rustc_flags = ["-Ctarget-feature=+crt-static"] | ||
| return { | ||
| "//command_line_option:compilation_mode": "opt", | ||
| # Only affects macOS. Without it, the minimum OS version is the build | ||
| # machine's SDK version. | ||
| "//command_line_option:macos_minimum_os": "11.0", | ||
| _FEATURES: settings[_FEATURES] + features, | ||
| _RUSTC_FLAGS: settings[_RUSTC_FLAGS] + rustc_flags, | ||
| } | ||
|
|
||
| _release_transition = transition( | ||
| implementation = _release_transition_impl, | ||
| inputs = [_FEATURES, _RUSTC_FLAGS], | ||
| outputs = [ | ||
| "//command_line_option:compilation_mode", | ||
| "//command_line_option:macos_minimum_os", | ||
| _FEATURES, | ||
| _RUSTC_FLAGS, | ||
| ], | ||
| ) | ||
|
|
||
| def _release_files_impl(ctx): | ||
| manifest = ctx.actions.declare_file(ctx.label.name + ".txt") | ||
| ctx.actions.write( | ||
| output = manifest, | ||
| # End every line with "\n", including the last: `while read` loops skip | ||
| # an unterminated last line, and build.sh adds a line after the paths. | ||
| content = "".join([file.path + "\n" for file in ctx.files.srcs]), | ||
| ) | ||
| return [DefaultInfo(files = depset([manifest] + ctx.files.srcs))] | ||
|
|
||
| _release_files = rule( | ||
| implementation = _release_files_impl, | ||
| attrs = { | ||
| "srcs": attr.label_list( | ||
| allow_files = True, | ||
| cfg = _release_transition, | ||
| doc = "The files to build and list.", | ||
| ), | ||
| "target_os": attr.string( | ||
| doc = "The OS that the files are built for. Set by the macro.", | ||
| ), | ||
| }, | ||
| ) | ||
|
|
||
| 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 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 | ||
| resolve from the workspace root through the `bazel-out` convenience | ||
| symlink. This lets scripts find the files without running `bazel cquery`, | ||
| which re-analyzes the build. | ||
|
|
||
| Args: | ||
| name: The target name. | ||
| srcs: The files to build and list. | ||
| **kwargs: Additional attributes for the rule. | ||
| """ | ||
| _release_files( | ||
|
rickeylev marked this conversation as resolved.
|
||
| name = name, | ||
| srcs = srcs, | ||
| target_os = select({ | ||
| Label("@platforms//os:linux"): "linux", | ||
| labels.PLATFORMS_OS_WINDOWS: "windows", | ||
| "//conditions:default": "", | ||
| }), | ||
| **kwargs | ||
| ) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| #!/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. | ||
| # | ||
| # Usage: dev/release_artifacts/verify.sh TRIPLE | ||
| set -euo pipefail | ||
|
|
||
| triple="$1" | ||
|
|
||
| # The paths below are relative to the workspace root. | ||
| 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" | ||
| exit 1 | ||
| fi | ||
| ;; | ||
| *-apple-darwin) | ||
| minos="$(otool -l "$bin" | awk ' | ||
| $2 == "LC_BUILD_VERSION" || $2 == "LC_VERSION_MIN_MACOSX" { found = 1 } | ||
| found && minos == "" && ($1 == "minos" || $1 == "version") { minos = $2 } | ||
| END { print minos } | ||
| ')" | ||
| if [[ -z "$minos" || "${minos%%.*}" -gt 11 ]]; then | ||
| echo "::error::$bin requires macOS ${minos:-<unknown>}; expected 11 or lower" | ||
| exit 1 | ||
| fi | ||
| ;; | ||
| esac | ||
| done < bazel-bin/dev/release_artifacts/artifacts_for_release.txt |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally I would love the cross compiling happen from one host, that may facilitate supporting more esoteric platforms, as those will likely come from PRs adding cross compiling.