Skip to content
Merged
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
26 changes: 18 additions & 8 deletions .github/workflows/build-binaries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
# Each platform builds from its OWN committed seed (boot/seed_mac / boot/seed_linux), so there is no
# cross-emit and no foreign toolchain — only the system `cc` and the vendored qbe:
# darwin-arm64 → macOS runner, native `build.sh`
# darwin-amd64 → Intel macOS runner (macos-13), native `build.sh darwin-amd64` (shares the mac seed
# IL with arm64 — the amd64 `syscall` class bit lives in the floor, not the IL)
# darwin-amd64 → arm64 macOS runner (macos-14), `build.sh darwin-amd64` CROSS-built via `-arch
# x86_64` (shares the mac seed IL with arm64 — the amd64 `syscall` class bit lives in
# the floor, not the IL). No Intel runner: the last Intel image (macos-13) is being
# retired and its queue is unreliable. The build emits x86-64 without running it; only
# the `--version` verify executes the artifact, under Rosetta 2 (installed below).
# linux-arm64 → ubuntu-arm runner, native `build.sh linux-arm64`
# linux-amd64 → ubuntu x86-64 runner, native `build.sh linux-amd64` (its OWN seed IL — x86-64's
# linux syscall numbers + struct-stat layout differ from the generic arm64/riscv table)
# linux-riscv64 → ubuntu-arm runner, `build.sh linux-riscv64` cross-linked with the distro's
# gcc-riscv64-linux-gnu (shared linux IL, riscv floor)
# linux-riscv64 → ubuntu x86-64 runner, `build.sh linux-riscv64` cross-linked with the x86_64-hosted
# riscv64 musl cross toolchain fetched below (shared linux IL, riscv floor). The runner
# must be x86-64 to MATCH that toolchain's host — an arm runner cannot exec it.
# Every binary is stamped with the release version via lib/std/compiler/buildinfo.cf, so it reports
# itself through `std::comptime::version::compiler`.
#
Expand Down Expand Up @@ -53,7 +57,7 @@ jobs:
target: darwin-arm64
experimental: false
- name: darwin-amd64
runner: macos-13 # macos-13 is the last Intel x86-64 image; macos-14+ are arm64
runner: macos-14 # arm64 runner; darwin-amd64 is cross-built via `-arch x86_64` (build.sh)
target: darwin-amd64
experimental: false
- name: linux-arm64
Expand All @@ -65,9 +69,9 @@ jobs:
target: linux-amd64
experimental: false
- name: linux-riscv64
runner: ubuntu-24.04-arm
target: linux-riscv64
experimental: false
runner: ubuntu-24.04 # x86-64: matches the x86_64-hosted musl cross toolchain (below).
target: linux-riscv64 # A cross-compile — host arch is irrelevant to the riscv output, and
experimental: false # this leg never runs the riscv binary (qemu verify is skipped for it).
continue-on-error: ${{ matrix.experimental }}
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -126,6 +130,12 @@ jobs:
echo "RISCV_CC=riscv64-unknown-linux-musl-gcc" >> "$GITHUB_ENV"
echo "RISCV_STRIP=riscv64-unknown-linux-musl-strip" >> "$GITHUB_ENV"

# darwin-amd64 is cross-built on this arm64 runner; Rosetta 2 lets the `--version` verify below
# actually run the x86-64 artifact. Idempotent (a no-op if Rosetta is already present).
- name: Install Rosetta 2 (run the cross-built x86-64 cf on the arm64 runner)
if: matrix.target == 'darwin-amd64'
run: softwareupdate --install-rosetta --agree-to-license

- name: Build
env:
CF_STRIP: 1 # release binaries are stripped (objects already carry no -g)
Expand Down
18 changes: 6 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# ci — pull-request gate for changes targeting margarita.
#
# Two independent checks run on every PR into margarita:
# corpus — build cf from the committed seed and run the whole corpus suite (boot/test.sh):
# the same end-to-end path a user takes (compile -> embedded QBE -> link -> run),
# every test's exit code matched against its `# expect:` directive.
# One check runs on every PR into margarita:
# format — build cf, then assert every `.cf` under boot/src + lib is already formatted
# (`cf format --check`). A drifted file fails the PR. Scope is the hand-written
# source only: boot/seed_* are emitted IL/asm, boot/vendor is C, and the
# boot/tests/corpus fixtures are deliberately varied.
#
# Both run on macos-14 (arm64): it matches the committed darwin seed and ships `cc`, so no
# The corpus suite is NOT a PR gate — it's the RELEASE gate for the rc/latest/stable rings
# (see release.yml), where it runs per-arch before a release is cut. On a margarita PR,
# formatting is the whole gate for now.
#
# Runs on macos-14 (arm64): it matches the committed darwin seed and ships `cc`, so no
# toolchain install is needed (same runner as release.yml's version job).
name: ci

Expand All @@ -21,13 +22,6 @@ permissions:
contents: read

jobs:
corpus:
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- name: Run the corpus suite
run: ./boot/test.sh

format:
runs-on: macos-14
steps:
Expand Down
45 changes: 41 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,42 @@ permissions:
contents: write

jobs:
# Corpus gate — the rc/latest/stable rings only. Build cf on each natively-runnable arch and run the
# whole corpus (boot/test.sh: compile -> embedded QBE -> link -> run, exit vs `# expect:`) BEFORE any
# release is cut. A failure fails the workflow and the `version` job below never creates a release, so
# a broken build is never published. Nightly (behemoth) SKIPS this so nightly cuts stay fast — the
# corpus never gated nightly. darwin-amd64 (Rosetta-only) and linux-riscv64 (needs qemu) aren't run
# here, but the gate covers their IL transitively — darwin-amd64 shares the mac IL exercised by
# darwin-arm64, riscv the linux IL exercised by linux-arm64 — leaving only their floor asm unrun.
corpus:
if: github.ref_name != 'behemoth'
strategy:
fail-fast: false
matrix:
include:
- arch: darwin-arm64
runner: macos-14
- arch: linux-arm64
runner: ubuntu-24.04-arm
- arch: linux-amd64
runner: ubuntu-24.04
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v4
# Linux: musl-gcc builds cf; clang + ld.lld are what cf itself uses to link the corpus programs it
# compiles (freestanding `-static -e _start` ELF, no libc). darwin needs neither — `cc` covers both.
- name: Install linux toolchain
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y build-essential musl-tools clang lld
- name: Build cf and run the corpus (${{ matrix.arch }})
run: ./boot/test.sh

version:
needs: corpus
# Run when the gate PASSED (rc/latest/stable) or was SKIPPED (nightly) — but not when it FAILED or
# was cancelled. `!cancelled()` lifts the implicit "all needs succeeded" so a skipped gate still
# lets nightly through; `result != 'failure'` is what actually blocks a release on a red corpus.
if: ${{ !cancelled() && needs.corpus.result != 'failure' }}
runs-on: macos-14
outputs:
version: ${{ steps.compute.outputs.version }}
Expand Down Expand Up @@ -130,12 +165,14 @@ jobs:
SHA: ${{ github.sha }}
run: |
set -eu
mkdir dist && cd dist
mkdir dist
# Mirror the just-built versioned binaries under ring-based names, with fresh checksums.
# Everything the rolling release should carry lands in dist/; notes.md stays OUT of it so the
# `dist/*` upload glob picks up only the binaries and their checksums, never the notes.
for name in darwin-arm64 darwin-amd64 linux-arm64 linux-amd64 linux-riscv64; do
if gh release download "$VERSION" -R "$REPO" -p "cf-$VERSION-$name" 2>/dev/null; then
mv "cf-$VERSION-$name" "cf-$RING-$name"
sha256sum "cf-$RING-$name" > "cf-$RING-$name.sha256"
if gh release download "$VERSION" -R "$REPO" -p "cf-$VERSION-$name" -D dist 2>/dev/null; then
mv "dist/cf-$VERSION-$name" "dist/cf-$RING-$name"
( cd dist && sha256sum "cf-$RING-$name" > "cf-$RING-$name.sha256" )
else
echo "note: no cf-$VERSION-$name asset — skipping"
fi
Expand Down
3 changes: 2 additions & 1 deletion boot/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
# (boot/qbe_embed.c) are linked in, so cf translates IL->asm in-process. QBE uses libc; cf's floor owns
# `_start` (freestanding), so we link libc for QBE WITHOUT its crt startup (-lSystem on darwin, static
# -lc on linux). darwin and linux-arm64 build natively from their own seed; linux-riscv64 cross-builds
# on a linux-arm64 host (shared IL, riscv floor, a riscv cross toolchain for QBE's C).
# on any linux host (x86-64 in CI, to match the x86_64-hosted riscv cross toolchain) — shared IL, riscv
# floor, a riscv cross toolchain for QBE's C. The cross toolchain's host arch must match the runner.
#
# After editing cf's `.cf` source, regenerate BOTH seeds with boot/reseed.sh, then commit them.
set -eu
Expand Down
Loading
Loading