# ww — Plan 9-organised toolchain. POSIX make. # # Build a small static frontend library libwcc.a and the user-facing # driver `ww`. Per-target tools (w6c, w6a, w6l) and the runtime are added # in their own phases. Everything lands under out/. PREFIX ?= /usr/local CC ?= cc AR ?= ar CFLAGS ?= -O0 -g -Wall -Wextra -Wpedantic -Wno-unused-parameter CFLAGS += -std=c99 -fno-strict-aliasing -D_POSIX_C_SOURCE=200809L INCS = -Icmd/wcc OUT = out BIN = $(OUT)/bin LIB = $(OUT)/lib OBJ = $(OUT)/obj WCC_SRC = cmd/wcc/mem.c cmd/wcc/err.c cmd/wcc/tok.c cmd/wcc/lex.c \ cmd/wcc/ast.c cmd/wcc/parse.c cmd/wcc/sym.c cmd/wcc/type.c \ cmd/wcc/check.c WCC_OBJ = $(WCC_SRC:cmd/wcc/%.c=$(OBJ)/wcc/%.o) WW_SRC = cmd/ww/main.c WW_OBJ = $(WW_SRC:cmd/ww/%.c=$(OBJ)/ww/%.o) WD_SRC = cmd/wwdump/main.c WD_OBJ = $(WD_SRC:cmd/wwdump/%.c=$(OBJ)/wwdump/%.o) W6C_SRC = cmd/w6c/main.c cmd/w6c/cgen.c cmd/w6c/txt.c cmd/w6c/swt.c \ cmd/w6c/peep.c cmd/w6c/reg.c W6C_OBJ = $(W6C_SRC:cmd/w6c/%.c=$(OBJ)/w6c/%.o) W6A_SRC = cmd/w6a/main.c cmd/w6a/lex.c cmd/w6a/parse.c cmd/w6a/asm.c cmd/w6a/obj.c W6A_OBJ = $(W6A_SRC:cmd/w6a/%.c=$(OBJ)/w6a/%.o) W6L_SRC = cmd/w6l/main.c cmd/w6l/obj.c cmd/w6l/sym.c cmd/w6l/pass.c cmd/w6l/out.c \ cmd/w6l/dyn.c cmd/w6l/dynout.c W6L_OBJ = $(W6L_SRC:cmd/w6l/%.c=$(OBJ)/w6l/%.o) RT_S = rt/start.s rt/syscall.s rt/alloc.s rt/streq.s rt/abort.s RT_OBJ = $(RT_S:rt/%.s=$(OBJ)/rt/%.o) # Cstage: one-time C bootstrap (see BOOTSTRAP.md). Built by `cc`. # Goes away at v1.0, replaced by a checked-in stage-0 binary. CSTAGE_BINS = $(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l $(BIN)/wwdump # Wwstage: ww-rewritten toolchain. Built by Cstage today; will be the # only toolchain after Phase 10 closeout. Byte-identical to Cstage # (tests 990-994). WWSTAGE_BINS = $(BIN)/wwdump_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww $(BIN)/ww_ww BINS = $(CSTAGE_BINS) $(WWSTAGE_BINS) LIBS = $(LIB)/libwcc.a $(LIB)/libwwrt.a all: cstage wwstage cstage: $(CSTAGE_BINS) $(LIBS) wwstage: $(WWSTAGE_BINS) # ---- libwcc.a ---------------------------------------------------------- $(LIB)/libwcc.a: $(WCC_OBJ) | $(LIB) $(AR) rcs $@ $(WCC_OBJ) $(OBJ)/wcc/%.o: cmd/wcc/%.c cmd/wcc/ww.h | $(OBJ)/wcc $(CC) $(CFLAGS) $(INCS) -c -o $@ $< # ---- ww driver --------------------------------------------------------- $(BIN)/ww: $(WW_OBJ) $(LIB)/libwcc.a | $(BIN) $(CC) $(CFLAGS) -o $@ $(WW_OBJ) -L$(LIB) -lwcc $(OBJ)/ww/%.o: cmd/ww/%.c cmd/wcc/ww.h | $(OBJ)/ww $(CC) $(CFLAGS) $(INCS) -c -o $@ $< # ---- wwdump (lex/AST diff anchor) -------------------------------------- $(BIN)/wwdump: $(WD_OBJ) $(LIB)/libwcc.a | $(BIN) $(CC) $(CFLAGS) -o $@ $(WD_OBJ) -L$(LIB) -lwcc $(OBJ)/wwdump/%.o: cmd/wwdump/%.c cmd/wcc/ww.h | $(OBJ)/wwdump $(CC) $(CFLAGS) $(INCS) -c -o $@ $< # ---- w6c amd64 compiler ------------------------------------------------ $(BIN)/w6c: $(W6C_OBJ) $(LIB)/libwcc.a | $(BIN) $(CC) $(CFLAGS) -o $@ $(W6C_OBJ) -L$(LIB) -lwcc $(OBJ)/w6c/%.o: cmd/w6c/%.c cmd/w6c/gc.h cmd/w6c/6.out.h cmd/wcc/ww.h | $(OBJ)/w6c $(CC) $(CFLAGS) $(INCS) -Icmd/w6c -c -o $@ $< # ---- w6a amd64 assembler ----------------------------------------------- $(BIN)/w6a: $(W6A_OBJ) | $(BIN) $(CC) $(CFLAGS) -o $@ $(W6A_OBJ) $(OBJ)/w6a/%.o: cmd/w6a/%.c cmd/w6a/a.h cmd/w6c/6.out.h | $(OBJ)/w6a $(CC) $(CFLAGS) -Icmd/w6a -Icmd/w6c -c -o $@ $< # ---- w6l amd64 linker -------------------------------------------------- $(BIN)/w6l: $(W6L_OBJ) | $(BIN) $(CC) $(CFLAGS) -o $@ $(W6L_OBJ) $(OBJ)/w6l/%.o: cmd/w6l/%.c cmd/w6l/l.h | $(OBJ)/w6l $(CC) $(CFLAGS) -Icmd/w6l -c -o $@ $< # ---- ww-side wwdump (the lexer port, exercised by 990_selfhost) -------- # Built via the user-facing ww driver. The introspection ports (lex, # tok, ast, parse, typ, sym) live in lib/ww/; the compiler-only bits # (mem, check, cgen*) stay in selfhost/cmd/wcc/. Output named wwdump_ww # to avoid colliding with the C-side wwdump in $(BIN). $(BIN)/wwdump_ww: selfhost/cmd/wwdump/main.ww \ lib/ww/lex.ww lib/ww/tok.ww lib/ww/ast.ww \ lib/ww/parse.ww lib/ww/typ.ww lib/ww/sym.ww \ selfhost/cmd/wcc/mem.ww selfhost/cmd/wcc/check.ww \ selfhost/cmd/wcc/cgen.ww selfhost/cmd/wcc/cgen_expr.ww \ selfhost/cmd/wcc/cgen_stmt.ww selfhost/cmd/wcc/cgen_util.ww \ selfhost/cmd/wcc/cgen_decl.ww \ lib/os/os.ww lib/strconv/strconv.ww \ $(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \ $(LIB)/libwwrt.a | $(BIN) cd $(BIN) && ./ww build \ -I $$PWD/../../lib/ww \ -I $$PWD/../../selfhost/cmd/wcc \ $$PWD/../../selfhost/cmd/wwdump/main.ww mv $(BIN)/main $@ # ---- ww-side w6c (compiler port, exercised by 994_w6c_ww) ------------- # Thin driver: parse + cgen. The frontend (lex/parse/ast/...) lives in # lib/ww/; cgen + check live in selfhost/cmd/wcc/. $(BIN)/w6c_ww: selfhost/cmd/w6c/main.ww \ lib/ww/lex.ww lib/ww/tok.ww lib/ww/ast.ww \ lib/ww/parse.ww lib/ww/typ.ww lib/ww/sym.ww \ selfhost/cmd/wcc/mem.ww selfhost/cmd/wcc/check.ww \ selfhost/cmd/wcc/cgen.ww selfhost/cmd/wcc/cgen_expr.ww \ selfhost/cmd/wcc/cgen_stmt.ww selfhost/cmd/wcc/cgen_util.ww \ selfhost/cmd/wcc/cgen_decl.ww \ lib/os/os.ww \ $(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \ $(LIB)/libwwrt.a | $(BIN) cd $(BIN) && ./ww build \ -I $$PWD/../../lib/ww \ -I $$PWD/../../selfhost/cmd/wcc \ $$PWD/../../selfhost/cmd/w6c/main.ww mv $(BIN)/main $@ # ---- ww-side w6a (assembler port, exercised by 991_w6a_ww) ------------ # Built like wwdump_ww. Needs -I selfhost/cmd/w6a for the local types/lex/ # parse/asm/obj modules and -I selfhost/cmd/wcc to find `mem`. $(BIN)/w6a_ww: selfhost/cmd/w6a/main.ww selfhost/cmd/w6a/types.ww \ selfhost/cmd/w6a/lex.ww selfhost/cmd/w6a/parse.ww \ selfhost/cmd/w6a/asm.ww selfhost/cmd/w6a/obj.ww \ selfhost/cmd/wcc/mem.ww \ lib/os/os.ww \ $(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \ $(LIB)/libwwrt.a | $(BIN) cd $(BIN) && ./ww build \ -I $$PWD/../../selfhost/cmd/w6a \ -I $$PWD/../../selfhost/cmd/wcc \ $$PWD/../../selfhost/cmd/w6a/main.ww mv $(BIN)/main $@ # ---- ww-side w6l (linker port, exercised by 992_w6l_ww) --------------- # Built like 6a_ww. Needs -I selfhost/cmd/w6l for the local sym/obj/pass/ # out modules and -I selfhost/cmd/wcc to find `mem`. $(BIN)/w6l_ww: selfhost/cmd/w6l/main.ww selfhost/cmd/w6l/sym.ww \ selfhost/cmd/w6l/obj.ww selfhost/cmd/w6l/dyn.ww \ selfhost/cmd/w6l/pass.ww selfhost/cmd/w6l/dynout.ww \ selfhost/cmd/w6l/out.ww selfhost/cmd/wcc/mem.ww \ lib/os/os.ww \ $(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \ $(LIB)/libwwrt.a | $(BIN) cd $(BIN) && ./ww build \ -I $$PWD/../../selfhost/cmd/w6l \ -I $$PWD/../../selfhost/cmd/wcc \ $$PWD/../../selfhost/cmd/w6l/main.ww mv $(BIN)/main $@ # ---- ww-side ww driver (exercised by 993_ww_ww) ------------------------ # The driver pulls in lib/os (default search path) and selfhost/cmd/wcc # (for the bump arena). It then orchestrates w6c/w6a/w6l like the C driver. $(BIN)/ww_ww: selfhost/cmd/ww/main.ww selfhost/cmd/wcc/mem.ww lib/os/os.ww \ $(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \ $(LIB)/libwwrt.a | $(BIN) cd $(BIN) && ./ww build \ -I $$PWD/../../selfhost/cmd/wcc \ $$PWD/../../selfhost/cmd/ww/main.ww mv $(BIN)/main $@ # ---- runtime (libwwrt.a, assembled by our own w6a) --------------------- $(OBJ)/rt/%.o: rt/%.s $(BIN)/w6a | $(OBJ)/rt $(BIN)/w6a -o $@ $< $(LIB)/libwwrt.a: $(RT_OBJ) | $(LIB) $(AR) rcs $@ $(RT_OBJ) # ---- directories ------------------------------------------------------- $(BIN) $(LIB) $(OBJ)/wcc $(OBJ)/ww $(OBJ)/wwdump $(OBJ)/w6c $(OBJ)/w6a $(OBJ)/w6l $(OBJ)/rt: mkdir -p $@ # ---- tests ------------------------------------------------------------- # Each phase adds a $(BIN)/test_ target; the runner walks them. TESTS = $(BIN)/test_smoke $(BIN)/test_lex $(BIN)/test_parse $(BIN)/test_check \ $(BIN)/test_w6c $(BIN)/test_w6a $(BIN)/test_w6l $(BIN)/test_arch \ $(BIN)/test_e2e $(BIN)/test_ffi $(BIN)/test_dyn $(BIN)/test_stdlib \ $(BIN)/test_selfhost $(BIN)/test_w6a_ww $(BIN)/test_w6l_ww \ $(BIN)/test_w6c_ww $(BIN)/test_ww_ww $(BIN)/test_self_rebuild \ $(BIN)/test_dyn_ww $(BIN)/test_smoke: test/wcc/000_smoke.c $(LIB)/libwcc.a | $(BIN) $(CC) $(CFLAGS) $(INCS) -o $@ $< -L$(LIB) -lwcc $(BIN)/test_lex: test/wcc/100_lex.c $(LIB)/libwcc.a | $(BIN) $(CC) $(CFLAGS) $(INCS) -o $@ $< -L$(LIB) -lwcc $(BIN)/test_parse: test/wcc/200_parse.c $(LIB)/libwcc.a | $(BIN) $(CC) $(CFLAGS) $(INCS) -o $@ $< -L$(LIB) -lwcc $(BIN)/test_check: test/wcc/300_check.c $(LIB)/libwcc.a | $(BIN) $(CC) $(CFLAGS) $(INCS) -o $@ $< -L$(LIB) -lwcc $(BIN)/test_w6c: test/wcc/400_w6c.c $(BIN)/w6c | $(BIN) $(CC) $(CFLAGS) -o $@ $< $(BIN)/test_w6a: test/wcc/500_w6a.c $(BIN)/w6c $(BIN)/w6a | $(BIN) $(CC) $(CFLAGS) -o $@ $< $(BIN)/test_w6l: test/wcc/600_w6l.c $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l | $(BIN) $(CC) $(CFLAGS) -o $@ $< $(BIN)/test_arch: test/wcc/610_arch.c $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \ $(OBJ)/rt/start.o | $(BIN) $(CC) $(CFLAGS) -o $@ $< $(BIN)/test_e2e: test/wcc/700_e2e.c $(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \ $(LIB)/libwwrt.a $(OBJ)/rt/start.o | $(BIN) $(CC) $(CFLAGS) -o $@ $< $(BIN)/test_ffi: test/wcc/800_ffi.c $(BIN)/w6c | $(BIN) $(CC) $(CFLAGS) -o $@ $< $(BIN)/test_dyn: test/wcc/810_dyn.c $(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \ $(LIB)/libwwrt.a | $(BIN) $(CC) $(CFLAGS) -o $@ $< $(BIN)/test_stdlib: test/wcc/900_stdlib.c $(BIN)/w6c | $(BIN) $(CC) $(CFLAGS) -o $@ $< $(BIN)/test_selfhost: test/wcc/990_selfhost.c $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \ $(BIN)/ww $(BIN)/wwdump $(BIN)/wwdump_ww $(LIB)/libwwrt.a | $(BIN) $(CC) $(CFLAGS) -o $@ $< $(BIN)/test_w6a_ww: test/wcc/991_w6a_ww.c $(BIN)/w6a $(BIN)/w6a_ww | $(BIN) $(CC) $(CFLAGS) -o $@ $< $(BIN)/test_w6l_ww: test/wcc/992_w6l_ww.c $(BIN)/w6l $(BIN)/w6l_ww \ $(LIB)/libwwrt.a | $(BIN) $(CC) $(CFLAGS) -o $@ $< $(BIN)/test_w6c_ww: test/wcc/994_w6c_ww.c $(BIN)/w6c_ww $(BIN)/wwdump_ww | $(BIN) $(CC) $(CFLAGS) -o $@ $< $(BIN)/test_ww_ww: test/wcc/993_ww_ww.c $(BIN)/ww $(BIN)/ww_ww \ $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l $(LIB)/libwwrt.a | $(BIN) $(CC) $(CFLAGS) -o $@ $< $(BIN)/test_self_rebuild: test/wcc/995_self_rebuild.c $(BIN)/ww_ww \ $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww $(BIN)/wwdump_ww \ $(LIB)/libwwrt.a | $(BIN) $(CC) $(CFLAGS) -o $@ $< $(BIN)/test_dyn_ww: test/wcc/996_dyn_ww.c $(BIN)/ww $(BIN)/w6l $(BIN)/w6l_ww \ $(LIB)/libwwrt.a | $(BIN) $(CC) $(CFLAGS) -o $@ $< test: all $(TESTS) @WW=$(BIN)/ww BIN=$(BIN) sh test/run install: all mkdir -p $(PREFIX)/bin $(PREFIX)/lib cp $(BIN)/ww $(PREFIX)/bin/ cp $(LIB)/libwcc.a $(PREFIX)/lib/ clean: rm -rf $(OUT) # ---- bootstrap (phase 10) ---------------------------------------------- # Four-stage self-host: Cstage (these C tools) → ww1 → ww2 → ww3 → ww4 # with cmp ww2 == ww3 and cmp ww3 == ww4. Stage 1 is wwdump_ww (the # ww-built frontend); stages 2/3/4 assemble with w6a_ww and link with # w6l_ww — every tool below the driver is now in ww. The C `ww` driver # still orchestrates the pipeline (porting it is the remaining phase-10 # work). # # Why a fourth stage? Stage 3 proves ww1 and ww2 (which differ in how # they were built) emit the same machine code. Stage 4 proves ww3 is # byte-stable when used as a compiler — i.e. the fixed point is truly # fixed, not merely a coincidental two-stage equilibrium. BS = $(OUT)/bootstrap bootstrap: all @echo "=== stage 0 (Cstage): C-built tools ===" @echo " $(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l" @echo @echo "=== stage 1: ww-built tools, used to drive stages 2/3/4 ===" @ls -l $(BIN)/wwdump_ww $(BIN)/w6a_ww $(BIN)/w6l_ww $(BIN)/ww_ww @rm -rf $(BS) && mkdir -p $(BS) @echo @echo "=== stage 2: ww2 = ww1 self-compiles main.combined.ww ===" @$(BIN)/wwdump_ww -c selfhost/cmd/wwdump/main.combined.ww > $(BS)/ww2.s @$(BIN)/w6a_ww -o $(BS)/ww2.o $(BS)/ww2.s @$(BIN)/w6l_ww -o $(BS)/ww2 $(BS)/ww2.o $(LIB)/libwwrt.a @ls -l $(BS)/ww2 @echo @echo "=== stage 3: ww3 = ww2 self-compiles main.combined.ww ===" @$(BS)/ww2 -c selfhost/cmd/wwdump/main.combined.ww > $(BS)/ww3.s @$(BIN)/w6a_ww -o $(BS)/ww3.o $(BS)/ww3.s @$(BIN)/w6l_ww -o $(BS)/ww3 $(BS)/ww3.o $(LIB)/libwwrt.a @ls -l $(BS)/ww3 @echo @echo "=== stage 4: ww4 = ww3 self-compiles main.combined.ww ===" @$(BS)/ww3 -c selfhost/cmd/wwdump/main.combined.ww > $(BS)/ww4.s @$(BIN)/w6a_ww -o $(BS)/ww4.o $(BS)/ww4.s @$(BIN)/w6l_ww -o $(BS)/ww4 $(BS)/ww4.o $(LIB)/libwwrt.a @ls -l $(BS)/ww4 @echo @echo "=== fixed-point gates ===" @cmp $(BS)/ww2.s $(BS)/ww3.s && echo " ww2.s == ww3.s ✓" @cmp $(BS)/ww2.o $(BS)/ww3.o && echo " ww2.o == ww3.o ✓ (byte-identical .o)" @cmp $(BS)/ww2 $(BS)/ww3 && echo " ww2 == ww3 ✓ (byte-identical exe)" @cmp $(BS)/ww3.s $(BS)/ww4.s && echo " ww3.s == ww4.s ✓" @cmp $(BS)/ww3.o $(BS)/ww4.o && echo " ww3.o == ww4.o ✓ (byte-identical .o)" @cmp $(BS)/ww3 $(BS)/ww4 && echo " ww3 == ww4 ✓ (byte-identical exe, ww3 is byte-stable as a compiler)" @echo @echo "BOOTSTRAP OK: ww-cgen + w6a_ww + w6l_ww reach a fixed point that holds across two iterations." @echo @echo "Phase 10 remaining work:" @echo " - delete cmd/wcc/ cmd/w6c/ cmd/w6a/ cmd/w6l/ cmd/ww/ in the final commit" @echo @echo "Already in selfhost/:" @echo " - cmd/wcc/ : ww-cgen (lex/parse/check/cgen) — bootstrap fixed point" @echo " - cmd/w6c/ : ww-w6c (lex/parse/cgen front-end) — matches wwdump_ww -c (test 994)" @echo " - cmd/w6a/ : ww-w6a (lex/parse/asm/obj) — byte-identical to C w6a (test 991)" @echo " - cmd/w6l/ : ww-w6l (linker w/ archive support) — byte-identical to C w6l (test 992)" @echo " - cmd/ww/ : ww-driver (build/run/version) — byte-identical to C ww (test 993)" # ---- nocc: bootstrap from a checked-in stage-0 binary, no cc ----------- # A fresh-checkout flow that never invokes cc. Mirrors `make bootstrap`'s # fixed-point check but uses `bootstrap/$(ARCH)/{ww,w6c,w6a,w6l}` as the # starting point and lands in $(OUT)/nocc/ so the cstage build under # $(OUT)/ stays untouched. See bootstrap/README.md and BOOTSTRAP.md. # # `make bootstrap-snapshot` populates bootstrap/$(ARCH)/ from the # currently-built wwstage so you can verify locally before deciding # to commit the binaries. ARCH ?= amd64 STAGE0 = bootstrap/$(ARCH) NOCC_OUT = $(OUT)/nocc NOCC_BIN = $(NOCC_OUT)/bin NOCC_LIB = $(NOCC_OUT)/lib NOCC_OBJ = $(NOCC_OUT)/obj bootstrap-snapshot: wwstage @mkdir -p $(STAGE0) @cp $(BIN)/ww_ww $(STAGE0)/ww @cp $(BIN)/w6c_ww $(STAGE0)/w6c @cp $(BIN)/w6a_ww $(STAGE0)/w6a @cp $(BIN)/w6l_ww $(STAGE0)/w6l @echo "snapshot: $(STAGE0)/{ww,w6c,w6a,w6l} populated from $(BIN)/*_ww" @echo " (gitignored — 'git add -f bootstrap/$(ARCH)/*' to ship)" nocc: @for f in ww w6c w6a w6l; do \ test -x $(STAGE0)/$$f || { \ echo "$@: missing $(STAGE0)/$$f"; \ echo "$@: run 'make bootstrap-snapshot' first, or read bootstrap/README.md"; \ exit 1; \ }; \ done @echo "=== nocc: starting from $(STAGE0) (no cc invoked) ===" @rm -rf $(NOCC_OUT) @mkdir -p $(NOCC_BIN) $(NOCC_LIB) $(NOCC_OBJ) @# Stage 0: drop bootstrap binaries under both natural names and @# the _ww-suffixed names the driver expects when shelling out. @for f in ww w6c w6a w6l; do \ cp $(STAGE0)/$$f $(NOCC_BIN)/$$f; \ cp $(STAGE0)/$$f $(NOCC_BIN)/$${f}_ww; \ done @# Assemble libwwrt.a using stage-0 w6a — the linker needs it for @# every wwstage-built binary in the next stage. Member order @# follows $(RT_S) so the embedded symbol table matches the @# cstage-built libwwrt.a (cstage uses ar rcs $(RT_OBJ), same @# order). @objs=""; for s in $(RT_S); do \ b=`basename $$s .s`; \ $(NOCC_BIN)/w6a -o $(NOCC_OBJ)/$$b.o $$s; \ objs="$$objs $(NOCC_OBJ)/$$b.o"; \ done; $(AR) rcs $(NOCC_LIB)/libwwrt.a $$objs @echo "=== stage 1: stage-0 rebuilds the wwstage tools from source ===" @# The driver's default lib path is $self_dir/../../lib — under @# $(NOCC_BIN) that resolves to $(NOCC_OUT)/lib (libwwrt only). @# Pass -I $(CURDIR)/lib so `use os` etc. resolve to source. @cd $(NOCC_BIN) && ./ww build \ -I $(CURDIR)/lib/ww \ -I $(CURDIR)/selfhost/cmd/wcc \ -I $(CURDIR)/lib $(CURDIR)/selfhost/cmd/w6c/main.ww && mv main w6c_ww1 @cd $(NOCC_BIN) && ./ww build -I $(CURDIR)/selfhost/cmd/w6a \ -I $(CURDIR)/selfhost/cmd/wcc -I $(CURDIR)/lib \ $(CURDIR)/selfhost/cmd/w6a/main.ww && mv main w6a_ww1 @cd $(NOCC_BIN) && ./ww build -I $(CURDIR)/selfhost/cmd/w6l \ -I $(CURDIR)/selfhost/cmd/wcc -I $(CURDIR)/lib \ $(CURDIR)/selfhost/cmd/w6l/main.ww && mv main w6l_ww1 @cd $(NOCC_BIN) && ./ww build -I $(CURDIR)/selfhost/cmd/wcc \ -I $(CURDIR)/lib $(CURDIR)/selfhost/cmd/ww/main.ww && mv main ww_ww1 @echo "=== fixed-point gates: rebuilt tools == stage-0 binaries? ===" @cmp $(NOCC_BIN)/w6c_ww1 $(STAGE0)/w6c && echo " w6c ✓" @cmp $(NOCC_BIN)/w6a_ww1 $(STAGE0)/w6a && echo " w6a ✓" @cmp $(NOCC_BIN)/w6l_ww1 $(STAGE0)/w6l && echo " w6l ✓" @cmp $(NOCC_BIN)/ww_ww1 $(STAGE0)/ww && echo " ww ✓" @echo @echo "NOCC OK: $(STAGE0)/* reproduces itself from source. cc not invoked." .PHONY: all cstage wwstage test install clean bootstrap nocc bootstrap-snapshot