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