commit 7c103f48b35e13efa8aafa4fb2c49a5a50a257dd
parent 7a40928766648342fc82fb107a508408ff2908f6
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Tue, 5 May 2026 13:03:07 -0700
move build/tcc/<TCC_TARGET>/ -> build/<arch>/vendor/tcc/
Per-arch tcc artifacts (flattened TU, unpacked source tree, stdarg
bridge) now live under build/<arch>/vendor/tcc/ alongside mes-libc, so
boot.sh <arch> writes everything beneath build/<arch>/. The bridge
file becomes a per-arch copy (content is byte-identical across arches);
build/tcc/ is gone entirely.
Makefile switches $(TCC_FLAT) to a static pattern rule over $(TCC_FLATS)
and threads the per-arch path through the tcc-boot2 P1pp rule.
Diffstat:
15 files changed, 107 insertions(+), 100 deletions(-)
diff --git a/Makefile b/Makefile
@@ -274,20 +274,20 @@ $(CC_BINS): build/%/cc/cc.scm: $(CC_SRCS) build/%/.image build/%/tools/catm
# --- tcc-boot2 end-to-end harness -----------------------------------------
#
# Drives stage1-flatten.sh (host preprocessor only — no container) to
-# produce build/tcc/$(TCC_TARGET)/tcc.flat.c, then runs cc.scm inside
+# produce build/$(ARCH)/vendor/tcc/tcc.flat.c, then runs cc.scm inside
# the per-arch container against the flattened TU, then assembles the
# resulting P1pp into a runnable ELF using the standard P1pp pipeline.
-# The resulting binary embeds tcc's $(TCC_TARGET) codegen, so match
-# $(ARCH) to it (aarch64↔ARM64, amd64↔X86_64, riscv64↔RISCV64) if you
-# want generated programs to run natively in the container. tcc.flat.c
-# lives outside the per-arch tree because it depends on TCC_TARGET, not
-# the build arch.
+# The resulting binary embeds tcc's $(TCC_TARGET) codegen; ARCH and
+# TCC_TARGET track 1:1 (aarch64↔ARM64, amd64↔X86_64, riscv64↔RISCV64)
+# so generated programs run natively in the per-arch container.
TCC_TARGET_aarch64 := ARM64
TCC_TARGET_amd64 := X86_64
TCC_TARGET_riscv64 := RISCV64
TCC_TARGET ?= $(TCC_TARGET_$(ARCH))
-TCC_FLAT := build/tcc/$(TCC_TARGET)/tcc.flat.c
+TCC_VENDOR := build/$(ARCH)/vendor/tcc
+TCC_FLAT := $(TCC_VENDOR)/tcc.flat.c
+TCC_FLATS := $(foreach a,$(ALL_ARCHES),build/$(a)/vendor/tcc/tcc.flat.c)
TCC_BOOT2_BINS := $(foreach a,$(ALL_ARCHES),build/$(a)/tcc-boot2/tcc-boot2)
TCC_BOOT2_P1PPS := $(foreach a,$(ALL_ARCHES),build/$(a)/tcc-boot2/tcc.flat.P1pp)
@@ -302,13 +302,13 @@ LIBC_P1PPS := $(foreach a,$(ALL_ARCHES),build/$(a)/vendor/mes-libc/libc.P1pp)
tcc-flat: $(TCC_FLAT)
tcc-boot2: $(OUT_DIR)/tcc-boot2/tcc-boot2
-$(TCC_FLAT): scripts/stage1-flatten.sh
- sh scripts/stage1-flatten.sh --arch $(TCC_TARGET)
+$(TCC_FLATS): build/%/vendor/tcc/tcc.flat.c: scripts/stage1-flatten.sh
+ sh scripts/stage1-flatten.sh --arch $*
# stage1-flatten.sh writes this as a side effect — the post-patch tcc
-# <stdarg.h>, used as a cross-arch bridge prepended into both .flat.c
+# <stdarg.h>, used as a per-arch bridge prepended into both .flat.c
# files (see comments in stage1-flatten.sh / libc-flatten.sh).
-build/tcc/stdarg-bridge.h: $(TCC_FLAT)
+build/%/vendor/tcc/stdarg-bridge.h: build/%/vendor/tcc/tcc.flat.c
# Catalog of inputs the host preprocessor reads when flattening libc.
LIBC_VENDOR_SRCS := $(shell find vendor/mes-libc -type f \( -name '*.c' -o -name '*.h' \) 2>/dev/null) \
@@ -316,7 +316,7 @@ LIBC_VENDOR_SRCS := $(shell find vendor/mes-libc -type f \( -name '*.c' -o -name
$(wildcard vendor/mes-libc/patches/*.after)
$(LIBC_FLATS): build/%/vendor/mes-libc/libc.flat.c: \
- scripts/libc-flatten.sh build/tcc/stdarg-bridge.h $(LIBC_VENDOR_SRCS)
+ scripts/libc-flatten.sh build/%/vendor/tcc/stdarg-bridge.h $(LIBC_VENDOR_SRCS)
sh scripts/libc-flatten.sh --arch $*
# libc and tcc.flat are both compiled with --lib= so they omit the
@@ -340,11 +340,11 @@ $(LIBC_P1PPS): build/%/vendor/mes-libc/libc.P1pp: \
sh scripts/boot-build-cc.sh $< $@
$(TCC_BOOT2_P1PPS): build/%/tcc-boot2/tcc.flat.P1pp: \
- $(TCC_FLAT) build/%/scheme1/scheme1 build/%/cc/cc.scm \
+ build/%/vendor/tcc/tcc.flat.c build/%/scheme1/scheme1 build/%/cc/cc.scm \
scripts/boot-build-cc.sh build/%/.image
$(call PODMAN,$*) env CC_LIB=tcc__ \
CC_DEBUG=$(CC_DEBUG) CC_TRACE_EMIT=$(CC_TRACE_EMIT) \
- sh scripts/boot-build-cc.sh $(TCC_FLAT) $@
+ sh scripts/boot-build-cc.sh build/$*/vendor/tcc/tcc.flat.c $@
# tcc-boot2 link: pure catm chain — entry stub, libc, client TU,
# elf terminator. boot-build-p1pp.sh concatenates them in order
@@ -426,8 +426,8 @@ endif
TCC_CC_START := build/$(ARCH)/tcc-cc/start.o
TCC_CC_MEM := build/$(ARCH)/tcc-cc/mem.o
-TCC_CC_TCC_INCLUDE = build/tcc/$(TCC_TARGET)/tcc-0.9.26-1147-gee75a10c/include
-TCC_CC_TCC_LIBDIR = build/tcc/$(TCC_TARGET)/tcc-0.9.26-1147-gee75a10c/lib
+TCC_CC_TCC_INCLUDE = $(TCC_VENDOR)/tcc-0.9.26-1147-gee75a10c/include
+TCC_CC_TCC_LIBDIR = $(TCC_VENDOR)/tcc-0.9.26-1147-gee75a10c/lib
# x86_64-only: tcc emits calls to __va_start / __va_arg for variadic
# functions. Upstream tcc supplies these via lib/va_list.c → va_list.o
@@ -494,13 +494,13 @@ $(TCC_CC_MEM): tcc-cc/mem.c \
# rule is gated on amd64 via TCC_CC_VA_LIST being non-empty above.
build/amd64/tcc-cc/va_list.o: \
build/amd64/tcc-boot2/tcc-boot2 \
- build/amd64/.image $(TCC_FLAT)
+ build/amd64/.image build/amd64/vendor/tcc/tcc.flat.c
mkdir -p $(@D)
$(call PODMAN,amd64) \
build/amd64/tcc-boot2/tcc-boot2 \
- -nostdlib -I build/tcc/X86_64/tcc-0.9.26-1147-gee75a10c/include \
+ -nostdlib -I build/amd64/vendor/tcc/tcc-0.9.26-1147-gee75a10c/include \
-D TCC_TARGET_X86_64=1 \
- -c -o $@ build/tcc/X86_64/tcc-0.9.26-1147-gee75a10c/lib/va_list.c
+ -c -o $@ build/amd64/vendor/tcc/tcc-0.9.26-1147-gee75a10c/lib/va_list.c
# --- tcc-libc test harness inputs ----------------------------------------
#
diff --git a/docs/LIBC.md b/docs/LIBC.md
@@ -354,7 +354,7 @@ Add `scripts/boot-build-libtcc1.sh`:
```sh
TCC_BOOT2=build/$ARCH/tcc-boot2/tcc-boot2
-TCC_SRC=build/tcc/$TCC_TARGET/tcc-0.9.26-1147-gee75a10c
+TCC_SRC=build/$ARCH/vendor/tcc/tcc-0.9.26-1147-gee75a10c
$TCC_BOOT2 -c -D HAVE_CONFIG_H=1 -D HAVE_LONG_LONG=1 -D HAVE_FLOAT=1 \
-I vendor/mes-libc/include \
-I vendor/mes-libc/include/linux/$MES_ARCH \
diff --git a/docs/MUSL.md b/docs/MUSL.md
@@ -36,7 +36,7 @@ scripts/boot5.sh <amd64|aarch64|riscv64>
| `vendor/upstream/musl-1.2.5-deletes.txt` | upstream files removed by the same patch set, one path per line |
| `vendor/upstream/musl-1.2.5-generated/$MUSL_ARCH/{alltypes,syscall}.h` | per-arch headers pre-generated at vendor time (replaces musl's mkalltypes.sed + `__NR_`→`SYS_` rewrite, so the container needs no awk) |
| `vendor/upstream/musl-1.2.5-skip-$ARCH.txt` | per-arch calibration list — sources tcc 0.9.26 cannot compile, produced by `scripts/boot5-calibrate.sh` |
-| `build/tcc/stdarg-bridge.h` | shared `__builtin_va_list` bridge (one file, three arches gated by `#ifdef`; produced by `scripts/stage1-flatten.sh`) |
+| `build/$ARCH/vendor/tcc/stdarg-bridge.h` | per-arch `__builtin_va_list` bridge (byte-identical across arches, three arches gated by `#ifdef`; produced by `scripts/stage1-flatten.sh`) |
| `scripts/boot-hello.c` | smoke-test source (shared with boot4) |
Architecture mapping:
@@ -125,7 +125,7 @@ surfaces tcc 0.9.26 cannot compile:
| C99 array parameters | remove `[static N]` qualifiers tcc does not parse |
| `_Complex` | stub `complex.h` and remove complex sources |
| arch asm overrides | delete unsupported fenv, signal, setjmp, thread, string, math overrides as needed |
-| varargs | pre-include `build/tcc/stdarg-bridge.h` (the post-patch tcc `<stdarg.h>`) for C translation units |
+| varargs | pre-include `build/$ARCH/vendor/tcc/stdarg-bridge.h` (the post-patch tcc `<stdarg.h>`) for C translation units |
Required tcc fixes live under `scripts/simple-patches/tcc-0.9.26/`.
The musl build depends on the aarch64 literal-address load/store fixes
diff --git a/docs/TCC.md b/docs/TCC.md
@@ -45,7 +45,7 @@ tcc-0.9.26-1147-gee75a10c.tar.gz live-bootstrap source
│ • apply 2 simple-patches
│ • host cc -E -nostdinc with mes headers + tcc-mes defines
▼
-build/tcc/X86_64/tcc.flat.c 608 KB single-file C
+build/amd64/vendor/tcc/tcc.flat.c 608 KB single-file C
│
│ stage2-alpine.sh (alpine:latest)
│ • apk add gcc musl-dev
@@ -55,18 +55,18 @@ build/tcc/X86_64/tcc.flat.c 608 KB single-file C
│ • tcc-host -static compiles+links real tcc.c -> tcc-boot0-mes
│ (mirrors live-bootstrap's tcc-boot0 invocation)
▼
-build/tcc/X86_64/tcc-boot0-mes ~750 KB tcc-0.9.26 ELF
+build/amd64/vendor/tcc/tcc-boot0-mes ~750 KB tcc-0.9.26 ELF
│
│ stage3-rebuild.sh (busybox:musl)
│ • tcc-boot0-mes rebuilds libc, then compiles real tcc.c -> tcc-boot1
│ • tcc-boot1 rebuilds libc, then compiles real tcc.c -> tcc-boot2
▼
-build/tcc/X86_64/tcc-boot2 final tcc-0.9.26
+build/amd64/vendor/tcc/tcc-boot2 final tcc-0.9.26
```
Two containers, three scripts, one host-side step. Stage 1's
`tcc.flat.c` is a portable artifact; stage 2's `tcc-boot0-mes` plus
-mes libc bits cross into stage 3 via `build/tcc/<arch>/stage3-input/`.
+mes libc bits cross into stage 3 via `build/amd64/vendor/tcc/stage3-input/`.
## Stage 1 — flatten tcc.c into tcc.flat.c
@@ -85,7 +85,7 @@ regardless of where stage 1 ran.
### Sub-steps
-1. **Unpack** `tcc-0.9.26.tar.gz` into `build/tcc/X86_64/`.
+1. **Unpack** `tcc-0.9.26.tar.gz` into `build/amd64/vendor/tcc/`.
2. **Apply simple-patches**: `remove-fileopen.before/.after` then
`addback-fileopen.before/.after` against `tcctools.c`. Implemented
as an `awk` literal-block replacer (live-bootstrap's `simple-patch`
@@ -190,7 +190,7 @@ libc, where errno is the plain global mes expects.
live-bootstrap-style direct invocation doesn't already validate.
~750 KB output.
7. **Stage out** mes libc + libtcc1 + crt1.o + headers into
- `build/tcc/X86_64/stage3-input/`, so stage 3 can mount
+ `build/amd64/vendor/tcc/stage3-input/`, so stage 3 can mount
them without re-running stage 2.
8. **Smoke test**: `tcc-boot0-mes -version`. **Expected to SEGV under
QEMU on macOS arm64** (Issue §3); native x86_64 needed to verify
@@ -283,7 +283,7 @@ scripts/stage2-alpine.sh --arch X86_64
scripts/stage3-rebuild.sh --arch X86_64 # blocked on Issue §3 today
```
-Artifacts in `build/tcc/X86_64/`:
+Artifacts in `build/amd64/vendor/tcc/`:
| File | Stage | Size | Built by | What it is |
|-------------------|-------|---------|-----------------------|-------------------------------------------|
diff --git a/scripts/boot-build-tcc-tcc.sh b/scripts/boot-build-tcc-tcc.sh
@@ -38,14 +38,15 @@ OUT=$1
CC=${2:-build/$ARCH/tcc-boot2/tcc-boot2}
case "$ARCH" in
- aarch64) TCC_TARGET=ARM64; LIB_TARGET_DEFINES="-D TCC_TARGET_ARM64=1 -D TCC_TARGET_ARM=1" ;;
- amd64) TCC_TARGET=X86_64; LIB_TARGET_DEFINES= ;;
- riscv64) TCC_TARGET=RISCV64; LIB_TARGET_DEFINES="-D TCC_TARGET_RISCV64=1" ;;
+ aarch64) LIB_TARGET_DEFINES="-D TCC_TARGET_ARM64=1 -D TCC_TARGET_ARM=1" ;;
+ amd64) LIB_TARGET_DEFINES= ;;
+ riscv64) LIB_TARGET_DEFINES="-D TCC_TARGET_RISCV64=1" ;;
*) echo "boot-build-tcc-tcc.sh: unsupported ARCH '$ARCH'" >&2; exit 2 ;;
esac
-TCC_INC=build/tcc/$TCC_TARGET/tcc-0.9.26-1147-gee75a10c/include
-TCC_FLAT=build/tcc/$TCC_TARGET/tcc.flat.c
+TCC_VENDOR=build/$ARCH/vendor/tcc
+TCC_INC=$TCC_VENDOR/tcc-0.9.26-1147-gee75a10c/include
+TCC_FLAT=$TCC_VENDOR/tcc.flat.c
LIBC_O=build/$ARCH/tcc-libc/libc.o
MEM_O=build/$ARCH/tcc-libc/mem.o
SYS_O=build/$ARCH/tcc-libc/sys_stubs.o
@@ -54,7 +55,7 @@ WORK=$(dirname "$OUT")
mkdir -p "$WORK"
-TCC_LIB_DIR=build/tcc/$TCC_TARGET/tcc-0.9.26-1147-gee75a10c/lib
+TCC_LIB_DIR=$TCC_VENDOR/tcc-0.9.26-1147-gee75a10c/lib
LIB_OBJS=
if [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "riscv64" ]; then
diff --git a/scripts/boot-run-tests.sh b/scripts/boot-run-tests.sh
@@ -625,7 +625,7 @@ run_tcc_cc_suite() {
esac
start=build/$ARCH/tcc-cc/start.o
mem=build/$ARCH/tcc-cc/mem.o
- tcc_include=build/tcc/$tcc_target/tcc-0.9.26-1147-gee75a10c/include
+ tcc_include=build/$ARCH/vendor/tcc/tcc-0.9.26-1147-gee75a10c/include
# x86_64 only: __va_start / __va_arg intrinsics for variadic
# functions. Other arches lower va_arg without out-of-line helpers.
if [ "$ARCH" = "amd64" ]; then
@@ -736,7 +736,7 @@ run_tcc_libc_suite() {
sys_stubs=build/$ARCH/tcc-libc/sys_stubs.o
mem=build/$ARCH/tcc-libc/mem.o
libc=build/$ARCH/tcc-libc/libc.o
- tcc_include=build/tcc/$tcc_target/tcc-0.9.26-1147-gee75a10c/include
+ tcc_include=build/$ARCH/vendor/tcc/tcc-0.9.26-1147-gee75a10c/include
# x86_64 only: __va_start / __va_arg intrinsics for variadic
# functions. mes-libc's printf family hits this directly.
if [ "$ARCH" = "amd64" ]; then
diff --git a/scripts/boot3.sh b/scripts/boot3.sh
@@ -13,11 +13,11 @@
## tcc3 = tcc-source compiled by tcc2 ← boot4
##
## ─── Inputs (host-side, auto-built if missing) ────────────────────────
-## build/tcc/$TCC_TARGET/tcc.flat.c
-## build/tcc/$TCC_TARGET/tcc-0.9.26-1147-gee75a10c/{include,lib}
+## build/$ARCH/vendor/tcc/tcc.flat.c
+## build/$ARCH/vendor/tcc/tcc-0.9.26-1147-gee75a10c/{include,lib}
## — flattened tcc TU + unpacked tree; built
## via scripts/stage1-flatten.sh --arch
-## $TCC_TARGET (host cc -E, no container)
+## $ARCH (host cc -E, no container)
## build/$ARCH/vendor/mes-libc/libc.flat.c
## — flattened mes-libc TU; built via
## scripts/libc-flatten.sh --arch $ARCH
@@ -56,9 +56,9 @@ usage() { echo "usage: $0 <aarch64|amd64|riscv64>" >&2; exit 2; }
ARCH=$1
case "$ARCH" in
- aarch64) PLATFORM=linux/arm64; TCC_TARGET=ARM64 ;;
- amd64) PLATFORM=linux/amd64; TCC_TARGET=X86_64 ;;
- riscv64) PLATFORM=linux/riscv64; TCC_TARGET=RISCV64 ;;
+ aarch64) PLATFORM=linux/arm64 ;;
+ amd64) PLATFORM=linux/amd64 ;;
+ riscv64) PLATFORM=linux/riscv64 ;;
*) usage ;;
esac
@@ -72,8 +72,9 @@ BOOT2=build/$ARCH/boot2
OUT=build/$ARCH/boot3
STAGE=build/$ARCH/.boot3-stage
-TCC_DIR=build/tcc/$TCC_TARGET/tcc-0.9.26-1147-gee75a10c
-TCC_FLAT=build/tcc/$TCC_TARGET/tcc.flat.c
+TCC_VENDOR=build/$ARCH/vendor/tcc
+TCC_DIR=$TCC_VENDOR/tcc-0.9.26-1147-gee75a10c
+TCC_FLAT=$TCC_VENDOR/tcc.flat.c
LIBC_FLAT=build/$ARCH/vendor/mes-libc/libc.flat.c
# ── ensure container image exists (podman driver only) ────────────────
@@ -101,9 +102,9 @@ export IMAGE PLATFORM DRIVER
# tcc.flat.c + the unpacked $TCC_DIR/{include,lib} tree are produced
# together by stage1-flatten.sh; libc.flat.c by libc-flatten.sh. Both
# run on the host (cc -E), no container — auto-invoke if missing.
-if [ ! -e "$TCC_FLAT" ] || [ ! -d "$TCC_DIR/include" ] || [ ! -e build/tcc/stdarg-bridge.h ]; then
+if [ ! -e "$TCC_FLAT" ] || [ ! -d "$TCC_DIR/include" ] || [ ! -e "$TCC_VENDOR/stdarg-bridge.h" ]; then
echo "[boot3 $ARCH] flatten tcc.flat.c (host)"
- scripts/stage1-flatten.sh --arch "$TCC_TARGET"
+ scripts/stage1-flatten.sh --arch "$ARCH"
fi
if [ ! -e "$LIBC_FLAT" ]; then
echo "[boot3 $ARCH] flatten libc.flat.c (host)"
diff --git a/scripts/boot4.sh b/scripts/boot4.sh
@@ -20,11 +20,11 @@
## tcc3 = tcc-source compiled by tcc2 ← produced here
##
## ─── Inputs (host-side, auto-built if missing) ────────────────────────
-## build/tcc/$TCC_TARGET/tcc.flat.c
-## build/tcc/$TCC_TARGET/tcc-0.9.26-1147-gee75a10c/{include,lib}
+## build/$ARCH/vendor/tcc/tcc.flat.c
+## build/$ARCH/vendor/tcc/tcc-0.9.26-1147-gee75a10c/{include,lib}
## — flattened tcc TU + unpacked tree; built
## via scripts/stage1-flatten.sh --arch
-## $TCC_TARGET (host cc -E, no container)
+## $ARCH (host cc -E, no container)
## build/$ARCH/vendor/mes-libc/libc.flat.c
## — flattened mes-libc TU; built via
## scripts/libc-flatten.sh --arch $ARCH
@@ -34,17 +34,17 @@
## tcc-libc/$ARCH/start.S — _start, calls __libc_init+main
## tcc-libc/$ARCH/sys_stubs.S — sys_* syscall wrappers
## tcc-cc/mem.c — memcpy/memmove/memset/memcmp
-## build/tcc/$TCC_TARGET/tcc-0.9.26-1147-gee75a10c/lib/libtcc1.c
+## build/$ARCH/vendor/tcc/tcc-0.9.26-1147-gee75a10c/lib/libtcc1.c
## (amd64: generic compiler helper runtime)
-## build/tcc/$TCC_TARGET/tcc-0.9.26-1147-gee75a10c/lib/lib-arm64.c
+## build/$ARCH/vendor/tcc/tcc-0.9.26-1147-gee75a10c/lib/lib-arm64.c
## (aarch64 + riscv64: TFmode soft-float)
-## build/tcc/$TCC_TARGET/tcc-0.9.26-1147-gee75a10c/lib/va_list.c
+## build/$ARCH/vendor/tcc/tcc-0.9.26-1147-gee75a10c/lib/va_list.c
## (amd64: __va_start / __va_arg)
-## build/tcc/$TCC_TARGET/tcc-0.9.26-1147-gee75a10c/lib/alloca86_64*.S
+## build/$ARCH/vendor/tcc/tcc-0.9.26-1147-gee75a10c/lib/alloca86_64*.S
## (amd64: alloca helpers)
-## build/tcc/$TCC_TARGET/tcc.flat.c — flattened tcc TU
-## build/$ARCH/vendor/mes-libc/libc.flat.c — flattened mes-libc TU
-## scripts/boot-hello.c — smoke binary
+## build/$ARCH/vendor/tcc/tcc.flat.c — flattened tcc TU
+## build/$ARCH/vendor/mes-libc/libc.flat.c — flattened mes-libc TU
+## scripts/boot-hello.c — smoke binary
##
## ─── Inputs (binaries from prior stages) ──────────────────────────────
## build/$ARCH/boot3/tcc0 — built by scripts/boot3.sh
@@ -87,15 +87,12 @@ ARCH=$1
case "$ARCH" in
aarch64) PLATFORM=linux/arm64;
- TCC_TARGET=ARM64;
LIBTCC1_C_SRCS="lib-arm64.c";
LIBTCC1_ASM_SRCS="" ;;
amd64) PLATFORM=linux/amd64;
- TCC_TARGET=X86_64;
LIBTCC1_C_SRCS="libtcc1.c va_list.c";
LIBTCC1_ASM_SRCS="alloca86_64.S alloca86_64-bt.S" ;;
riscv64) PLATFORM=linux/riscv64;
- TCC_TARGET=RISCV64;
LIBTCC1_C_SRCS="lib-arm64.c";
LIBTCC1_ASM_SRCS="" ;;
*) usage ;;
@@ -111,8 +108,9 @@ BOOT3=build/$ARCH/boot3
OUT=build/$ARCH/boot4
STAGE=build/$ARCH/.boot4-stage
-TCC_DIR=build/tcc/$TCC_TARGET/tcc-0.9.26-1147-gee75a10c
-TCC_FLAT=build/tcc/$TCC_TARGET/tcc.flat.c
+TCC_VENDOR=build/$ARCH/vendor/tcc
+TCC_DIR=$TCC_VENDOR/tcc-0.9.26-1147-gee75a10c
+TCC_FLAT=$TCC_VENDOR/tcc.flat.c
LIBC_FLAT=build/$ARCH/vendor/mes-libc/libc.flat.c
# ── ensure container image exists (podman driver only) ────────────────
@@ -138,10 +136,10 @@ export IMAGE PLATFORM DRIVER
# ── prerequisite: host-flattened sources + unpacked tcc tree ──────────
# Normally these were produced by boot3 (auto-invoked by stage1-flatten
# / libc-flatten there). Re-check here so boot4 runs standalone if a
-# user has tcc0 but blew away build/tcc/.
-if [ ! -e "$TCC_FLAT" ] || [ ! -d "$TCC_DIR/include" ] || [ ! -e "$TCC_DIR/lib/lib-arm64.c" ] || [ ! -e build/tcc/stdarg-bridge.h ]; then
+# user has tcc0 but blew away build/$ARCH/vendor/tcc/.
+if [ ! -e "$TCC_FLAT" ] || [ ! -d "$TCC_DIR/include" ] || [ ! -e "$TCC_DIR/lib/lib-arm64.c" ] || [ ! -e "$TCC_VENDOR/stdarg-bridge.h" ]; then
echo "[boot4 $ARCH] flatten tcc.flat.c (host)"
- scripts/stage1-flatten.sh --arch "$TCC_TARGET"
+ scripts/stage1-flatten.sh --arch "$ARCH"
fi
if [ ! -e "$LIBC_FLAT" ]; then
echo "[boot4 $ARCH] flatten libc.flat.c (host)"
diff --git a/scripts/boot5-calibrate.sh b/scripts/boot5-calibrate.sh
@@ -45,7 +45,7 @@ MUSL_TARBALL=vendor/upstream/musl-1.2.5.tar.gz
MUSL_OVERRIDES=vendor/upstream/musl-1.2.5-overrides
MUSL_DELETES=vendor/upstream/musl-1.2.5-deletes.txt
MUSL_GENERATED=vendor/upstream/musl-1.2.5-generated/$MUSL_ARCH
-BRIDGE_FILE=build/tcc/stdarg-bridge.h
+BRIDGE_FILE=build/$ARCH/vendor/tcc/stdarg-bridge.h
SKIP_OUT=vendor/upstream/musl-1.2.5-skip-$ARCH.txt
[ -x "$BOOT4/tcc3" ] || { echo "missing $BOOT4/tcc3 (run scripts/boot4.sh $ARCH)" >&2; exit 1; }
diff --git a/scripts/boot5.sh b/scripts/boot5.sh
@@ -24,11 +24,14 @@
## — list of upstream files removed by the
## same patch set (one path per line,
## relative to musl-1.2.5/).
-## build/tcc/stdarg-bridge.h
+## build/$ARCH/vendor/tcc/stdarg-bridge.h
## — per-arch __builtin_va_list bridge,
## generated by scripts/stage1-flatten.sh
-## (shared with boot3/boot4; one file,
-## three arches gated by #ifdef inside)
+## (shared with boot3/boot4; the file is
+## byte-identical across arches but a
+## per-arch copy is written so every
+## artifact under build/$ARCH/ comes from
+## a single boot.sh $ARCH invocation)
##
## ─── Tools ────────────────────────────────────────────────────────────
## In container: scratch + busybox (no libc, no /etc, no resolver).
@@ -80,7 +83,7 @@ MUSL_OVERRIDES=vendor/upstream/musl-1.2.5-overrides
MUSL_DELETES=vendor/upstream/musl-1.2.5-deletes.txt
MUSL_GENERATED=vendor/upstream/musl-1.2.5-generated/$MUSL_ARCH
MUSL_SKIP=vendor/upstream/musl-1.2.5-skip-$ARCH.txt
-BRIDGE_FILE=build/tcc/stdarg-bridge.h
+BRIDGE_FILE=build/$ARCH/vendor/tcc/stdarg-bridge.h
# ── prerequisites ─────────────────────────────────────────────────────
[ -x "$BOOT4/tcc3" ] || { echo "[boot5 $ARCH] missing $BOOT4/tcc3 (run scripts/boot4.sh $ARCH)" >&2; exit 1; }
diff --git a/scripts/libc-flatten.sh b/scripts/libc-flatten.sh
@@ -166,7 +166,7 @@ HOST_CC=${HOST_CC:-cc}
# per-arch va_list typedef + __builtin_va_* → tcc __va_* mapping into
# libc.flat.c, eliminating the need for `-I /work/in/tcc-include
# -include /work/in/tcc-include/stdarg.h` on every in-container compile.
-BRIDGE=$ROOT/build/tcc/stdarg-bridge.h
+BRIDGE=$ROOT/build/$ARCH/vendor/tcc/stdarg-bridge.h
[ -e "$BRIDGE" ] || { echo "missing $BRIDGE — run scripts/stage1-flatten.sh first" >&2; exit 1; }
# -I order matters: vendor/boot2-include first so our stdarg.h shim
diff --git a/scripts/run-gcc-libc-flat-tcc.sh b/scripts/run-gcc-libc-flat-tcc.sh
@@ -29,7 +29,7 @@ TCC=${TCC:-build/$ARCH/tcc-gcc/tcc-gcc}
START=build/$ARCH/tcc-cc/start.o
OUT_ROOT=build/$ARCH/tests/gcc-libc-flat-tcc
WORK_ROOT=build/$ARCH/.work/tests/gcc-libc-flat-tcc
-TCC_SRC=build/tcc/$TCC_TARGET/tcc-0.9.26-1147-gee75a10c
+TCC_SRC=build/$ARCH/vendor/tcc/tcc-0.9.26-1147-gee75a10c
MES_INC=vendor/mes-libc/include
case "$ARCH" in
aarch64) MES_LINUX_INC=vendor/mes-libc/include/linux/riscv64 ;;
@@ -38,7 +38,7 @@ esac
RUNTIME=$WORK_ROOT/runtime.a
[ -x "$TCC" ] || {
- echo "missing $TCC; build it with scripts/build-tcc-gcc.sh and build/tcc/$TCC_TARGET/tcc.flat.c" >&2
+ echo "missing $TCC; build it with scripts/build-tcc-gcc.sh and $TCC_SRC/../tcc.flat.c" >&2
exit 2
}
[ -r "$START" ] || { echo "missing $START" >&2; exit 2; }
diff --git a/scripts/stage1-flatten.sh b/scripts/stage1-flatten.sh
@@ -9,7 +9,7 @@
## 1. unpack tcc-0.9.26-1147-gee75a10c.tar.gz
## 2. apply live-bootstrap simple-patches (tcctools.c file-open reorder)
## 3. host cc -E -nostdinc with mes-bundled headers + tcc-mes defines
-## 4. emit build/tcc/<arch>/tcc.flat.c
+## 4. emit build/<arch>/vendor/tcc/tcc.flat.c
## 5. (--verify) compile tcc.flat.c with host cc to confirm well-formedness
##
## Stage 1 deliberately stays on the host: it is just text manipulation
@@ -34,11 +34,11 @@ while [ $# -gt 0 ]; do
done
case "$ARCH" in
- X86_64|x86_64) MES_ARCH=x86_64; HAVE_LL=1; TCC_TARGET_DEFINE=X86_64; CPP_ARCH=x86_64 ;;
- I386|i386) MES_ARCH=x86; HAVE_LL=0; TCC_TARGET_DEFINE=I386; CPP_ARCH=x86 ;;
- RISCV64|riscv64) MES_ARCH=riscv64; HAVE_LL=1; TCC_TARGET_DEFINE=RISCV64; CPP_ARCH=riscv64 ;;
+ X86_64|x86_64|amd64) BOOT_ARCH=amd64; MES_ARCH=x86_64; HAVE_LL=1; TCC_TARGET_DEFINE=X86_64; CPP_ARCH=x86_64 ;;
+ I386|i386) BOOT_ARCH=i386; MES_ARCH=x86; HAVE_LL=0; TCC_TARGET_DEFINE=I386; CPP_ARCH=x86 ;;
+ RISCV64|riscv64) BOOT_ARCH=riscv64; MES_ARCH=riscv64; HAVE_LL=1; TCC_TARGET_DEFINE=RISCV64; CPP_ARCH=riscv64 ;;
ARM64|arm64|AARCH64|aarch64)
- MES_ARCH=riscv64; HAVE_LL=1; TCC_TARGET_DEFINE=ARM64; CPP_ARCH=aarch64 ;;
+ BOOT_ARCH=aarch64; MES_ARCH=riscv64; HAVE_LL=1; TCC_TARGET_DEFINE=ARM64; CPP_ARCH=aarch64 ;;
*) echo "unknown ARCH: $ARCH" >&2; exit 2 ;;
esac
@@ -57,7 +57,7 @@ esac
# vendor/boot2-include/ — our own header shim, wins
# -I priority for stdarg.h
ROOT=$(cd "$(dirname "$0")/.." && pwd)
-WORK=$ROOT/build/tcc/$ARCH
+WORK=$ROOT/build/$BOOT_ARCH/vendor/tcc
DISTFILES=$ROOT/vendor/upstream
LB_PATCHES=$ROOT/scripts/simple-patches/tcc-0.9.26-lb
OUR_PATCHES=$ROOT/scripts/simple-patches/tcc-0.9.26
@@ -273,15 +273,15 @@ FLAT=$WORK/tcc.flat.c
-D TCC_TARGET_${TCC_TARGET_DEFINE}=1 \
"$SRC/tcc.c" > "$FLAT.body"
-# Publish the post-patch tcc <stdarg.h> as a shared bridge file.
-# libc-flatten.sh prepends the same bridge to libc.flat.c, so the
-# boot3/boot4 container compiles no longer need `-I /work/in/tcc-include
-# -include /work/in/tcc-include/stdarg.h`. The patched stdarg.h is
-# byte-identical across X86_64 / ARM64 / RISCV64 (per-arch logic lives
-# inside its #ifdefs), so a cross-arch shared path is fine — whichever
-# arch's stage1-flatten.sh runs last wins, idempotently.
-BRIDGE=$ROOT/build/tcc/stdarg-bridge.h
-mkdir -p "$ROOT/build/tcc"
+# Publish the post-patch tcc <stdarg.h> as a per-arch bridge file
+# alongside tcc.flat.c. libc-flatten.sh prepends the same bridge to
+# libc.flat.c, so the boot3/boot4 container compiles no longer need
+# `-I /work/in/tcc-include -include /work/in/tcc-include/stdarg.h`.
+# The patched stdarg.h is byte-identical across X86_64 / ARM64 / RISCV64
+# (per-arch logic lives inside its #ifdefs); we still write a per-arch
+# copy so every artifact under build/<arch>/ comes from a single
+# `boot.sh <arch>` invocation, with nothing shared across arches.
+BRIDGE=$WORK/stdarg-bridge.h
cp "$SRC/include/stdarg.h" "$BRIDGE"
# Prepend the bridge into tcc.flat.c, guarded by !CCSCM so cc.scm
diff --git a/scripts/stage2-alpine.sh b/scripts/stage2-alpine.sh
@@ -14,7 +14,7 @@
## definition and links cleanly.
##
## Pre-condition:
-## build/tcc/<arch>/tcc.flat.c (run scripts/stage1-flatten.sh)
+## build/amd64/vendor/tcc/tcc.flat.c (run scripts/stage1-flatten.sh)
##
## Inside alpine:latest (linux/amd64):
## 1. apk add gcc musl-dev
@@ -35,7 +35,7 @@
## Expected to segfault under QEMU x86_64 emulation on macOS arm64
## (Issue §3); native x86_64 needed to verify cleanly.
##
-## Output: build/tcc/<arch>/tcc-boot0-mes (static, mes-libc-linked).
+## Output: build/amd64/vendor/tcc/tcc-boot0-mes (static, mes-libc-linked).
## This artifact is what stage 3 (busybox) consumes to drive the
## tcc-boot1 / tcc-boot2 chain.
##
@@ -58,9 +58,10 @@ if [ "$ARCH" != "X86_64" ]; then
exit 2
fi
MES_ARCH=x86_64
+BOOT_ARCH=amd64
ROOT=$(cd "$(dirname "$0")/.." && pwd)
-WORK=$ROOT/build/tcc/$ARCH
+WORK=$ROOT/build/$BOOT_ARCH/vendor/tcc
# This is the legacy gcc-driven path the cc.scm tcc-boot2 chain
# replaces (see docs/TCC.md). Not on the main `make tcc-boot2`
# build path; kept around as a verification fallback. Requires the
@@ -98,13 +99,14 @@ echo "(slow on macOS arm64 — runs under QEMU linux/amd64)"
TCC_PKG=tcc-0.9.26-1147-gee75a10c
podman run --rm -i --platform linux/amd64 \
- -v "$ROOT":/work -w /work alpine:latest sh -s "$ARCH" "$MES_ARCH" "$MES_PKG" "$TCC_PKG" <<'CONTAINER_SCRIPT'
+ -v "$ROOT":/work -w /work alpine:latest sh -s "$ARCH" "$MES_ARCH" "$MES_PKG" "$TCC_PKG" "$BOOT_ARCH" <<'CONTAINER_SCRIPT'
set -eu
ARCH=$1
MES_ARCH=$2
MES_PKG=$3
TCC_PKG=$4
-WORK=/work/build/tcc/$ARCH
+BOOT_ARCH=$5
+WORK=/work/build/$BOOT_ARCH/vendor/tcc
# --- (1) install gcc + musl-dev (provides libc.a for -static) --------
apk add --no-cache gcc musl-dev >/dev/null
diff --git a/scripts/stage3-rebuild.sh b/scripts/stage3-rebuild.sh
@@ -14,10 +14,10 @@
## flatten set).
##
## Pre-condition:
-## build/tcc/<arch>/tcc-boot0-mes
-## build/tcc/<arch>/stage3-input/ (staged by stage 2)
-## build/tcc/<arch>/tcc-0.9.26-1147-gee75a10c/ (patched, from stage 1)
-## build/tcc/<arch>/mes-0.27.1/ (from stage 2)
+## build/amd64/vendor/tcc/tcc-boot0-mes
+## build/amd64/vendor/tcc/stage3-input/ (staged by stage 2)
+## build/amd64/vendor/tcc/tcc-0.9.26-1147-gee75a10c/ (patched, from stage 1)
+## build/amd64/vendor/tcc/mes-0.27.1/ (from stage 2)
##
## Container: docker.io/library/busybox:musl on linux/amd64.
## Tools used inside: busybox sh + tcc-boot0-mes (which provides its own
@@ -49,9 +49,10 @@ if [ "$ARCH" != "X86_64" ]; then
exit 2
fi
MES_ARCH=x86_64
+BOOT_ARCH=amd64
ROOT=$(cd "$(dirname "$0")/.." && pwd)
-WORK=$ROOT/build/tcc/$ARCH
+WORK=$ROOT/build/$BOOT_ARCH/vendor/tcc
TCC_PKG=tcc-0.9.26-1147-gee75a10c
MES_PKG=mes-0.27.1
@@ -66,13 +67,14 @@ echo "(Issue §3 may block on macOS arm64 / QEMU; native x86_64 expected to succ
podman run --rm -i --platform linux/amd64 \
-v "$ROOT":/work -w /work \
- docker.io/library/busybox:musl sh -s "$ARCH" "$MES_ARCH" "$TCC_PKG" "$MES_PKG" <<'CONTAINER_SCRIPT'
+ docker.io/library/busybox:musl sh -s "$ARCH" "$MES_ARCH" "$TCC_PKG" "$MES_PKG" "$BOOT_ARCH" <<'CONTAINER_SCRIPT'
set -eu
ARCH=$1
MES_ARCH=$2
TCC_PKG=$3
MES_PKG=$4
-WORK=/work/build/tcc/$ARCH
+BOOT_ARCH=$5
+WORK=/work/build/$BOOT_ARCH/vendor/tcc
# --- install tcc-boot0-mes + mes libc bits at baked-in paths --------
mkdir -p /lib/tcc /include/mes /bin