# GCCdhdms 自举构建Makefile
# 作者：孙立佳
# 实现三阶段自举，最终不依赖任何外部工具链
# 自举验证：stage1和stage2二进制哈希一致即为自举成功

# 阶段0：DHDMS自带Stage0引导编译器（C实现，自举后完全零依赖，不需要Python或任何外部工具）
# 第一次引导使用Python版编译C版stage0，之后完全使用C版，不需要Python
STAGE0_C = bootstrap/stage0
ifeq ($(wildcard $(STAGE0_C)),)
HOST_CC = python bootstrap/stage0_cc.py
else
HOST_CC = $(STAGE0_C)
endif
HOST_CFLAGS =
HOST_LDFLAGS =

# 自举后的GCCdhdms编译器
DHDMS_CC = ./build/stage1/gcc
DHDMS_CFLAGS = -O2 -Iinclude -nostdlib -nostdinc -fno-builtin
DHDMS_LDFLAGS = -static -Lbuild -ldhdmsrt -lc

# 所有源文件
RT_SRCS = src/rt/dhdms_rt.c
IR_SRCS = src/ir/dhdms_ir.c
OPT_SRCS = src/opt/dhdms_ops.c src/opt/dhdms_opt.c
FE_C_SRCS = src/fe/c/dhdms_fe_c.c
BE_X86_SRCS = src/be/x86_64/dhdms_be_x86_64.c
BINUTILS_SRCS = src/binutils/dhdms_binutils.c
DRIVER_SRCS = src/driver/gcc.c
GPP_SRCS = src/driver/gpp.c

RTLIB_SRCS = rtlib/libgcc/dhdms_libgcc.c rtlib/libc/dhdms_libc.c

ALL_SRCS = $(RT_SRCS) $(IR_SRCS) $(OPT_SRCS) $(FE_C_SRCS) $(BE_X86_SRCS) $(BINUTILS_SRCS)

.PHONY: all bootstrap clean distclean check selfhost

all: bootstrap selfhost
	@echo ==============================================
	@echo GCCdhdms 自举完成！
	@echo 最终编译器: build/gcc build/g++
	@echo 运行时库: build/libdhdmsrt.a build/libc.a
	@echo ==============================================

# 阶段0：编译C版引导编译器，完全零依赖
bootstrap: $(STAGE0_C) build/bootstrap/gcc build/bootstrap/g++ build/bootstrap/libdhdmsrt.a build/bootstrap/libc.a
	@echo [Stage 0] C版Bootstrap编译器编译完成，完全零依赖

$(STAGE0_C): bootstrap/stage0.c
	@echo [Bootstrap] 编译C版引导编译器...
	python bootstrap/stage0_cc.py bootstrap/stage0.c $(STAGE0_C)
	@echo [Bootstrap] C版引导编译器编译完成，后续不再需要Python

build/bootstrap/%.o: src/rt/%.c
	@mkdir -p build/bootstrap
	$(HOST_CC) $(HOST_CFLAGS) -c $< -o $@

build/bootstrap/%.o: src/ir/%.c
	@mkdir -p build/bootstrap
	$(HOST_CC) $(HOST_CFLAGS) -c $< -o $@

build/bootstrap/%.o: src/opt/%.c
	@mkdir -p build/bootstrap
	$(HOST_CC) $(HOST_CFLAGS) -c $< -o $@

build/bootstrap/%.o: src/fe/c/%.c
	@mkdir -p build/bootstrap
	$(HOST_CC) $(HOST_CFLAGS) -c $< -o $@

build/bootstrap/%.o: src/be/x86_64/%.c
	@mkdir -p build/bootstrap
	$(HOST_CC) $(HOST_CFLAGS) -c $< -o $@

build/bootstrap/%.o: src/binutils/%.c
	@mkdir -p build/bootstrap
	$(HOST_CC) $(HOST_CFLAGS) -c $< -o $@

build/bootstrap/gcc.o: src/driver/gcc.c
	@mkdir -p build/bootstrap
	$(HOST_CC) $(HOST_CFLAGS) -c $< -o $@

build/bootstrap/gpp.o: src/driver/gpp.c
	@mkdir -p build/bootstrap
	$(HOST_CC) $(HOST_CFLAGS) -c $< -o $@

build/bootstrap/libgcc.o: rtlib/libgcc/dhdms_libgcc.c
	@mkdir -p build/bootstrap
	$(HOST_CC) $(HOST_CFLAGS) -c $< -o $@

build/bootstrap/libc.o: rtlib/libc/dhdms_libc.c
	@mkdir -p build/bootstrap
	$(HOST_CC) $(HOST_CFLAGS) -c $< -o $@

BOOT_OBJS = build/bootstrap/dhdms_rt.o build/bootstrap/dhdms_ir.o build/bootstrap/dhdms_ops.o \
            build/bootstrap/dhdms_opt.o build/bootstrap/dhdms_fe_c.o build/bootstrap/dhdms_be_x86_64.o \
            build/bootstrap/dhdms_binutils.o

build/bootstrap/gcc: $(BOOT_OBJS) build/bootstrap/gcc.o build/bootstrap/libc.o build/bootstrap/libgcc.o
	$(HOST_CC) $(HOST_LDFLAGS) $^ -o $@ -e main

build/bootstrap/g++: $(BOOT_OBJS) build/bootstrap/gpp.o build/bootstrap/libc.o build/bootstrap/libgcc.o
	$(HOST_CC) $(HOST_LDFLAGS) $^ -o $@ -e main

build/bootstrap/libdhdmsrt.a: build/bootstrap/libgcc.o
	ar rcs $@ $^

build/bootstrap/libc.a: build/bootstrap/libc.o
	ar rcs $@ $^

# 阶段1：用bootstrap编译器编译自身，得到stage1
build/stage1/gcc: bootstrap
	@echo [Stage 1] 使用bootstrap编译GCCdhdms自身...
	@mkdir -p build/stage1
	cp build/bootstrap/*.a build/stage1/
	./build/bootstrap/gcc src/driver/gcc.c $(DHDMS_CFLAGS) -c -o build/stage1/gcc.o
	@for src in $(ALL_SRCS); do \
		obj=build/stage1/`basename $$src .c`.o; \
		./build/bootstrap/gcc $$src $(DHDMS_CFLAGS) -c -o $$obj; \
	done
	./build/bootstrap/gcc build/stage1/*.o $(DHDMS_LDFLAGS) -o build/stage1/gcc
	@echo [Stage 1] Stage1编译器编译完成

build/stage1/g++: build/stage1/gcc
	./build/bootstrap/gcc src/driver/gpp.c $(DHDMS_CFLAGS) -c -o build/stage1/gpp.o
	./build/bootstrap/gcc build/stage1/gpp.o build/stage1/dhdms_*.o build/stage1/*.a $(DHDMS_LDFLAGS) -o build/stage1/g++

# 阶段2：用stage1编译器再次编译自身，得到stage2
selfhost: build/stage1/gcc build/stage1/g++
	@echo [Stage 2] 使用Stage1编译器再次编译自身，验证自举...
	@mkdir -p build/stage2
	cp build/stage1/*.a build/stage2/
	./build/stage1/gcc src/driver/gcc.c $(DHDMS_CFLAGS) -c -o build/stage2/gcc.o
	@for src in $(ALL_SRCS); do \
		obj=build/stage2/`basename $$src .c`.o; \
		./build/stage1/gcc $$src $(DHDMS_CFLAGS) -c -o $$obj; \
	done
	./build/stage1/gcc build/stage2/*.o $(DHDMS_LDFLAGS) -o build/stage2/gcc
	./build/stage1/gcc src/driver/gpp.c $(DHDMS_CFLAGS) -c -o build/stage2/gpp.o
	./build/stage1/gcc build/stage2/gpp.o build/stage2/dhdms_*.o build/stage2/*.a $(DHDMS_LDFLAGS) -o build/stage2/g++
	@echo [Stage 2] Stage2编译器编译完成
	@$(MAKE) check

# 自举验证：对比stage1和stage2哈希
check:
	@echo ==============================================
	@echo 自举验证：对比Stage1和Stage2编译器哈希...
	@Hash1=$(shell certutil -hashfile build/stage1/gcc SHA256 | findstr /v "hash")
	@Hash2=$(shell certutil -hashfile build/stage2/gcc SHA256 | findstr /v "hash")
	@echo Stage1 GCC哈希: $(Hash1)
	@echo Stage2 GCC哈希: $(Hash2)
	@if [ "$(Hash1)" = "$(Hash2)" ]; then \
		echo 自举成功！Stage1和Stage2二进制完全一致，无外部依赖！; \
		cp build/stage2/gcc build/gcc; \
		cp build/stage2/g++ build/g++; \
		cp build/stage2/*.a build/; \
	else \
		echo 自举验证失败，二进制不一致; \
		exit 1; \
	fi
	@echo ==============================================

# 测试：用自举后的编译器编译hello world
test: all
	@echo int main() { printf("Hello GCCdhdMS! 自举成功！\n"); return 0; } > build/test.c
	./build/gcc build/test.c -o build/test
	@echo 测试程序编译成功，运行：
	./build/test

clean:
	rm -rf build/bootstrap build/stage1 build/stage2 build/*.o build/*.a build/gcc build/g++ build/test build/test.c
	@echo 清理构建文件完成

distclean: clean
	rm -rf build/*
	@echo 完全清理完成
