boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

Makefile (11714B)


      1 # tests/Makefile — test infrastructure (suites + their build deps).
      2 #
      3 # Two ways in:
      4 #   1. `include tests/Makefile` from the top-level Makefile (REPO_ROOT
      5 #      already set). All test/build rules are emitted; the top-level's
      6 #      `test`, `image`, etc. targets resolve here.
      7 #   2. `make -C tests <target>` standalone. We detect the missing
      8 #      REPO_ROOT and re-exec the top-level Makefile, forwarding goals.
      9 #
     10 # Suites:
     11 #   test SUITE=<name>             one suite (defaults to all)
     12 #   test                          aggregate (m1pp, p1, scheme1, cc-util,
     13 #                                 cc-lex, cc-pp, cc-cg, cc, cc-libc)
     14 #   test SUITE=tcc-cc ARCH=...    self-built tcc through cc fixtures
     15 #   test SUITE=tcc-libc ARCH=...  self-built tcc through cc-libc fixtures
     16 #
     17 # Tests pin DRIVER=podman: every binary tests reach for is the
     18 # bootN-built podman variant. The seed-driver chain is exercised by
     19 # the bootstrap top-level, not the test runner.
     20 
     21 ifndef REPO_ROOT
     22 # ── Standalone invocation: delegate to top-level. ────────────────────────
     23 # `make -C tests <goals>` lands here. Forward to ../Makefile.
     24 .PHONY: __forward $(MAKECMDGOALS)
     25 __forward:
     26 	@$(MAKE) -C .. $(if $(MAKECMDGOALS),$(MAKECMDGOALS),test)
     27 $(MAKECMDGOALS): __forward ;
     28 .DEFAULT_GOAL := __forward
     29 else
     30 # ── Included from top-level: emit rules. ─────────────────────────────────
     31 
     32 # Tests always run against the podman driver's bootN outputs. The seed
     33 # driver builds an equivalent chain but boots through QEMU; that path is
     34 # validated by the top-level bootstrap, not by the test suite.
     35 TEST_DRIVER := podman
     36 
     37 # bootN/<file> path helpers — keep call sites readable.
     38 boot0 = build/$(1)/$(TEST_DRIVER)/boot0
     39 boot1 = build/$(1)/$(TEST_DRIVER)/boot1
     40 boot2 = build/$(1)/$(TEST_DRIVER)/boot2
     41 boot3 = build/$(1)/$(TEST_DRIVER)/boot3
     42 boot4 = build/$(1)/$(TEST_DRIVER)/boot4
     43 boot5 = build/$(1)/$(TEST_DRIVER)/boot5
     44 
     45 # ── tests-only container images (boot2-busybox-test, boot2-alpine-gcc) ──
     46 
     47 IMAGE_STAMP  := build/$(ARCH)/.image
     48 IMAGE_STAMPS := $(foreach a,$(ALL_ARCHES),build/$(a)/.image)
     49 
     50 .PHONY: image
     51 image: $(IMAGE_STAMP)
     52 
     53 $(IMAGE_STAMPS): build/%/.image: tests/containers/Containerfile.busybox-test
     54 	mkdir -p $(@D)
     55 	podman build --platform $(PLATFORM_$*) -t boot2-busybox-test:$* \
     56 	    -f tests/containers/Containerfile.busybox-test tests/containers/
     57 	@touch $@
     58 
     59 ALPINE_GCC_IMAGES := $(foreach a,$(ALL_ARCHES),build/$(a)/.image-alpine-gcc)
     60 
     61 $(ALPINE_GCC_IMAGES): build/%/.image-alpine-gcc: tests/containers/Containerfile.alpine-gcc
     62 	mkdir -p $(@D)
     63 	podman build --platform $(PLATFORM_$*) \
     64 	    -t boot2-alpine-gcc:$* \
     65 	    -f tests/containers/Containerfile.alpine-gcc tests/containers/
     66 	@touch $@
     67 
     68 PODMAN = podman run --rm --pull=never --platform $(PLATFORM_$(1)) \
     69     --tmpfs /tmp:size=512M \
     70     -e ARCH=$(1) \
     71     -v $(CURDIR):/work -w /work boot2-busybox-test:$(1)
     72 
     73 ALPINE_GCC = podman run --rm --pull=never --platform $(PLATFORM_$(1)) \
     74     --tmpfs /tmp:size=128M \
     75     -e ARCH=$(1) \
     76     -v $(CURDIR):/work -w /work boot2-alpine-gcc:$(1)
     77 
     78 # ── P1 backend tables (committed under P1/P1-<arch>.M1) ──────────────────
     79 
     80 P1_PRUNE_SRCS := M1pp/M1pp.P1 hex2pp/hex2pp.P1 $(wildcard tests/P1/*.P1)
     81 
     82 .PHONY: tables
     83 tables: $(foreach a,$(ALL_ARCHES),P1/P1-$(a).M1)
     84 
     85 build/%/P1/P1.M1: $(wildcard P1/gen/*.py)
     86 	mkdir -p $(@D)
     87 	python3 P1/gen/p1_gen.py --arch $* --out $@
     88 
     89 .SECONDARY: $(foreach a,$(ALL_ARCHES),build/$(a)/P1/P1.M1)
     90 
     91 P1/P1-%.M1: build/%/P1/P1.M1 bootprep/prune-p1-table.sh $(P1_PRUNE_SRCS)
     92 	sh bootprep/prune-p1-table.sh $< $@ $(P1_PRUNE_SRCS)
     93 
     94 # ── tcc-gcc: same flatten, stock gcc (sanity check) ──────────────────────
     95 
     96 TCC_PKG_INCLUDE = build/$(ARCH)/src/src/tcc/$(TCC_PKG)/include
     97 TCC_PKG_LIBDIR  = build/$(ARCH)/src/src/tcc/$(TCC_PKG)/lib
     98 
     99 TCC_GCC_BIN     := build/$(ARCH)/tcc/gcc/tcc-gcc
    100 TCC_GCC_IMAGE   := build/$(ARCH)/.image-alpine-gcc
    101 TCC_GCC_HARNESS := tcc/gcc/$(ARCH)/start.S tcc/gcc/$(ARCH)/sys_stubs.c
    102 TCC_GCC_TCC_FLAT  := build/$(ARCH)/src/src/tcc/tcc.flat.c
    103 TCC_GCC_LIBC_FLAT := build/$(ARCH)/src/src/libc/libc.flat.c
    104 
    105 $(TCC_GCC_BIN): $(TCC_GCC_TCC_FLAT) $(TCC_GCC_LIBC_FLAT) \
    106         $(TCC_GCC_HARNESS) tcc/scripts/build-tcc-gcc.sh $(TCC_GCC_IMAGE) \
    107         build/$(ARCH)/src/.stamp
    108 	mkdir -p $(@D)
    109 	podman run --rm --pull=never --platform $(PLATFORM_$(ARCH)) \
    110 	    -e ARCH=$(ARCH) \
    111 	    -v $(CURDIR):/work -w /work boot2-alpine-gcc:$(ARCH) \
    112 	    sh tcc/scripts/build-tcc-gcc.sh $@ $(TCC_GCC_TCC_FLAT) $(TCC_GCC_LIBC_FLAT)
    113 
    114 # ── tcc-cc / tcc-libc test stubs (per-arch start.S / sys_stubs.S) ────────
    115 #
    116 # Tests pull every other tcc-flow binary out of bootN now (tcc0 from
    117 # boot3, tcc1/tcc2 from boot4, libc.a/libtcc1.a from boot4/boot5). The
    118 # tcc-cc and tcc-libc trees keep a few small per-arch stubs that the
    119 # bootN chain doesn't expose as standalone .o files.
    120 
    121 HOST_CC ?= cc
    122 
    123 TCC_HARNESS_ARCHES := aarch64 amd64 riscv64
    124 
    125 HOST_CC_TARGET_aarch64 := aarch64-linux-gnu
    126 HOST_CC_TARGET_amd64   := x86_64-linux-gnu
    127 HOST_CC_TARGET = $(HOST_CC_TARGET_$(ARCH))
    128 
    129 # Assembler used to compile per-arch .S stubs into .o:
    130 #   aarch64 — boot3/tcc0 inside the busybox container (it speaks AArch64
    131 #             asm thanks to the phase-1 arm64 patches).
    132 #   riscv64 — alpine-gcc (boot3/tcc0 lacks RISC-V inline asm support).
    133 #   amd64   — host clang/cc with a Linux target triple.
    134 ifeq ($(ARCH),aarch64)
    135 TCC_ASM_DEPS := $(call boot3,$(ARCH))/tcc0 build/$(ARCH)/.image
    136 TCC_ASM       = $(call PODMAN,$(ARCH)) $(call boot3,$(ARCH))/tcc0 -nostdlib -c -o $(1) $(2)
    137 else ifeq ($(ARCH),riscv64)
    138 TCC_ASM_DEPS := build/$(ARCH)/.image-alpine-gcc
    139 TCC_ASM       = $(call ALPINE_GCC,$(ARCH)) cc -c -o $(1) -x assembler $(2)
    140 else
    141 TCC_ASM_DEPS :=
    142 TCC_ASM       = $(HOST_CC) -target $(HOST_CC_TARGET) -c -o $(1) -x assembler $(2)
    143 endif
    144 
    145 TCC_CC_START := build/$(ARCH)/tcc/cc/start.o
    146 
    147 ifeq ($(ARCH),amd64)
    148 # x86_64 va_arg intrinsics (__va_start / __va_arg). On other arches tcc
    149 # lowers va_arg without out-of-line helpers.
    150 TCC_CC_VA_LIST := build/$(ARCH)/tcc/cc/va_list.o
    151 else
    152 TCC_CC_VA_LIST :=
    153 endif
    154 
    155 TCC_LIBC_START     := build/$(ARCH)/tcc/libc/start.o
    156 TCC_LIBC_SYS_STUBS := build/$(ARCH)/tcc/libc/sys_stubs.o
    157 
    158 $(TCC_CC_START): tcc/cc/$(ARCH)/start.S $(TCC_ASM_DEPS)
    159 	mkdir -p $(@D)
    160 	$(call TCC_ASM,$@,$<)
    161 
    162 build/amd64/tcc/cc/va_list.o: \
    163         build/amd64/src/src/tcc/$(TCC_PKG)/lib/va_list.c \
    164         $(call boot3,amd64)/tcc0 build/amd64/.image \
    165         build/amd64/src/.stamp
    166 	mkdir -p $(@D)
    167 	$(call PODMAN,amd64) \
    168 	    $(call boot3,amd64)/tcc0 \
    169 	    -nostdlib -I build/amd64/src/src/tcc/$(TCC_PKG)/include \
    170 	    -D TCC_TARGET_X86_64=1 \
    171 	    -c -o $@ build/amd64/src/src/tcc/$(TCC_PKG)/lib/va_list.c
    172 
    173 $(TCC_LIBC_START): tcc/libc/$(ARCH)/start.S $(TCC_ASM_DEPS)
    174 	mkdir -p $(@D)
    175 	$(call TCC_ASM,$@,$<)
    176 
    177 $(TCC_LIBC_SYS_STUBS): tcc/libc/$(ARCH)/sys_stubs.S $(TCC_ASM_DEPS)
    178 	mkdir -p $(@D)
    179 	$(call TCC_ASM,$@,$<)
    180 
    181 # ── Suite dispatch (proxies to tests/run.sh) ─────────────────────────────
    182 
    183 SUITE ?=
    184 
    185 ifeq ($(origin ARCH),file)
    186   ARCH_FILTER :=
    187   TEST_ARCHES := $(ALL_ARCHES)
    188 else
    189   ARCH_FILTER := $(ARCH)
    190   TEST_ARCHES := $(ARCH)
    191 endif
    192 
    193 # Per-suite build dependency sets. Every entry resolves to a bootN
    194 # artifact (or, for `start.o` / `sys_stubs.o` / `va_list.o`, a small
    195 # per-arch .S stub built next to bootN binaries).
    196 
    197 TEST_M1PP_DEPS := $(foreach a,$(TEST_ARCHES), \
    198     build/$(a)/.image $(call boot1,$(a))/M1pp $(call boot1,$(a))/hex2pp \
    199     vendor/seed/$(a)/ELF.hex2)
    200 
    201 TEST_P1_DEPS := $(foreach a,$(TEST_ARCHES), \
    202     build/$(a)/.image $(call boot0,$(a))/M0 $(call boot0,$(a))/hex2 \
    203     P1/P1-$(a).M1 \
    204     $(call boot1,$(a))/M1pp $(call boot1,$(a))/hex2pp \
    205     vendor/seed/$(a)/ELF.hex2)
    206 
    207 TEST_SCHEME1_DEPS := $(foreach a,$(TEST_ARCHES), \
    208     build/$(a)/.image \
    209     $(call boot1,$(a))/M1pp $(call boot1,$(a))/hex2pp \
    210     $(call boot2,$(a))/scheme1 $(call boot2,$(a))/catm)
    211 
    212 TEST_CC_UNIT_DEPS := $(foreach a,$(TEST_ARCHES), \
    213     build/$(a)/.image \
    214     $(call boot1,$(a))/M1pp $(call boot1,$(a))/hex2pp \
    215     $(call boot2,$(a))/scheme1 $(call boot2,$(a))/catm)
    216 
    217 TEST_CC_DEPS := $(TEST_CC_UNIT_DEPS) build/cc.scm
    218 
    219 TEST_CC_LIBC_DEPS := $(TEST_CC_DEPS) \
    220     $(foreach a,$(TEST_ARCHES),$(call boot3,$(a))/libc.P1pp) \
    221     P1/entry-libc.P1pp P1/elf-end.P1pp
    222 
    223 TEST_TCC_CC_DEPS := build/$(ARCH)/.image \
    224     $(call boot4,$(ARCH))/tcc1 $(call boot4,$(ARCH))/tcc2 \
    225     $(call boot4,$(ARCH))/libtcc1.a \
    226     $(TCC_CC_START) $(TCC_CC_VA_LIST) \
    227     build/$(ARCH)/src/.stamp
    228 
    229 TEST_TCC_LIBC_DEPS := build/$(ARCH)/.image \
    230     $(call boot4,$(ARCH))/tcc1 $(call boot4,$(ARCH))/tcc2 \
    231     $(call boot4,$(ARCH))/libtcc1.a \
    232     $(call boot5,$(ARCH))/libc.a \
    233     $(TCC_LIBC_START) $(TCC_LIBC_SYS_STUBS) \
    234     $(TCC_CC_VA_LIST) \
    235     build/$(ARCH)/src/.stamp
    236 
    237 .PHONY: test
    238 test:
    239 ifeq ($(SUITE),)
    240 	@$(MAKE) --no-print-directory test SUITE=m1pp
    241 	@$(MAKE) --no-print-directory test SUITE=p1
    242 	@$(MAKE) --no-print-directory test SUITE=scheme1
    243 	@$(MAKE) --no-print-directory test SUITE=cc-util
    244 	@$(MAKE) --no-print-directory test SUITE=cc-lex
    245 	@$(MAKE) --no-print-directory test SUITE=cc-pp
    246 	@$(MAKE) --no-print-directory test SUITE=cc-cg
    247 	@$(MAKE) --no-print-directory test SUITE=cc
    248 	@$(MAKE) --no-print-directory test SUITE=cc-libc
    249 else ifeq ($(SUITE),m1pp)
    250 	@$(MAKE) --no-print-directory $(TEST_M1PP_DEPS)
    251 	sh tests/run.sh --suite=m1pp $(if $(ARCH_FILTER),--arch=$(ARCH_FILTER)) $(NAMES)
    252 else ifeq ($(SUITE),p1)
    253 	@$(MAKE) --no-print-directory $(TEST_P1_DEPS)
    254 	sh tests/run.sh --suite=p1 $(if $(ARCH_FILTER),--arch=$(ARCH_FILTER)) $(NAMES)
    255 else ifeq ($(SUITE),scheme1)
    256 	@$(MAKE) --no-print-directory $(TEST_SCHEME1_DEPS)
    257 	sh tests/run.sh --suite=scheme1 $(if $(ARCH_FILTER),--arch=$(ARCH_FILTER)) $(NAMES)
    258 else ifeq ($(filter $(SUITE),cc-util cc-lex cc-pp cc-cg),$(SUITE))
    259 	@$(MAKE) --no-print-directory $(TEST_CC_UNIT_DEPS)
    260 	sh tests/run.sh --suite=$(SUITE) $(if $(ARCH_FILTER),--arch=$(ARCH_FILTER)) $(NAMES)
    261 else ifeq ($(SUITE),cc)
    262 	@$(MAKE) --no-print-directory $(TEST_CC_DEPS)
    263 	sh tests/run.sh --suite=cc $(if $(ARCH_FILTER),--arch=$(ARCH_FILTER)) $(NAMES)
    264 else ifeq ($(SUITE),cc-libc)
    265 	@$(MAKE) --no-print-directory $(TEST_CC_LIBC_DEPS)
    266 	sh tests/run.sh --suite=cc-libc $(if $(ARCH_FILTER),--arch=$(ARCH_FILTER)) $(NAMES)
    267 else ifeq ($(SUITE),cc-ext)
    268 	@$(MAKE) --no-print-directory $(TEST_CC_LIBC_DEPS)
    269 	sh tests/run.sh --suite=cc-ext $(if $(ARCH_FILTER),--arch=$(ARCH_FILTER)) $(NAMES)
    270 else ifeq ($(SUITE),tcc-cc)
    271 	@if [ -z "$(filter $(ARCH),$(TCC_HARNESS_ARCHES))" ]; then \
    272 	    echo "tcc-cc supports ARCH in {$(TCC_HARNESS_ARCHES)} only (got '$(ARCH)')" >&2; exit 2; \
    273 	fi
    274 	@$(MAKE) --no-print-directory ARCH=$(ARCH) $(TEST_TCC_CC_DEPS)
    275 	@s2=0; s3=0; \
    276 	    sh tests/run.sh --suite=tcc-cc --arch=$(ARCH) --stage=2 $(NAMES) || s2=$$?; \
    277 	    sh tests/run.sh --suite=tcc-cc --arch=$(ARCH) --stage=3 $(NAMES) || s3=$$?; \
    278 	    [ $$s2 -eq 0 ] && [ $$s3 -eq 0 ]
    279 else ifeq ($(SUITE),tcc-libc)
    280 	@if [ -z "$(filter $(ARCH),$(TCC_HARNESS_ARCHES))" ]; then \
    281 	    echo "tcc-libc supports ARCH in {$(TCC_HARNESS_ARCHES)} only (got '$(ARCH)')" >&2; exit 2; \
    282 	fi
    283 	@$(MAKE) --no-print-directory ARCH=$(ARCH) $(TEST_TCC_LIBC_DEPS)
    284 	@s2=0; s3=0; \
    285 	    sh tests/run.sh --suite=tcc-libc --arch=$(ARCH) --stage=2 $(NAMES) || s2=$$?; \
    286 	    sh tests/run.sh --suite=tcc-libc --arch=$(ARCH) --stage=3 $(NAMES) || s3=$$?; \
    287 	    [ $$s2 -eq 0 ] && [ $$s3 -eq 0 ]
    288 else
    289 	@echo "unknown SUITE='$(SUITE)' (m1pp | p1 | scheme1 | cc-util | cc-lex | cc-pp | cc-cg | cc | cc-libc | cc-ext | tcc-cc | tcc-libc)" >&2; exit 2
    290 endif
    291 
    292 endif # REPO_ROOT