From 08f906f249005015a7f3c55ca790762e579e642f Mon Sep 17 00:00:00 2001 From: frankzhu Date: Tue, 16 Jun 2026 10:27:41 +1000 Subject: [PATCH 1/3] Build ARM64 musl release in Alpine --- .github/workflows/package-preview.yml | 9 +++- .github/workflows/release.yml | 9 +++- scripts/package-release-alpine.sh | 62 +++++++++++++++++++++++++++ scripts/package-release.sh | 20 ++++++++- 4 files changed, 94 insertions(+), 6 deletions(-) create mode 100755 scripts/package-release-alpine.sh diff --git a/.github/workflows/package-preview.yml b/.github/workflows/package-preview.yml index 28ed40f..9834a2d 100644 --- a/.github/workflows/package-preview.yml +++ b/.github/workflows/package-preview.yml @@ -57,7 +57,7 @@ jobs: run: brew install cmake libb2 lz4 xz zstd - name: Install Linux dependencies - if: runner.os == 'Linux' + if: runner.os == 'Linux' && matrix.target != 'aarch64-unknown-linux-musl' run: | sudo apt-get update sudo apt-get install -y \ @@ -72,6 +72,7 @@ jobs: echo /opt/zig >> "$GITHUB_PATH" - name: Install Rust toolchain + if: matrix.target != 'aarch64-unknown-linux-musl' run: | rustup toolchain install stable --profile minimal rustup default stable @@ -83,9 +84,13 @@ jobs: python-version: "3.x" - name: Package Unix - if: runner.os != 'Windows' + if: runner.os != 'Windows' && matrix.target != 'aarch64-unknown-linux-musl' run: scripts/package-release.sh "${{ matrix.target }}" dist + - name: Package Linux ARM64 musl in Alpine + if: matrix.target == 'aarch64-unknown-linux-musl' + run: scripts/package-release-alpine.sh "${{ matrix.target }}" dist + - name: Package Windows if: runner.os == 'Windows' shell: pwsh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0ed355b..d9338ac 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -53,7 +53,7 @@ jobs: run: brew install cmake libb2 lz4 xz zstd - name: Install Linux dependencies - if: runner.os == 'Linux' + if: runner.os == 'Linux' && matrix.target != 'aarch64-unknown-linux-musl' run: | sudo apt-get update sudo apt-get install -y \ @@ -68,6 +68,7 @@ jobs: echo /opt/zig >> "$GITHUB_PATH" - name: Install Rust toolchain + if: matrix.target != 'aarch64-unknown-linux-musl' run: | rustup toolchain install stable --profile minimal rustup default stable @@ -79,9 +80,13 @@ jobs: python-version: "3.x" - name: Package Unix - if: runner.os != 'Windows' + if: runner.os != 'Windows' && matrix.target != 'aarch64-unknown-linux-musl' run: scripts/package-release.sh "${{ matrix.target }}" dist + - name: Package Linux ARM64 musl in Alpine + if: matrix.target == 'aarch64-unknown-linux-musl' + run: scripts/package-release-alpine.sh "${{ matrix.target }}" dist + - name: Package Windows if: runner.os == 'Windows' shell: pwsh diff --git a/scripts/package-release-alpine.sh b/scripts/package-release-alpine.sh new file mode 100755 index 0000000..90f6396 --- /dev/null +++ b/scripts/package-release-alpine.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [[ $# -lt 1 || $# -gt 2 ]]; then + echo "usage: scripts/package-release-alpine.sh [out-dir]" >&2 + exit 2 +fi + +TARGET=$1 +OUT_DIR=${2:-dist} +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +IMAGE=${ZM_ALPINE_RUST_IMAGE:-rust:1-alpine3.22} + +if [[ "$TARGET" != "aarch64-unknown-linux-musl" ]]; then + echo "Alpine packaging is currently supported only for aarch64-unknown-linux-musl" >&2 + exit 2 +fi + +if ! command -v docker >/dev/null 2>&1; then + echo "docker is required for Alpine musl packaging" >&2 + exit 1 +fi + +cd "$ROOT" +mkdir -p "$OUT_DIR" + +docker run --rm \ + --platform linux/arm64 \ + -v "$ROOT:/workspace" \ + -w /workspace \ + -e TARGET="$TARGET" \ + -e OUT_DIR="$OUT_DIR" \ + -e CARGO_HOME=/workspace/target/alpine-cargo \ + -e CARGO_TARGET_DIR=/workspace/target \ + -e HOST_UID="$(id -u)" \ + -e HOST_GID="$(id -g)" \ + -e ZM_USE_SYSTEM_MUSL_TOOLCHAIN=1 \ + "$IMAGE" \ + /bin/sh -lc ' + set -eu + apk add --no-cache \ + bash \ + binutils \ + build-base \ + cmake \ + file \ + linux-headers \ + perl \ + pkgconf \ + python3 + + rustup target add "$TARGET" + + export CC_aarch64_unknown_linux_musl=cc + export CXX_aarch64_unknown_linux_musl=c++ + export AR_aarch64_unknown_linux_musl=ar + export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=cc + + scripts/package-release.sh "$TARGET" "$OUT_DIR" + + chown -R "$HOST_UID:$HOST_GID" "$OUT_DIR" "target/$TARGET" 2>/dev/null || true + ' diff --git a/scripts/package-release.sh b/scripts/package-release.sh index 07615c3..6da0f49 100755 --- a/scripts/package-release.sh +++ b/scripts/package-release.sh @@ -37,13 +37,29 @@ configure_static_linux_target() { ;; esac + local target_env=${TARGET//-/_} + local target_env_upper=${target_env^^} + + if [[ "${ZM_USE_SYSTEM_MUSL_TOOLCHAIN:-}" == "1" ]]; then + local cc_env="CC_${target_env}" + local cxx_env="CXX_${target_env}" + local ar_env="AR_${target_env}" + local cxxstdlib_env="CXXSTDLIB_${target_env}" + local linker_env="CARGO_TARGET_${target_env_upper}_LINKER" + + export "$cc_env=${!cc_env:-${CC:-cc}}" + export "$cxx_env=${!cxx_env:-${CXX:-c++}}" + export "$ar_env=${!ar_env:-${AR:-ar}}" + export "$cxxstdlib_env=${!cxxstdlib_env:-stdc++}" + export "$linker_env=${!linker_env:-${!cc_env}}" + return + fi + if ! command -v zig >/dev/null 2>&1; then echo "zig is required to build static Linux release artifacts for $TARGET" >&2 exit 1 fi - local target_env=${TARGET//-/_} - local target_env_upper=${target_env^^} local tool_dir="$ROOT/target/zmanager-tools/$TARGET" local zig_cc="$tool_dir/zig-cc" local zig_cxx="$tool_dir/zig-cxx" From 591c7aabad6ccd70f2ec6421322e253f289804a8 Mon Sep 17 00:00:00 2001 From: frankzhu Date: Tue, 16 Jun 2026 10:46:47 +1000 Subject: [PATCH 2/3] Remove rustup from Alpine package build --- scripts/package-release-alpine.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/package-release-alpine.sh b/scripts/package-release-alpine.sh index 90f6396..f723ad4 100755 --- a/scripts/package-release-alpine.sh +++ b/scripts/package-release-alpine.sh @@ -49,8 +49,6 @@ docker run --rm \ pkgconf \ python3 - rustup target add "$TARGET" - export CC_aarch64_unknown_linux_musl=cc export CXX_aarch64_unknown_linux_musl=c++ export AR_aarch64_unknown_linux_musl=ar From 5240212e06fd1676e03c60fd62edfdf766de8b7d Mon Sep 17 00:00:00 2001 From: frankzhu Date: Tue, 16 Jun 2026 11:20:59 +1000 Subject: [PATCH 3/3] Fix Alpine release packaging CI --- docs/INSTALL.md | 6 +++--- scripts/package-release-alpine.sh | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index bcf915a..755f478 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -115,9 +115,9 @@ zm completions powershell > zm.ps1 ## Linux Direct Install -Linux release archives are statically linked musl builds. The install script is -the recommended path; use the manual flow when you want to inspect or stage the -tarball yourself. +Linux release archives are statically linked musl builds that run +without installing extra runtime packages. The install script is the recommended +path; use the manual flow when you want to inspect or stage the tarball yourself. ```sh curl -LO https://github.com/tzap-org/zmanager/releases/download/v1.0.4/SHA256SUMS diff --git a/scripts/package-release-alpine.sh b/scripts/package-release-alpine.sh index f723ad4..d9c8c5e 100755 --- a/scripts/package-release-alpine.sh +++ b/scripts/package-release-alpine.sh @@ -36,7 +36,7 @@ docker run --rm \ -e HOST_GID="$(id -g)" \ -e ZM_USE_SYSTEM_MUSL_TOOLCHAIN=1 \ "$IMAGE" \ - /bin/sh -lc ' + /bin/sh -c ' set -eu apk add --no-cache \ bash \