Skip to content

Commit d51faca

Browse files
committed
ci: extract shared cross-build into a reusable workflow
The 22-arch musl build matrix and per-arch steps were duplicated across build.yml and release.yml. Move them into a single reusable workflow (_cross-build.yml, workflow_call) so the released arch set lives in one place and the two callers can't drift. build.yml's cross-compile and release.yml's build-release now just call it: build with package=false (compile gate), release with package=true (the reusable workflow native-tests x86_64, tarballs, and uploads artifacts). No change to what's built or shipped.
1 parent 73da508 commit d51faca

3 files changed

Lines changed: 150 additions & 176 deletions

File tree

.github/workflows/_cross-build.yml

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
name: _cross-build
2+
3+
# Reusable: build kasld for every supported musl architecture (the matrix below
4+
# fans out one job per arch). This is the SINGLE source of the released arch set
5+
# — build.yml (compile-gate, package=false) and release.yml (package=true)
6+
# both call it, so the two can't drift.
7+
#
8+
# Toolchains come from cross-tools/musl-cross GitHub Releases (musl.cc blocks
9+
# GitHub Actions), broad enough to cover every arch kasld targets — including
10+
# loongarch64, which musl.cc never provided. armeb is omitted: cross-tools/
11+
# musl-cross ships no big-endian-ARM toolchain.
12+
13+
on:
14+
workflow_call:
15+
inputs:
16+
toolchain_version:
17+
description: 'cross-tools/musl-cross release tag to build against'
18+
required: true
19+
type: string
20+
package:
21+
description: 'release mode: native-test x86_64, tarball + upload artifacts'
22+
required: false
23+
default: false
24+
type: boolean
25+
26+
jobs:
27+
build:
28+
runs-on: ubuntu-latest
29+
strategy:
30+
fail-fast: false
31+
matrix:
32+
# arch: friendly name (job label + tarball / artifact name).
33+
# musl_triple: cross-tools/musl-cross triple — the tar.xz stem, the
34+
# extracted dir name, and the <triple>-gcc prefix.
35+
# The float/baseline variants (i586, armhf, armv7, mipssf, ...) compile
36+
# the same kasld as their base arch, but each is a distinct shipped
37+
# toolchain, so the gate builds them too.
38+
include:
39+
# --- x86 ---
40+
- { arch: x86_64, musl_triple: x86_64-unknown-linux-musl, native_test: true }
41+
- { arch: i686, musl_triple: i686-unknown-linux-musl }
42+
- { arch: i586, musl_triple: i586-unknown-linux-musl }
43+
# --- ARM (soft/hard float, v6/v7) ---
44+
- { arch: aarch64, musl_triple: aarch64-unknown-linux-musl }
45+
- { arch: arm, musl_triple: arm-unknown-linux-musleabi }
46+
- { arch: armhf, musl_triple: arm-unknown-linux-musleabihf }
47+
- { arch: armv7, musl_triple: armv7-unknown-linux-musleabi }
48+
- { arch: armv7l, musl_triple: armv7-unknown-linux-musleabihf }
49+
# --- MIPS (hard/soft float, BE/LE) ---
50+
- { arch: mips, musl_triple: mips-unknown-linux-musl }
51+
- { arch: mipssf, musl_triple: mips-unknown-linux-muslsf }
52+
- { arch: mipsel, musl_triple: mipsel-unknown-linux-musl }
53+
- { arch: mipselsf, musl_triple: mipsel-unknown-linux-muslsf }
54+
- { arch: mips64, musl_triple: mips64-unknown-linux-musl }
55+
- { arch: mips64el, musl_triple: mips64el-unknown-linux-musl }
56+
# --- POWER (32/64, BE/LE) ---
57+
- { arch: powerpc, musl_triple: powerpc-unknown-linux-musl }
58+
- { arch: powerpcle, musl_triple: powerpcle-unknown-linux-musl }
59+
- { arch: powerpc64, musl_triple: powerpc64-unknown-linux-musl }
60+
- { arch: powerpc64le, musl_triple: powerpc64le-unknown-linux-musl }
61+
# --- RISC-V (32/64) ---
62+
- { arch: riscv32, musl_triple: riscv32-unknown-linux-musl }
63+
- { arch: riscv64, musl_triple: riscv64-unknown-linux-musl }
64+
# --- s390x ---
65+
- { arch: s390x, musl_triple: s390x-ibm-linux-musl }
66+
# --- LoongArch ---
67+
- { arch: loongarch64, musl_triple: loongarch64-unknown-linux-musl }
68+
steps:
69+
- uses: actions/checkout@v6
70+
71+
- name: Cache toolchain
72+
uses: actions/cache@v4
73+
with:
74+
path: ~/musl-cross/${{ matrix.musl_triple }}
75+
key: musl-${{ matrix.musl_triple }}-${{ inputs.toolchain_version }}
76+
77+
- name: Fetch toolchain + add to PATH
78+
run: |
79+
set -euo pipefail
80+
t="${{ matrix.musl_triple }}"
81+
root="$HOME/musl-cross"; mkdir -p "$root"
82+
if [ ! -d "$root/$t" ]; then
83+
base="https://github.com/cross-tools/musl-cross/releases/download/${{ inputs.toolchain_version }}"
84+
dl() { curl -fsSL --retry 5 --retry-delay 5 --retry-all-errors "$1" -o "$2"; }
85+
dl "${base}/${t}.tar.xz" "/tmp/${t}.tar.xz"
86+
dl "${base}/${t}.tar.xz.sha256" "/tmp/${t}.sha256"
87+
# The .sha256 holds only the bare digest; pair it with the filename.
88+
echo "$(cut -d' ' -f1 "/tmp/${t}.sha256") /tmp/${t}.tar.xz" | sha256sum -c -
89+
tar -xJf "/tmp/${t}.tar.xz" -C "$root"
90+
fi
91+
echo "$root/$t/bin" >> "$GITHUB_PATH"
92+
93+
- name: Build
94+
run: make build CC=${{ matrix.musl_triple }}-gcc
95+
96+
- name: Identify build directory
97+
id: builddir
98+
run: echo "dir=build/$(${{ matrix.musl_triple }}-gcc -dumpmachine)" >> "$GITHUB_OUTPUT"
99+
100+
- name: Verify static linkage
101+
run: |
102+
file "${{ steps.builddir.outputs.dir }}/kasld"
103+
file "${{ steps.builddir.outputs.dir }}/kasld" | grep -q "statically linked"
104+
105+
# Release mode only: x86_64 runs natively on the runner. (PR coverage
106+
# tests x86_64 via build.yml's host job, so this would be redundant there.)
107+
- name: Run tests (native, x86_64)
108+
if: inputs.package && matrix.native_test
109+
run: make test CC=${{ matrix.musl_triple }}-gcc
110+
111+
- name: Package release tarball
112+
if: inputs.package
113+
run: |
114+
set -euo pipefail
115+
TAG="${GITHUB_REF_NAME}"
116+
DIR="kasld-${TAG}-${{ matrix.arch }}"
117+
mkdir -p "${DIR}"
118+
# Ship the build/<arch> output (kasld + components/), minus the .o
119+
# build intermediates.
120+
cp -a "${{ steps.builddir.outputs.dir }}/." "${DIR}/"
121+
find "${DIR}" -name '*.o' -delete
122+
cp README.md LICENSE "${DIR}/"
123+
tar czf "${DIR}.tar.gz" "${DIR}"
124+
sha256sum "${DIR}.tar.gz" > "${DIR}.tar.gz.sha256"
125+
126+
- name: Upload artifact
127+
if: inputs.package
128+
uses: actions/upload-artifact@v5
129+
with:
130+
name: kasld-${{ matrix.arch }}
131+
path: |
132+
kasld-*-${{ matrix.arch }}.tar.gz
133+
kasld-*-${{ matrix.arch }}.tar.gz.sha256

.github/workflows/build.yml

Lines changed: 8 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -34,73 +34,12 @@ jobs:
3434
- name: End-to-end replay (x86, native)
3535
run: KASLD_NATIVE=1 tests/replay tests/fixtures/x86_64/* tests/fixtures/x86_32/*
3636

37-
# Compile-gate every arch we release, on push/PR. Same musl toolchains
38-
# release.yml ships (musl.cc blocks GitHub Actions), minus packaging — so a
39-
# per-arch toolchain or arch-gated-code break is caught here, not at release.
37+
# Compile-gate every released arch on push/PR (matrix + steps in
38+
# _cross-build.yml, shared with release.yml so the arch set can't drift).
39+
# Pinned for deterministic PR builds + a stable cache; bump periodically.
40+
# release.yml tracks the latest cross-tools release instead.
4041
cross-compile:
41-
runs-on: ubuntu-latest
42-
# Pinned for deterministic PR builds + a stable per-arch toolchain cache;
43-
# bump periodically. release.yml tracks the latest cross-tools release.
44-
env:
45-
MUSL_CROSS_VERSION: '20260515'
46-
strategy:
47-
fail-fast: false
48-
matrix:
49-
# KEEP IN SYNC with release.yml's build-release matrix. armeb (big-endian
50-
# ARM) is omitted in both — cross-tools/musl-cross ships no armeb
51-
# toolchain. (The float/baseline variants compile identically to their
52-
# base arch, but are built here too so every shipped toolchain is gated.)
53-
include:
54-
- { arch: x86_64, musl_triple: x86_64-unknown-linux-musl }
55-
- { arch: i686, musl_triple: i686-unknown-linux-musl }
56-
- { arch: i586, musl_triple: i586-unknown-linux-musl }
57-
- { arch: aarch64, musl_triple: aarch64-unknown-linux-musl }
58-
- { arch: arm, musl_triple: arm-unknown-linux-musleabi }
59-
- { arch: armhf, musl_triple: arm-unknown-linux-musleabihf }
60-
- { arch: armv7, musl_triple: armv7-unknown-linux-musleabi }
61-
- { arch: armv7l, musl_triple: armv7-unknown-linux-musleabihf }
62-
- { arch: mips, musl_triple: mips-unknown-linux-musl }
63-
- { arch: mipssf, musl_triple: mips-unknown-linux-muslsf }
64-
- { arch: mipsel, musl_triple: mipsel-unknown-linux-musl }
65-
- { arch: mipselsf, musl_triple: mipsel-unknown-linux-muslsf }
66-
- { arch: mips64, musl_triple: mips64-unknown-linux-musl }
67-
- { arch: mips64el, musl_triple: mips64el-unknown-linux-musl }
68-
- { arch: powerpc, musl_triple: powerpc-unknown-linux-musl }
69-
- { arch: powerpcle, musl_triple: powerpcle-unknown-linux-musl }
70-
- { arch: powerpc64, musl_triple: powerpc64-unknown-linux-musl }
71-
- { arch: powerpc64le, musl_triple: powerpc64le-unknown-linux-musl }
72-
- { arch: riscv32, musl_triple: riscv32-unknown-linux-musl }
73-
- { arch: riscv64, musl_triple: riscv64-unknown-linux-musl }
74-
- { arch: s390x, musl_triple: s390x-ibm-linux-musl }
75-
- { arch: loongarch64, musl_triple: loongarch64-unknown-linux-musl }
76-
steps:
77-
- uses: actions/checkout@v6
78-
79-
- name: Cache toolchain
80-
uses: actions/cache@v4
81-
with:
82-
path: ~/musl-cross/${{ matrix.musl_triple }}
83-
key: musl-${{ matrix.musl_triple }}-${{ env.MUSL_CROSS_VERSION }}
84-
85-
- name: Fetch toolchain + add to PATH
86-
run: |
87-
set -euo pipefail
88-
t="${{ matrix.musl_triple }}"
89-
root="$HOME/musl-cross"; mkdir -p "$root"
90-
if [ ! -d "$root/$t" ]; then
91-
base="https://github.com/cross-tools/musl-cross/releases/download/${MUSL_CROSS_VERSION}"
92-
dl() { curl -fsSL --retry 5 --retry-delay 5 --retry-all-errors "$1" -o "$2"; }
93-
dl "${base}/${t}.tar.xz" "/tmp/${t}.tar.xz"
94-
dl "${base}/${t}.tar.xz.sha256" "/tmp/${t}.sha256"
95-
echo "$(cut -d' ' -f1 "/tmp/${t}.sha256") /tmp/${t}.tar.xz" | sha256sum -c -
96-
tar -xJf "/tmp/${t}.tar.xz" -C "$root"
97-
fi
98-
echo "$root/$t/bin" >> "$GITHUB_PATH"
99-
100-
- name: Compile
101-
run: make build CC=${{ matrix.musl_triple }}-gcc
102-
103-
- name: Verify static linkage
104-
run: |
105-
d="build/$(${{ matrix.musl_triple }}-gcc -dumpmachine)"
106-
file "$d/kasld" | grep -q "statically linked"
42+
uses: ./.github/workflows/_cross-build.yml
43+
with:
44+
toolchain_version: '20260515'
45+
package: false

.github/workflows/release.yml

Lines changed: 9 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
name: release
22

3-
# Cross-compiled static release binaries, one per architecture.
4-
#
5-
# Toolchains come from cross-tools/musl-cross GitHub Releases
6-
# (https://github.com/cross-tools/musl-cross/releases): musl, fetched over
7-
# GitHub (musl.cc blocks GitHub Actions), and broad enough to cover every arch
8-
# kasld targets — including loongarch64, which musl.cc never provided.
3+
# Cross-compiled static release binaries, one per architecture. The per-arch
4+
# build matrix + steps live in the reusable _cross-build.yml (shared with
5+
# build.yml's compile gate); this workflow resolves the toolchain version,
6+
# builds + packages in release mode, and publishes the GitHub Release.
97
on:
108
push:
119
tags:
@@ -44,109 +42,13 @@ jobs:
4442
echo "Using cross-tools/musl-cross ${VER}"
4543
echo "version=${VER}" >> "$GITHUB_OUTPUT"
4644
45+
# Build + package every arch (matrix + steps in _cross-build.yml).
4746
build-release:
4847
needs: resolve-toolchain
49-
runs-on: ubuntu-latest
50-
strategy:
51-
fail-fast: false
52-
matrix:
53-
# arch: friendly name, used only in the artifact / tarball name.
54-
# musl_triple: cross-tools/musl-cross triple — the tar.xz stem, the
55-
# extracted directory name, and the <triple>-gcc prefix.
56-
# KEEP IN SYNC with build.yml's cross-compile matrix (which gates the
57-
# same arches on every push/PR). armeb has no cross-tools toolchain.
58-
include:
59-
# --- x86 ---
60-
- { arch: x86_64, musl_triple: x86_64-unknown-linux-musl, native_test: true }
61-
- { arch: i686, musl_triple: i686-unknown-linux-musl }
62-
- { arch: i586, musl_triple: i586-unknown-linux-musl } # older x86 baseline
63-
# --- ARM (soft/hard float, v6/v7) ---
64-
# NOTE: armeb (big-endian ARM) is intentionally omitted — cross-tools/
65-
# musl-cross ships no armeb toolchain. Re-add if a source appears.
66-
- { arch: aarch64, musl_triple: aarch64-unknown-linux-musl }
67-
- { arch: arm, musl_triple: arm-unknown-linux-musleabi } # v6 soft-float
68-
- { arch: armhf, musl_triple: arm-unknown-linux-musleabihf } # v6 hard-float
69-
- { arch: armv7, musl_triple: armv7-unknown-linux-musleabi } # v7 soft-float
70-
- { arch: armv7l, musl_triple: armv7-unknown-linux-musleabihf } # v7 hard-float
71-
# --- MIPS (hard/soft float, BE/LE) ---
72-
- { arch: mips, musl_triple: mips-unknown-linux-musl }
73-
- { arch: mipssf, musl_triple: mips-unknown-linux-muslsf } # soft-float
74-
- { arch: mipsel, musl_triple: mipsel-unknown-linux-musl }
75-
- { arch: mipselsf, musl_triple: mipsel-unknown-linux-muslsf } # soft-float
76-
- { arch: mips64, musl_triple: mips64-unknown-linux-musl }
77-
- { arch: mips64el, musl_triple: mips64el-unknown-linux-musl }
78-
# --- POWER (32/64, BE/LE) ---
79-
- { arch: powerpc, musl_triple: powerpc-unknown-linux-musl } # ppc32 BE
80-
- { arch: powerpcle, musl_triple: powerpcle-unknown-linux-musl } # ppc32 LE
81-
- { arch: powerpc64, musl_triple: powerpc64-unknown-linux-musl }
82-
- { arch: powerpc64le, musl_triple: powerpc64le-unknown-linux-musl }
83-
# --- RISC-V (32/64) ---
84-
- { arch: riscv32, musl_triple: riscv32-unknown-linux-musl }
85-
- { arch: riscv64, musl_triple: riscv64-unknown-linux-musl }
86-
# --- s390x ---
87-
- { arch: s390x, musl_triple: s390x-ibm-linux-musl }
88-
# --- LoongArch ---
89-
- { arch: loongarch64, musl_triple: loongarch64-unknown-linux-musl }
90-
91-
env:
92-
TC_VERSION: ${{ needs.resolve-toolchain.outputs.version }}
93-
94-
steps:
95-
- uses: actions/checkout@v6
96-
97-
- name: Download + verify musl cross-compiler
98-
run: |
99-
set -euo pipefail
100-
base="https://github.com/cross-tools/musl-cross/releases/download/${TC_VERSION}"
101-
tarball="${{ matrix.musl_triple }}.tar.xz"
102-
# Retry: the releases CDN occasionally returns a transient 5xx.
103-
dl() { curl -fsSL --retry 5 --retry-delay 5 --retry-all-errors "$1" -o "$2"; }
104-
dl "${base}/${tarball}" "${tarball}"
105-
dl "${base}/${tarball}.sha256" "${tarball}.sha256"
106-
# The .sha256 file holds only the bare digest, so pair it with the
107-
# local filename before checking.
108-
echo "$(cut -d' ' -f1 "${tarball}.sha256") ${tarball}" | sha256sum -c -
109-
mkdir -p "${RUNNER_TEMP}/toolchain"
110-
tar -xJf "${tarball}" -C "${RUNNER_TEMP}/toolchain"
111-
echo "${RUNNER_TEMP}/toolchain/${{ matrix.musl_triple }}/bin" >> "$GITHUB_PATH"
112-
113-
- name: Build static binaries
114-
run: make build CC=${{ matrix.musl_triple }}-gcc
115-
116-
- name: Identify build directory
117-
id: builddir
118-
run: echo "dir=build/$(${{ matrix.musl_triple }}-gcc -dumpmachine)" >> "$GITHUB_OUTPUT"
119-
120-
- name: Verify static linkage
121-
run: |
122-
file "${{ steps.builddir.outputs.dir }}/kasld"
123-
file "${{ steps.builddir.outputs.dir }}/kasld" | grep -q "statically linked"
124-
125-
- name: Run tests (native only)
126-
if: matrix.native_test
127-
run: make test CC=${{ matrix.musl_triple }}-gcc
128-
129-
- name: Package release tarball
130-
run: |
131-
set -euo pipefail
132-
TAG="${GITHUB_REF_NAME}"
133-
DIR="kasld-${TAG}-${{ matrix.arch }}"
134-
mkdir -p "${DIR}"
135-
# Ship the build/<arch> output (kasld + components/), minus the .o
136-
# build intermediates.
137-
cp -a "${{ steps.builddir.outputs.dir }}/." "${DIR}/"
138-
find "${DIR}" -name '*.o' -delete
139-
cp README.md LICENSE "${DIR}/"
140-
tar czf "${DIR}.tar.gz" "${DIR}"
141-
sha256sum "${DIR}.tar.gz" > "${DIR}.tar.gz.sha256"
142-
143-
- name: Upload artifact
144-
uses: actions/upload-artifact@v5
145-
with:
146-
name: kasld-${{ matrix.arch }}
147-
path: |
148-
kasld-*-${{ matrix.arch }}.tar.gz
149-
kasld-*-${{ matrix.arch }}.tar.gz.sha256
48+
uses: ./.github/workflows/_cross-build.yml
49+
with:
50+
toolchain_version: ${{ needs.resolve-toolchain.outputs.version }}
51+
package: true
15052

15153
create-release:
15254
needs: build-release

0 commit comments

Comments
 (0)