ci: anchor rolling-bootstrap at v0.12.0 (native default, no QBE/gcc)
v0.12.0 is the clean rolling-bootstrap anchor — the broken v0.11.0->v0.12.0 commit range sits before it, so the replay range (v0.12.0..HEAD) is entirely native-default with the internal assembler + linker and needs no external tools. scripts/rolling-bootstrap.sh: - build_step / smoke_test now compile straight to an executable with the native default backend (`--source ... --output ...`): no --emit-ir, no QBE, no gcc. - Dropped the QBE_BIN requirement and the QBE= make var from the RTL build. .github/workflows/bootstrap.yml: - STAGE1_TAG v0.10.0 -> v0.12.0 (the new cold-start anchor). - Removed the "Build QBE" and "Expose QBE to the compiler" steps and the QBE= make var from the -pre RTL rebuild — the bootstrap chain no longer needs them. - Branch-scoped validate-only triggers (ci/**, feature/**, bootstrap/**) and master-only cache writes were already in place (Step 3d-bis). These reference the v0.12.0 tag/release asset, which the cut creates next.
This commit is contained in:
parent
a873bc8ef9
commit
6c38672be3
36
.github/workflows/bootstrap.yml
vendored
36
.github/workflows/bootstrap.yml
vendored
|
|
@ -38,7 +38,10 @@ permissions:
|
|||
env:
|
||||
# Cold-start anchor: the newest *real* release whose binary is published as a
|
||||
# GitHub Release asset. Used only when no cached -pre binary is available.
|
||||
STAGE1_TAG: v0.10.0
|
||||
# v0.12.0 is the clean rolling-bootstrap anchor: the broken v0.11.0->v0.12.0
|
||||
# commit range is BEFORE it, so the replay range (v0.12.0..HEAD) is all
|
||||
# native-default + internal-toolchain and needs neither QBE nor gcc.
|
||||
STAGE1_TAG: v0.12.0
|
||||
|
||||
jobs:
|
||||
bootstrap:
|
||||
|
|
@ -56,35 +59,16 @@ jobs:
|
|||
fetch-depth: 0
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# 2. Toolchain. The runner needs gcc + make to build QBE and link the
|
||||
# bootstrapped compiler. ubuntu-latest already ships both, but install
|
||||
# explicitly so the workflow is self-documenting and resilient.
|
||||
# 2. Toolchain. From the v0.12.0 anchor onward the bootstrap chain is
|
||||
# native-default with the internal assembler + linker, so neither QBE
|
||||
# nor gcc is needed to replay it — only make (runtime Makefile) and the
|
||||
# distro CRT objects (build-essential) the internal linker reads.
|
||||
# --------------------------------------------------------------------
|
||||
- name: Install build tools
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y build-essential unzip
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# 3. Build vendored QBE (source is committed under vendor/qbe/).
|
||||
# rolling-bootstrap.sh and the runtime Makefile both need this binary.
|
||||
# --------------------------------------------------------------------
|
||||
- name: Build QBE
|
||||
run: make -C vendor/qbe
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# 3b. Make the freshly-built QBE discoverable by the *compiler itself*.
|
||||
# The compiler shells out to `qbe` and resolves it via the BLAISE_QBE
|
||||
# env var first, then PATH (see uToolchain.ResolveQBE). The QBE= make
|
||||
# variable only covers rolling-bootstrap.sh's direct qbe calls, NOT
|
||||
# the compiler's internal invocation when building the RTL — so
|
||||
# without this the RTL build fails with "qbe error (exit 127)".
|
||||
# --------------------------------------------------------------------
|
||||
- name: Expose QBE to the compiler
|
||||
run: |
|
||||
echo "BLAISE_QBE=$PWD/vendor/qbe/qbe" >> "$GITHUB_ENV"
|
||||
echo "$PWD/vendor/qbe" >> "$GITHUB_PATH"
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# 4. Restore the carry-forward cache: the previous successful master run
|
||||
# stashes its -pre binary + a marker file recording the commit SHA it
|
||||
|
|
@ -202,8 +186,8 @@ jobs:
|
|||
run: |
|
||||
set -euo pipefail
|
||||
BLAISE="${{ steps.pre.outputs.bin }}"
|
||||
( cd runtime && make BLAISE="$BLAISE" QBE="$PWD/../vendor/qbe/qbe" \
|
||||
&& make BLAISE="$BLAISE" QBE="$PWD/../vendor/qbe/qbe" install )
|
||||
# Native default backend builds the RTL with no external tools.
|
||||
( cd runtime && make BLAISE="$BLAISE" && make BLAISE="$BLAISE" install )
|
||||
|
||||
- name: Install PasBuild
|
||||
run: |
|
||||
|
|
|
|||
|
|
@ -144,16 +144,10 @@ trap cleanup EXIT
|
|||
git worktree add --detach "$WT" "$START_SHA" >/dev/null 2>&1 || {
|
||||
echo "Failed to create worktree." >&2; exit 1; }
|
||||
|
||||
# The worktree checks out vendored QBE *source* but not a built binary. The
|
||||
# runtime Makefile invokes $(QBE) (default ../vendor/qbe/qbe) and we call QBE
|
||||
# directly for the compiler link. Use the main repo's already-built QBE for
|
||||
# both. The QBE binary is stable across the replayed range; if a step bumps the
|
||||
# vendored QBE version, rebuild vendor/qbe in the main repo before replaying.
|
||||
QBE_BIN="$ROOT/vendor/qbe/qbe"
|
||||
if [ ! -x "$QBE_BIN" ]; then
|
||||
echo "QBE binary not built: $QBE_BIN (run 'make' in vendor/qbe)" >&2
|
||||
exit 1
|
||||
fi
|
||||
# From v0.12.0 onward the native backend is the default and the compiler links
|
||||
# via its internal assembler + internal linker, so no QBE binary and no gcc are
|
||||
# needed to replay the bootstrap chain. Only the distro's CRT objects (read by
|
||||
# the internal linker) are required, which the runtime depends on anyway.
|
||||
|
||||
# CUR_BIN / CUR_RTL hold the most recently built (or starting) artifacts.
|
||||
CUR_BIN="$START_BIN"
|
||||
|
|
@ -172,9 +166,10 @@ build_step() {
|
|||
|
||||
# 1. Build + install the RTL using the previous-step compiler.
|
||||
# runtime/Makefile honours BLAISE=<compiler> and COMPILER_BIN for install.
|
||||
# The native default backend builds the RTL units with no external tools.
|
||||
if ! ( cd "$wt/runtime" && make clean >/dev/null 2>&1 && \
|
||||
make BLAISE="$cc" QBE="$QBE_BIN" >"$out/rtl.log" 2>&1 && \
|
||||
make BLAISE="$cc" QBE="$QBE_BIN" install >>"$out/rtl.log" 2>&1 ); then
|
||||
make BLAISE="$cc" >"$out/rtl.log" 2>&1 && \
|
||||
make BLAISE="$cc" install >>"$out/rtl.log" 2>&1 ); then
|
||||
echo " RTL build failed:"; tail -8 "$out/rtl.log" | sed 's/^/ /'
|
||||
return 1
|
||||
fi
|
||||
|
|
@ -185,31 +180,23 @@ build_step() {
|
|||
echo " RTL archive missing after build"; return 1
|
||||
fi
|
||||
|
||||
# 2. Compile the compiler to IR with the previous-step binary, then
|
||||
# assemble + link. Mirrors fixpoint.sh's direct-invocation approach so we
|
||||
# do not depend on pasbuild internals varying across history.
|
||||
# 2. Compile the compiler with the previous-step binary straight to an
|
||||
# executable. Native default backend + internal assembler + internal
|
||||
# linker: source in, binary out, no --emit-ir, no QBE, no gcc. Valid for
|
||||
# the whole v0.12.0..HEAD range (every commit is native-default).
|
||||
if ! "$cc" --source "$wt/compiler/src/main/pascal/Blaise.pas" \
|
||||
--unit-path "$wt/compiler/src/main/pascal" \
|
||||
--unit-path "$wt/runtime/src/main/pascal" \
|
||||
--unit-path "$wt/stdlib/src/main/pascal" \
|
||||
--emit-ir > "$out/blaise.ssa" 2>"$out/compile.err"; then
|
||||
echo " compiler IR generation failed:"; head -5 "$out/compile.err" | sed 's/^/ /'
|
||||
--output "$out/blaise" 2>"$out/compile.err"; then
|
||||
echo " compiler build failed:"; head -5 "$out/compile.err" | sed 's/^/ /'
|
||||
return 1
|
||||
fi
|
||||
if [ ! -s "$out/blaise.ssa" ] || \
|
||||
head -1 "$out/blaise.ssa" | grep -qiE 'error|exception'; then
|
||||
echo " compiler IR invalid:"; head -3 "$out/blaise.ssa" | sed 's/^/ /'
|
||||
head -3 "$out/compile.err" | sed 's/^/ /'
|
||||
if [ ! -s "$out/blaise" ]; then
|
||||
echo " compiler binary missing after build:"; head -3 "$out/compile.err" | sed 's/^/ /'
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! "$QBE_BIN" -o "$out/blaise.s" "$out/blaise.ssa" 2>"$out/qbe.err"; then
|
||||
echo " QBE failed:"; head -5 "$out/qbe.err" | sed 's/^/ /'; return 1
|
||||
fi
|
||||
if ! gcc -o "$out/blaise" "$out/blaise.s" "$rtl" 2>"$out/gcc.err"; then
|
||||
echo " link failed:"; head -5 "$out/gcc.err" | sed 's/^/ /'; return 1
|
||||
fi
|
||||
|
||||
cp "$rtl" "$out/blaise_rtl.a"
|
||||
return 0
|
||||
}
|
||||
|
|
@ -217,9 +204,10 @@ build_step() {
|
|||
# ---------------------------------------------------------------------------
|
||||
# smoke_test <compiler-binary> <rtl-archive>
|
||||
# Compiles + runs a trivial program to prove the freshly-built binary is
|
||||
# functional (compiles → valid QBE → links → runs → correct stdout). Kept
|
||||
# deliberately feature-agnostic: it must pass at EVERY commit in history, so
|
||||
# it probes only arithmetic + WriteLn, not any specific later feature.
|
||||
# functional (source -> native backend -> internal assembler + linker ->
|
||||
# runs -> correct stdout). Kept deliberately feature-agnostic: it must pass
|
||||
# at EVERY commit in the replay range, so it probes only arithmetic + WriteLn,
|
||||
# not any specific later feature.
|
||||
# ---------------------------------------------------------------------------
|
||||
smoke_test() {
|
||||
local cc="$1" rtl="$2"
|
||||
|
|
@ -232,10 +220,11 @@ begin
|
|||
WriteLn(X)
|
||||
end.
|
||||
PAS
|
||||
# FindRTL looks beside the compiler binary; ensure the matching archive is
|
||||
# there so the internal linker finds it.
|
||||
cp "$rtl" "$(dirname "$cc")/blaise_rtl.a" 2>/dev/null || true
|
||||
local ok=1
|
||||
if "$cc" --source "$d/s.pas" --emit-ir > "$d/s.ssa" 2>"$d/s.err" \
|
||||
&& "$QBE_BIN" -o "$d/s.s" "$d/s.ssa" 2>>"$d/s.err" \
|
||||
&& gcc -o "$d/s" "$d/s.s" "$rtl" 2>>"$d/s.err"; then
|
||||
if "$cc" --source "$d/s.pas" --output "$d/s" 2>"$d/s.err"; then
|
||||
[ "$("$d/s" 2>/dev/null)" = "42" ] && ok=0
|
||||
fi
|
||||
rm -rf "$d"
|
||||
|
|
|
|||
Loading…
Reference in a new issue