From a354498dbf2916ff48de51f2959e882aa8b6ab6d Mon Sep 17 00:00:00 2001 From: Jolyon Suthers <201621+fenrick@users.noreply.github.com> Date: Wed, 9 Sep 2026 09:46:58 +1000 Subject: [PATCH 1/2] feat: publish Linux ARM64 builds and packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nothing built for aarch64-unknown-linux-gnu, so anyone running this on an ARM server or a Raspberry Pi had no asset at all — not even a tarball. Adds that target to the release matrix, cross-compiled from an x86-64 runner with gcc-aarch64-linux-gnu, and extends the Debian and RPM packaging job to build for both architectures. That job now runs with fail-fast disabled, so one architecture failing cannot cost the release the other's packages. CI checks the new target on every push alongside the existing four. `cargo check` does not link, so it needs no cross-linker; linking is exercised by the release workflow. --- .github/workflows/ci.yml | 3 +++ .github/workflows/release.yml | 37 +++++++++++++++++++++++++++++++---- README.md | 7 +++++-- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23848c3..d921982 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,6 +47,7 @@ jobs: matrix: include: - { target: x86_64-unknown-linux-gnu, os: ubuntu-latest } + - { target: aarch64-unknown-linux-gnu, os: ubuntu-latest } - { target: aarch64-apple-darwin, os: macos-latest } - { target: x86_64-pc-windows-msvc, os: windows-latest } - { target: aarch64-pc-windows-msvc, os: windows-latest } @@ -61,6 +62,8 @@ jobs: with: key: ${{ matrix.target }} + # `check` does not link, so no cross-linker is needed here. Linking is + # exercised by the release workflow. - run: cargo check --all-targets --target ${{ matrix.target }} # Guard the promise the README makes: an ordinary export carries no personal diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f097d6e..d05282c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -42,11 +42,16 @@ jobs: runs-on: ${{ matrix.os }} permissions: contents: write + # Only consulted when building the matching target, so it is harmless on + # the other legs. + env: + CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc strategy: fail-fast: false matrix: include: - { target: x86_64-unknown-linux-gnu, os: ubuntu-latest } + - { target: aarch64-unknown-linux-gnu, os: ubuntu-latest, apt: gcc-aarch64-linux-gnu } - { target: aarch64-apple-darwin, os: macos-latest } - { target: x86_64-pc-windows-msvc, os: windows-latest } - { target: aarch64-pc-windows-msvc, os: windows-latest } @@ -59,6 +64,13 @@ jobs: with: targets: ${{ matrix.target }} + - name: Install cross-linker + if: matrix.apt != '' + run: | + sudo apt-get update + sudo apt-get install --yes --no-install-recommends ${{ matrix.apt }} + + # Builds, archives (.tar.gz on Unix, .zip on Windows), checksums and # uploads to the release in one step. - uses: taiki-e/upload-rust-binary-action@v1 @@ -73,29 +85,46 @@ jobs: # Debian and RPM packages, for the distributions that want one. linux-packages: - name: Linux packages + name: Linux packages (${{ matrix.arch }}) needs: release-please if: needs.release-please.outputs.released == 'true' runs-on: ubuntu-latest permissions: contents: write + env: + CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc + strategy: + # One architecture failing must not cost the release the other's packages. + fail-fast: false + matrix: + include: + - { target: x86_64-unknown-linux-gnu, arch: amd64 } + - { target: aarch64-unknown-linux-gnu, arch: arm64, apt: gcc-aarch64-linux-gnu } steps: - uses: actions/checkout@v7 with: ref: ${{ needs.release-please.outputs.tag }} - uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - name: Install cross-linker + if: matrix.apt != '' + run: | + sudo apt-get update + sudo apt-get install --yes --no-install-recommends ${{ matrix.apt }} - name: Install packaging tools run: cargo install --locked cargo-deb cargo-generate-rpm - name: Build - run: cargo build --release + run: cargo build --release --target ${{ matrix.target }} - name: Build .deb and .rpm run: | - cargo deb --no-build --output dist/ - cargo generate-rpm --output dist/ + cargo deb --no-build --target ${{ matrix.target }} --output dist/ + cargo generate-rpm --target ${{ matrix.target }} --output dist/ - name: Checksums working-directory: dist diff --git a/README.md b/README.md index 4980b7f..20d6eaf 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ plus Debian and RPM packages. See | Platform | Asset | | --- | --- | | Linux x86-64 | `loop-extract-vX.Y.Z-x86_64-unknown-linux-gnu.tar.gz`, `.deb`, `.rpm` | +| Linux ARM64 | `loop-extract-vX.Y.Z-aarch64-unknown-linux-gnu.tar.gz`, `.deb`, `.rpm` | | macOS Apple Silicon | `loop-extract-vX.Y.Z-aarch64-apple-darwin.tar.gz` | | Windows x86-64 | `loop-extract-vX.Y.Z-x86_64-pc-windows-msvc.zip` | | Windows ARM64 | `loop-extract-vX.Y.Z-aarch64-pc-windows-msvc.zip` | @@ -45,10 +46,12 @@ sha256sum -c loop-extract-vX.Y.Z-x86_64-unknown-linux-gnu.tar.gz.sha256 ### Linux ```bash -sudo dpkg -i loop-extract_X.Y.Z-1_amd64.deb # Debian, Ubuntu -sudo rpm -i loop-extract-X.Y.Z-1.x86_64.rpm # Fedora, RHEL, openSUSE +sudo dpkg -i loop-extract_X.Y.Z-1_amd64.deb # Debian, Ubuntu +sudo rpm -i loop-extract-X.Y.Z-1.x86_64.rpm # Fedora, RHEL, openSUSE ``` +Replace `amd64` with `arm64`, or `x86_64` with `aarch64`, on ARM hardware. + Or extract the tarball and put the binary on your `PATH`. ### macOS From d3ba73bf357b75bac95ce45151015709a9040f89 Mon Sep 17 00:00:00 2001 From: Jolyon Suthers <201621+fenrick@users.noreply.github.com> Date: Wed, 9 Sep 2026 09:47:10 +1000 Subject: [PATCH 2/2] fix: keep runner paths out of published binaries The 1.0.0 binaries each carry 49 absolute paths from the CI runner, embedded in panic messages by file!() expansions in the toolchain and dependency sources. `strip = true` removes debug symbols but not these. CONTRIBUTING.md already told anyone building a binary by hand to remap paths first; the release workflow did not do it itself. It does now, on every target, resolving the home directory through cygpath on Windows so the prefix matches the native path rustc records. --- .github/workflows/release.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d05282c..942fd82 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -70,6 +70,20 @@ jobs: sudo apt-get update sudo apt-get install --yes --no-install-recommends ${{ matrix.apt }} + - name: Keep runner paths out of the binary + shell: bash + run: | + # Panic messages otherwise embed the runner's home directory, which + # reaches every published binary via the toolchain and registry paths + # baked in by file!(). CONTRIBUTING.md documents the same step for + # local release builds. + if [ "$RUNNER_OS" = "Windows" ]; then + home=$(cygpath -w "$HOME") + else + home="$HOME" + fi + echo "RUSTFLAGS=--remap-path-prefix=$home=." >> "$GITHUB_ENV" + # Builds, archives (.tar.gz on Unix, .zip on Windows), checksums and # uploads to the release in one step. @@ -115,6 +129,20 @@ jobs: sudo apt-get update sudo apt-get install --yes --no-install-recommends ${{ matrix.apt }} + - name: Keep runner paths out of the binary + shell: bash + run: | + # Panic messages otherwise embed the runner's home directory, which + # reaches every published binary via the toolchain and registry paths + # baked in by file!(). CONTRIBUTING.md documents the same step for + # local release builds. + if [ "$RUNNER_OS" = "Windows" ]; then + home=$(cygpath -w "$HOME") + else + home="$HOME" + fi + echo "RUSTFLAGS=--remap-path-prefix=$home=." >> "$GITHUB_ENV" + - name: Install packaging tools run: cargo install --locked cargo-deb cargo-generate-rpm