commit 78d4e8169776cc9364c5d4ea469bcde626352111
parent ad1edb1582d3d37e74b6b2b3b0960ad8823f1319
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Wed, 20 May 2026 06:59:57 -0700
Add bootstrap target
Diffstat:
| M | Makefile | | | 54 | +++++++++++++++++++++++------------------------------- |
1 file changed, 23 insertions(+), 31 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,8 +1,8 @@
CC = clang
SYSROOT = $(shell xcrun --show-sdk-path)
-# -isysroot lives in its own var so the `self` target (cfree-as-CC) can
-# swap it for cfree's -isystem-only flag set.
+# -isysroot lives in its own var so stage/bootstrap recipes can override
+# host SDK handling when cfree is used as the compiler.
HOST_SYSROOT_CFLAGS = -isysroot $(SYSROOT)
HOST_SYSROOT_LDFLAGS = -isysroot $(SYSROOT)
@@ -41,7 +41,7 @@ LIB_AR = build/libcfree.a
LANG_TOY_AR = build/libcfree_toy.a
BIN = build/cfree
-.PHONY: all lib bin format clean self self-stage2
+.PHONY: all lib bin format clean bootstrap
all: lib bin
@@ -90,37 +90,29 @@ build/lang/toy/%.o: lang/toy/%.c
include rt/Makefile
-# Self-host: build cfree with clang (stage 1), then rebuild libcfree.a +
-# driver + bin from clean using stage-1 cfree as CC (stage 2). Stage 1 is
-# preserved at build/cfree-stage1; build/cfree is replaced with stage 2.
-#
-# cfree's cc accepts -I, -isystem, -D, -U, -c, -o, -O, -g, -MMD, -MP,
-# -MF, -fPIC/-fPIE, -static, -shared, -Wl,, -target, -ffile-prefix-map=,
-# --build-id=. It rejects -isysroot, -std=c11, -Wpedantic/-Wall/-Wextra,
-# -Werror, -ffreestanding — those are dropped from the stage-2 flag set.
+# Bootstrap: build cfree with the host compiler as stage 1, rebuild it with
+# stage 1 as stage 2, rebuild it again with stage 2 as stage 3, then require
+# stages 2 and 3 to be bitwise identical.
STAGE1_BIN = build/cfree-stage1
+BOOTSTRAP_STAGE2_OUT = build/stage2-probe
+BOOTSTRAP_STAGE3_OUT = build/stage3-probe
+BOOTSTRAP_STAGE2_BIN = build/cfree-stage2
+BOOTSTRAP_STAGE3_BIN = build/cfree-stage3
-self: $(BIN)
+bootstrap: $(BIN)
cp $(BIN) $(STAGE1_BIN)
- rm -rf build/lib build/driver $(LIB_AR) $(BIN)
- $(MAKE) self-stage2
-
-# Stage 2 sysroot: cfree finds system headers via -isystem, not -isysroot.
-# rt/include ships cfree's freestanding headers (stddef.h, stdarg.h, ...)
-# and must precede the SDK so its versions win over Xcode's.
-SELF_SYSROOT_CFLAGS = -isystem rt/include -isystem rt/include/libc
-SELF_SYSROOT_LDFLAGS =
-SELF_LIB_CFLAGS = $(SELF_SYSROOT_CFLAGS) -Iinclude -Isrc
-SELF_DRIVER_CFLAGS = $(SELF_SYSROOT_CFLAGS) -Iinclude
-
-self-stage2:
- $(MAKE) all \
- CC='$(abspath $(STAGE1_BIN)) cc' \
- CFLAGS_COMMON='$(SELF_SYSROOT_CFLAGS)' \
- LIB_CFLAGS='$(SELF_LIB_CFLAGS)' \
- DRIVER_CFLAGS='$(SELF_DRIVER_CFLAGS)' \
- HOST_SYSROOT_LDFLAGS='$(SELF_SYSROOT_LDFLAGS)' \
- DEPFLAGS=''
+ rm -rf $(BOOTSTRAP_STAGE2_OUT) $(BOOTSTRAP_STAGE3_OUT) \
+ $(BOOTSTRAP_STAGE2_BIN) $(BOOTSTRAP_STAGE3_BIN)
+ CFREE_STAGE_BIN='$(abspath $(STAGE1_BIN))' \
+ CFREE_STAGE_OUT='$(abspath $(BOOTSTRAP_STAGE2_OUT))' \
+ CFREE_STAGE_OUTPUT='$(abspath $(BOOTSTRAP_STAGE2_BIN))' \
+ scripts/stage2_link.sh
+ CFREE_STAGE_BIN='$(abspath $(BOOTSTRAP_STAGE2_BIN))' \
+ CFREE_STAGE_OUT='$(abspath $(BOOTSTRAP_STAGE3_OUT))' \
+ CFREE_STAGE_OUTPUT='$(abspath $(BOOTSTRAP_STAGE3_BIN))' \
+ scripts/stage2_link.sh
+ cmp $(BOOTSTRAP_STAGE2_BIN) $(BOOTSTRAP_STAGE3_BIN)
+ shasum -a 256 $(BOOTSTRAP_STAGE2_BIN) $(BOOTSTRAP_STAGE3_BIN)
format:
find src include driver lang test rt \( -path test/lex -o -path test/pp \) -prune -o \( -name '*.c' -o -name '*.h' \) -print | xargs clang-format -i --style=google