112 lines
4.3 KiB
Bash
Executable file
112 lines
4.3 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Build the entire W65816 runtime — assemble *.s, compile *.c.
|
|
# Run after editing anything under runtime/src/.
|
|
|
|
set -euo pipefail
|
|
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
LLVM_MC="$PROJECT_ROOT/tools/llvm-mos-build/bin/llvm-mc"
|
|
CLANG="$PROJECT_ROOT/tools/llvm-mos-build/bin/clang"
|
|
# Apply CPU/memory caps so a runaway backend bug can't OOM-kill the
|
|
# entire tmux scope. Use `|| true` so when invoked from a parent that
|
|
# has already lowered the limit (e.g. smokeTest.sh sets 90s), we keep
|
|
# the parent's tighter cap rather than failing the build.
|
|
ulimit -v $((10 * 1024 * 1024)) 2>/dev/null || true
|
|
ulimit -t 1200 2>/dev/null || true
|
|
|
|
[ -x "$LLVM_MC" ] || { echo "llvm-mc not found at $LLVM_MC" >&2; exit 1; }
|
|
[ -x "$CLANG" ] || { echo "clang not found at $CLANG" >&2; exit 1; }
|
|
|
|
SRC="$PROJECT_ROOT/runtime/src"
|
|
OUT="$PROJECT_ROOT/runtime"
|
|
|
|
asm() {
|
|
local s="$1"
|
|
local o="$OUT/$(basename "${s%.s}").o"
|
|
echo " AS $(basename "$s")"
|
|
"$LLVM_MC" -arch=w65816 -filetype=obj "$s" -o "$o"
|
|
}
|
|
|
|
cc() {
|
|
local c="$1"
|
|
local o="$OUT/$(basename "${c%.c}").o"
|
|
local extra=("${@:2}")
|
|
echo " CC $(basename "$c")"
|
|
"$CLANG" -target w65816 -O2 -ffunction-sections \
|
|
"${extra[@]}" \
|
|
-I"$PROJECT_ROOT/runtime/include" \
|
|
-c "$c" -o "$o"
|
|
}
|
|
|
|
asm "$SRC/crt0.s"
|
|
asm "$SRC/crt0Gsos.s"
|
|
asm "$SRC/crt0Gno.s"
|
|
asm "$SRC/gnoKernel.s"
|
|
asm "$SRC/gnoGsos.s"
|
|
cc "$SRC/libcGno.c"
|
|
asm "$SRC/libgcc.s"
|
|
cc "$SRC/libc.c"
|
|
cc "$SRC/strtol.c"
|
|
cc "$SRC/snprintf.c"
|
|
# Float-less snprintf for smoke checks that overshoot the single-bank
|
|
# IIgs IO window at $C000-$CFFF. Same source file, gated by
|
|
# LLVM816_NO_FLOAT_PRINTF — skips emitDouble / emitHexFloat / decodeDouble
|
|
# / emitInfNan AND the float dispatch arms in format(), so the linker
|
|
# drops the softFloat / softDouble pull-in entirely.
|
|
echo " CC snprintf.c (no-float)"
|
|
"$CLANG" -target w65816 -O2 -ffunction-sections -DLLVM816_NO_FLOAT_PRINTF \
|
|
-I"$PROJECT_ROOT/runtime/include" \
|
|
-c "$SRC/snprintf.c" -o "$OUT/snprintfNoFloat.o"
|
|
cc "$SRC/sscanf.c"
|
|
cc "$SRC/qsort.c"
|
|
cc "$SRC/extras.c"
|
|
cc "$SRC/strtok.c"
|
|
cc "$SRC/timeExt.c"
|
|
cc "$SRC/math.c"
|
|
cc "$SRC/softFloat.c"
|
|
cc "$SRC/libcxxabi.c"
|
|
cc "$SRC/libcxxabiSjlj.c"
|
|
cc "$SRC/libunwindStub.c"
|
|
cc "$SRC/desktop.c"
|
|
cc "$SRC/sound.c"
|
|
cc "$SRC/cursor.c"
|
|
cc "$SRC/sprite.c"
|
|
cc "$SRC/eventLoop.c"
|
|
cc "$SRC/uiBuilder.c"
|
|
# resource.c is Phase 3.4 STUB-ONLY: bundler + linker integration ship,
|
|
# runtime LoadResource() returns RES_ERR_BLOCKED until Phase 1.1 (GS/OS
|
|
# fopen hang) lands. Build it unconditionally so the typed-C facade
|
|
# links from any demo; the body is a 2-instruction stub today.
|
|
cc "$SRC/resource.c"
|
|
asm "$SRC/iigsGsos.s"
|
|
asm "$SRC/iigsToolbox.s"
|
|
# softDouble.c builds at -O2. dpack is noinline to dodge a backend
|
|
# stack-slot aliasing bug; dclass stays inline because pointer-arg
|
|
# stores from a noinline boundary use DBR-relative addressing (broken
|
|
# under DBR != 0). Both choices documented in the source.
|
|
cc "$SRC/softDouble.c"
|
|
|
|
# Phase 6.2 UBSan-min runtime. MUST be compiled with
|
|
# `-fno-sanitize=undefined` — without that, the handlers would self-
|
|
# instrument on every integer op and recurse infinitely the first time
|
|
# UBSan fires. Routed via the existing cc() helper but with the extra
|
|
# flag appended. Built unconditionally so any user passing
|
|
# `-fsanitize=undefined -fsanitize-minimal-runtime` to their compile +
|
|
# `runtime/ubsan.o` to their link gets a fully-resolved symbol set.
|
|
cc "$SRC/ubsan.c" -fno-sanitize=undefined
|
|
|
|
# Emit a manifest listing every .o this build produced. CMake (Phase
|
|
# 2.6 of the gap-closure plan) consumes this as the single source of
|
|
# truth for the runtime object list, so a `file(GLOB)` in CMake doesn't
|
|
# pick up stale .bak files or out-of-tree leftovers. One basename per
|
|
# line (no path, no extension); sorted for diff-stability.
|
|
MANIFEST="$OUT/.runtime-imports.list"
|
|
{
|
|
echo "# runtime object manifest — produced by runtime/build.sh"
|
|
echo "# Format: one .o filename per line (relative to runtime/)."
|
|
echo "# Single source of truth for the W65816 runtime object set."
|
|
echo "# Do not edit by hand; rerun runtime/build.sh to regenerate."
|
|
ls -1 "$OUT"/*.o 2>/dev/null | xargs -n1 basename | sort
|
|
} >"$MANIFEST"
|
|
|
|
echo "runtime built: $(ls -1 "$OUT"/*.o | wc -l) objects"
|
|
echo "manifest: $MANIFEST"
|