test.mk (70342B)
1 # Data-driven tests. Included from the top-level Makefile. 2 # 3 # - test-driver: aggregate alias that runs all test-driver-* targets. 4 # - test-driver-cc: narrow CLI behavior checks that do not belong to a specific 5 # frontend/linker corpus. Depends on the kit driver binary. 6 # - test-pp: aggregate alias that runs test-pp-ok and test-pp-err. 7 # - test-pp-ok: C preprocessor success cases; depends on the kit driver binary. 8 # - test-elf: ELF roundtrip harness in test/elf/; depends only on 9 # libkit.a and compiles its own test binaries against it. Skipped 10 # layers are reported (set KIT_TEST_ALLOW_SKIP=1 to allow skips). 11 # - test-ar: in-process ar reader/writer tests; depends only on 12 # libkit.a. Set KIT_AR_TEST_HOST=1 to also dump produced bytes 13 # to /tmp and run the host's `ar t` / `nm --print-armap` as a 14 # cross-check. 15 # - test-driver-ar: scenario-driven CLI harness for `kit ar`. Each 16 # case under test/ar/cases/ runs a small script and diffs stdout. 17 # Depends on the kit driver binary. 18 # - test-link: linker + JIT behavioral harness in test/link/; three paths 19 # per case (roundtrip R, ELF exec E, JIT J). Depends only on libkit.a. 20 # Set KIT_TEST_ALLOW_SKIP=1 to allow skipped layers. 21 # - test-macho: Mach-O variant of test-link; defaults to roundtrip+JIT 22 # paths because hosted Mach-O executable execution is target/SDK-specific. 23 # - test-parse: aggregate alias that runs test-parse-ok and test-parse-err. 24 # - test-parse-ok: file-driven C parser success harness in test/parse/; each 25 # case is a .c source file. Built against the public kit.h surface; 26 # reuses kit-roundtrip, link-exe-runner, and jit-runner. 27 # - test-asm: aggregate alias over the per-arch asm lanes test-asm-aa64, 28 # test-asm-x64 and test-asm-rv64. The file-driven assembler/disassembler 29 # harness in test/asm/ runs one arch per invocation (KIT_TEST_ARCH) over 30 # three sub-corpora (encode/, decode/, listing/), one mode per sub-dir. 31 # aa64 runs the full path set (incl. native exec on aa64 hosts); x64/rv64 32 # run the host-independent encode/decode/listing lanes only. See doc/ASM.md. 33 34 TEST_TARGETS = \ 35 test-cf-corpus-selftest \ 36 test-aa64-inline \ 37 test-arm32-inline \ 38 test-abi-classify \ 39 test-ar \ 40 test-asm \ 41 test-asm-aa64 \ 42 test-asm-x64 \ 43 test-asm-rv64 \ 44 test-asm-rv32 \ 45 test-toy-rv32 \ 46 test-parse-rv32 \ 47 test-disasm-complete \ 48 test-asm-roundtrip \ 49 test-asm-roundtrip-exec \ 50 test-asm-symmetry \ 51 test-asm-roundtrip-toy \ 52 test-hostas-toy \ 53 test-hostas-cross \ 54 test-diff-llvm \ 55 test-bootstrap-toy \ 56 test-bootstrap-toy-debug \ 57 test-bootstrap-toy-release \ 58 test-build \ 59 test-build-pure \ 60 test-bounce \ 61 test-cbackend \ 62 test-cg-api \ 63 test-coff \ 64 test-coff-mingw-import \ 65 test-coff-windows-o1-abi \ 66 test-coff-windows-ucrt \ 67 test-debug \ 68 test-dbg \ 69 test-driver \ 70 test-driver-ar \ 71 test-driver-cpio \ 72 test-driver-cas \ 73 test-driver-make \ 74 test-driver-cc \ 75 test-driver-targets \ 76 test-driver-native-macos-sdk \ 77 test-driver-stack-protector \ 78 test-driver-help \ 79 test-driver-build \ 80 test-driver-build-coord \ 81 test-driver-lsan \ 82 test-driver-objcopy \ 83 test-driver-objdump \ 84 test-driver-pkg \ 85 test-dist \ 86 test-selfdist \ 87 test-release-macos-aa64 \ 88 test-driver-strings \ 89 test-driver-tools \ 90 test-driver-wasm \ 91 test-gram \ 92 test-driver-gram \ 93 test-hash \ 94 test-cas-api \ 95 test-release-index \ 96 test-driver-strip \ 97 test-dwarf \ 98 test-ecosystem \ 99 test-elf \ 100 test-extlink \ 101 test-emu \ 102 test-emu-unit \ 103 test-interp \ 104 test-interp-emu \ 105 test-interp-toy \ 106 test-ir-recorder \ 107 test-isa \ 108 test-lib-deps \ 109 test-libc \ 110 test-libc-glibc \ 111 test-libc-glibc-rv64 \ 112 test-libc-musl \ 113 test-libc-musl-rv64 \ 114 test-link \ 115 test-link-compat \ 116 test-link-riscv-flags \ 117 test-link-reloc-uleb128 \ 118 test-link-reloc-desc \ 119 test-link-reloc-apply \ 120 test-link-jit-tls-relax \ 121 test-link-coff-weak-alias \ 122 test-link-dso-aa64 \ 123 test-macho \ 124 test-native-direct-target \ 125 test-opt \ 126 test-parse \ 127 test-parse-err \ 128 test-parse-ok \ 129 test-parse-rv64-wide \ 130 test-pp \ 131 test-pp-err \ 132 test-pp-ok \ 133 test-pp-file-escape \ 134 test-pp-include-next \ 135 test-rpn-lang \ 136 test-rt-headers \ 137 test-rt-runtime \ 138 test-rt-backtrace \ 139 test-link-x64 \ 140 test-rv64-inline \ 141 test-rv64-jit \ 142 test-rv32-jit \ 143 test-rv64-tls-link \ 144 test-smoke-rv64 \ 145 test-smoke-rv32 \ 146 test-smoke-arm32 \ 147 test-smoke-x64 \ 148 test-smoke-x64-macos \ 149 test-smoke-ios-app \ 150 test-toy \ 151 test-wasm \ 152 test-wasm-c \ 153 test-wasm-front \ 154 test-wasm-target \ 155 test-wasm-toy \ 156 test-x64-dbg \ 157 test-x64-inline 158 159 DEFAULT_TEST_TARGETS = \ 160 test-cf-corpus-selftest \ 161 test-driver \ 162 test-pp \ 163 test-elf \ 164 test-coff \ 165 test-ar \ 166 test-link \ 167 test-toy \ 168 test-dwarf \ 169 test-debug \ 170 test-parse \ 171 test-asm \ 172 test-asm-roundtrip \ 173 test-isa \ 174 test-aa64-inline \ 175 test-arm32-inline \ 176 test-rv64-inline \ 177 test-rv64-jit \ 178 test-rv32-jit \ 179 test-rv64-tls-link \ 180 test-emu \ 181 test-emu-unit \ 182 test-interp \ 183 test-interp-emu \ 184 test-x64-inline \ 185 test-x64-dbg \ 186 test-rt-headers \ 187 test-lib-deps \ 188 test-cg-api \ 189 test-abi-classify \ 190 test-ir-recorder \ 191 test-native-direct-target \ 192 test-opt \ 193 test-asm-symmetry \ 194 test-link-reloc-uleb128 \ 195 test-link-reloc-desc \ 196 test-link-reloc-apply \ 197 test-link-jit-tls-relax \ 198 test-link-coff-weak-alias \ 199 test-dbg \ 200 test-disasm-complete \ 201 test-macho \ 202 test-extlink \ 203 test-interp-toy \ 204 test-wasm \ 205 test-libc \ 206 test-link-x64 \ 207 test-rt-runtime \ 208 test-rt-backtrace \ 209 test-gram \ 210 test-driver-gram \ 211 test-bounce \ 212 bootstrap \ 213 test-bootstrap-toy 214 215 TIER1_TEST_TARGETS = \ 216 test-t1-harness \ 217 test-t1-build \ 218 test-t1-driver \ 219 test-t1-build-coord \ 220 test-t1-core-api \ 221 test-t1-pp \ 222 test-t1-c-front \ 223 test-t1-cg \ 224 test-t1-opt \ 225 test-t1-arch \ 226 test-t1-asm-disas \ 227 test-t1-obj \ 228 test-t1-link-jit \ 229 test-t1-cross \ 230 test-t1-rt \ 231 test-t1-debug \ 232 test-t1-emu-interp \ 233 test-t1-wasm \ 234 test-t1-tools \ 235 test-t1-dist \ 236 test-t1-gram 237 238 TIER1_PARALLEL_TARGETS = $(filter-out test-t1-build,$(TIER1_TEST_TARGETS)) 239 240 T1_LOG = test/tier1/run_logged.sh 241 242 .PHONY: test test-full test-tier1 $(TIER1_TEST_TARGETS) \ 243 $(TEST_TARGETS) windows-ucrt-sysroots hosted-glibc-images 244 245 test: test-tier1 246 247 test-tier1: 248 @$(MAKE) --no-print-directory test-t1-build 249 @$(MAKE) --no-print-directory -j$(NCPU) $(TIER1_PARALLEL_TARGETS) 250 251 test-full: $(DEFAULT_TEST_TARGETS) 252 253 test-t1-harness: 254 @$(T1_LOG) harness bash test/lib/kit_corpus_selftest.sh 255 256 test-t1-build: 257 @$(T1_LOG) build $(MAKE) --no-print-directory lib bin rt 258 259 test-t1-driver: 260 @$(T1_LOG) driver env KIT=$(abspath $(BIN)) sh test/tier1/system/driver-kitchen.sh 261 262 test-t1-build-coord: bin 263 @$(T1_LOG) build-coord env KIT=$(abspath $(BIN)) sh test/tier1/system/buildcoord-kitchen.sh 264 265 test-t1-core-api: 266 @$(T1_LOG) core-api $(MAKE) --no-print-directory test-hash test-cas-api test-release-index test-abi-classify 267 268 test-t1-pp: bin 269 @$(T1_LOG) pp env KIT=$(abspath $(BIN)) test/tier1/frontend/run-kitchen.sh pp 270 271 test-t1-c-front: bin 272 @$(T1_LOG) c-front env KIT=$(abspath $(BIN)) test/tier1/frontend/run-kitchen.sh c 273 274 test-t1-cg: bin 275 @$(T1_LOG) cg $(MAKE) --no-print-directory test-cg-api test-ir-recorder 276 @$(T1_LOG) toy env KIT=$(abspath $(BIN)) test/tier1/frontend/run-kitchen.sh toy 277 278 test-t1-opt: 279 @$(T1_LOG) opt $(MAKE) --no-print-directory test-opt-tiny-inline test-opt-inline test-opt-zero-arg 280 281 test-t1-arch: 282 @$(T1_LOG) arch $(MAKE) --no-print-directory test-isa test-aa64-inline test-x64-inline test-rv64-inline test-arm32-inline 283 284 test-t1-asm-disas: bin 285 @$(T1_LOG) asm-disas env KIT=$(abspath $(BIN)) test/tier1/objlink/asm.sh 286 287 test-t1-obj: bin 288 @$(T1_LOG) obj env KIT=$(abspath $(BIN)) test/tier1/objlink/object.sh 289 @$(T1_LOG) ar $(MAKE) --no-print-directory test-ar 290 291 test-t1-link-jit: bin 292 @$(T1_LOG) link env KIT=$(abspath $(BIN)) test/tier1/objlink/link.sh 293 @$(T1_LOG) jit-relax $(MAKE) --no-print-directory test-link-jit-tls-relax 294 @$(T1_LOG) interop env KIT=$(abspath $(BIN)) test/tier1/objlink/interop.sh 295 296 test-t1-cross: bin 297 @$(T1_LOG) cross env KIT=$(abspath $(BIN)) test/tier1/cross/run.sh 298 299 test-t1-rt: bin 300 @$(T1_LOG) rt test/tier1/system/runtime-headers.sh 301 302 test-t1-debug: 303 @$(T1_LOG) debug test/tier1/system/debug-dwarf.sh 304 305 test-t1-emu-interp: 306 @$(T1_LOG) emu-interp $(MAKE) --no-print-directory test-emu test-interp test-interp-emu 307 308 test-t1-wasm: bin 309 @$(T1_LOG) wasm env KIT=$(abspath $(BIN)) test/tier1/frontend/run-kitchen.sh wasm 310 @$(T1_LOG) wasm-driver $(MAKE) --no-print-directory test-driver-wasm 311 312 test-t1-tools: 313 @$(T1_LOG) tools test/tier1/system/tools.sh 314 315 test-t1-dist: 316 @$(T1_LOG) dist test/tier1/system/dist.sh 317 318 test-t1-gram: 319 @$(T1_LOG) gram $(MAKE) --no-print-directory test-driver-gram 320 321 # Unit-test binary build rules: two regimes (public vs internal interface). 322 include mk/test_unit.mk 323 324 # Provision the pinned per-arch container rootfs images that exec_target.sh runs 325 # kit-emitted binaries inside. This is the ONLY test step that touches the 326 # network: the cross-arch exec harnesses (toy/parse/link ... path X/E/L) run with 327 # `podman run --pull=never`, so without these images those paths SKIP. Run once, 328 # and again only after the pin in test/lib/test_images.sh changes. FORCE=1 329 # re-pulls. The images are pinned per-arch by content digest, so they coexist in 330 # local storage and can never clobber one another. 331 .PHONY: test-images 332 test-images: 333 @bash test/lib/pull_test_images.sh 334 335 # Hermetic self-test of the shared corpus harness engine (test/lib/kit_corpus.sh): 336 # asserts serial==parallel determinism, SKIP-NA, and the parallel-safety 337 # invariant (exec_target queued only on the parent, never in a worker). No 338 # kit binary / podman / qemu needed. 339 test-cf-corpus-selftest: 340 @bash test/lib/kit_corpus_selftest.sh 341 342 test-driver: test-driver-help test-driver-cc test-driver-targets test-driver-native-macos-sdk test-driver-stack-protector test-driver-build test-driver-build-coord test-driver-ar test-driver-cpio test-driver-cas test-driver-make test-driver-strip test-driver-objcopy test-driver-objdump test-driver-pkg test-driver-strings test-driver-tools test-driver-diagnostics test-driver-wasm 343 344 test-driver-help: bin 345 @KIT=$(abspath $(BIN)) sh test/driver/help_uniform.sh 346 347 test-driver-cc: bin 348 @KIT=$(abspath $(BIN)) sh test/driver/run.sh 349 350 test-driver-targets: bin 351 @KIT=$(abspath $(BIN)) sh test/driver/targets.sh 352 353 test-driver-native-macos-sdk: bin 354 @KIT=$(abspath $(BIN)) sh test/driver/native_macos_sdk.sh 355 356 test-driver-stack-protector: bin 357 @KIT=$(abspath $(BIN)) sh test/driver/stack_protector.sh 358 359 test-driver-build: bin 360 @KIT=$(abspath $(BIN)) sh test/buildcmds/run.sh 361 362 test-driver-build-coord: bin 363 @KIT=$(abspath $(BIN)) sh test/buildcoord/run.sh 364 365 BUILD_PURE_TEST_BIN = build/test/build_pure_test 366 BUILD_PUBLIC_LINK_TEST_BIN = build/test/build_public_link_test 367 368 test-build-pure: $(BUILD_PURE_TEST_BIN) 369 $(BUILD_PURE_TEST_BIN) 370 371 test-build-public-link: $(BUILD_PUBLIC_LINK_TEST_BIN) 372 $(BUILD_PUBLIC_LINK_TEST_BIN) 373 374 test-build: test-build-pure test-build-public-link test-driver-build-coord 375 376 test-rpn-lang: lib 377 @KIT_BUILD_DIR=$(abspath $(BUILD_DIR)/test/rpn-lang) sh test/rpn-lang/run.sh 378 379 ifeq ($(HOST_OS),linux) 380 test-driver-lsan: 381 @$(MAKE) test-driver RELEASE=0 BUILD_DIR=build/lsan \ 382 ASAN_OPTIONS=detect_leaks=1:halt_on_error=1:abort_on_error=1 383 else 384 test-driver-lsan: 385 @printf '%s\n' 'SKIP test-driver-lsan: LeakSanitizer requires HOST_OS=linux' 386 endif 387 388 # test-cbackend: --emit=c C-source backend, driven through three 389 # frontends — parse-runner (C), toy-runner (toy), wasm-runner (wat/wasm). 390 # Each invokes its existing runner with paths=C so a single corpus per 391 # frontend exercises both the existing backends and the C backend. 392 # Together they prove the CGTarget seam is frontend-agnostic. 393 # Unimplemented CGTarget methods report as SKIP; see doc/CBACKEND.md. 394 KIT_CBACKEND_TEST_JOBS ?= $(if $(KIT_TEST_JOBS),$(KIT_TEST_JOBS),1) 395 test-cbackend: bin 396 @KIT_TEST_JOBS=$(KIT_CBACKEND_TEST_JOBS) KIT_TEST_PATHS=C KIT_TEST_ALLOW_SKIP=1 sh test/parse/run.sh 397 @KIT_TEST_JOBS=$(KIT_CBACKEND_TEST_JOBS) KIT_TEST_PATHS=C KIT=$(abspath $(BIN)) sh test/toy/run.sh 398 @KIT_TEST_JOBS=$(KIT_CBACKEND_TEST_JOBS) KIT_TEST_PATHS=C KIT=$(abspath $(BIN)) bash test/wasm/run.sh 399 400 # test-wasm-toy: opt-in Toy -> Wasm -> JIT roundtrip. Runs the toy corpus 401 # under the W path (compile -target wasm32-none, then `kit run` the .wasm, 402 # which routes back through the lang/wasm frontend to native CG). Most cases 403 # will fail or skip today; the target exists so progress on the Wasm CGTarget 404 # is visible without putting noise into the default `test` summary. 405 # Drop `KIT_TEST_ALLOW_SKIP=1` once the corpus is mostly green. 406 test-wasm-toy: bin 407 @KIT_TEST_PATHS=W KIT_TEST_ALLOW_SKIP=1 KIT=$(abspath $(BIN)) sh test/toy/run.sh 408 409 # test-wasm-c: opt-in C -> Wasm -> JIT roundtrip, the C-frontend analogue of 410 # test-wasm-toy. Runs the test/parse corpus under the W path (compile 411 # -target wasm32-none, then `kit run -e test_main` the .wasm, which routes 412 # back through the lang/wasm frontend to native CG). The C corpus exercises 413 # far more of the language than the toy corpus, so expect many SKIPs for 414 # not-yet-implemented Wasm lowerings; the target makes that progress visible 415 # without adding noise to the default `test` summary. Drop 416 # `KIT_TEST_ALLOW_SKIP=1` once the corpus is mostly green. 417 test-wasm-c: bin $(PARSE_RUNNER) 418 @KIT_TEST_PATHS=W KIT_TEST_ALLOW_SKIP=1 KIT=$(abspath $(BIN)) bash test/parse/run.sh 419 420 test-pp: test-pp-ok test-pp-err test-pp-file-escape test-pp-include-next 421 422 test-pp-ok: bin 423 @KIT=$(abspath $(BIN)) test/pp/run.sh 424 425 test-pp-err: bin 426 @KIT=$(abspath $(BIN)) test/pp/run_errors.sh 427 428 test-pp-file-escape: bin 429 @KIT=$(abspath $(BIN)) bash test/pp/run_file_escape.sh 430 431 test-pp-include-next: bin 432 @KIT=$(abspath $(BIN)) bash test/pp/run_include_next.sh 433 434 # Best-effort kit binary build: Layer D needs build/kit, but the 435 # binary may not link until enough libkit symbols exist. The harness 436 # detects a missing binary and skips that layer; don't break test-elf 437 # when bin fails. 438 .PHONY: bin-soft 439 bin-soft: 440 -@$(MAKE) bin 2>/dev/null || true 441 442 AR_TEST_BIN = build/test/ar_test 443 444 test-ar: $(AR_TEST_BIN) 445 $(AR_TEST_BIN) 446 447 448 test-driver-ar: bin 449 @KIT=$(abspath $(BIN)) test/ar/run.sh 450 451 test-driver-cpio: bin 452 @KIT=$(abspath $(BIN)) sh test/cpio/run.sh 453 454 test-driver-cas: bin 455 @KIT=$(abspath $(BIN)) sh test/cas/run.sh 456 457 test-driver-make: bin 458 @KIT=$(abspath $(BIN)) sh test/make/run.sh 459 460 461 test-driver-strip: bin build/test/object_rewrite_test 462 @build/test/object_rewrite_test 463 @KIT=$(abspath $(BIN)) test/strip/run.sh 464 @KIT=$(abspath $(BIN)) sh test/strip/linked.sh 465 466 test-driver-objcopy: bin 467 @KIT=$(abspath $(BIN)) test/objcopy/run.sh 468 469 test-driver-objdump: bin 470 @KIT=$(abspath $(BIN)) sh test/objdump/run.sh 471 472 test-driver-pkg: bin 473 @KIT=$(abspath $(BIN)) sh test/pkg/run.sh 474 475 # test-selfdist: hermetic self-distribution suite — drives `kit update` over 476 # packages built with `kit pkg create` (the same operation `make dist` runs), 477 # entirely under a sandbox $KIT_HOME so it touches no real install. Covers 478 # offline install/flip/rollback/prune, explicit-key + wrong-key + tamper 479 # rejection, stock-minisign bootstrap verification, and the networked + 480 # monotonic channel-index path over file:// (self-skips if curl is absent). 481 test-selfdist: bin 482 @KIT=$(abspath $(BIN)) sh test/dist/run.sh 483 484 # test-release-macos-aa64: full release-artifact smoke for the runnable arm64 485 # macOS target. Drives scripts/release.sh with the non-release test key into an 486 # isolated output dir, then proves both the .kpkg update path and the .tar.gz 487 # bootstrap-unpack path produce runnable kit binaries under separate KIT_HOME 488 # roots. Opt-in because it performs a release cross-build. 489 test-release-macos-aa64: bin 490 @KIT=$(abspath $(BIN)) sh test/release/run.sh 491 492 # test-extlink: prove kit-emitted objects link with the *system* linkers 493 # (LLVM lld ELF/COFF/Mach-O personalities + Apple ld), not just kit's own 494 # `ld`. Lanes self-skip when a linker / SDK is absent, so it is safe in the 495 # default set on hosts without lld installed. 496 test-extlink: bin 497 @KIT=$(abspath $(BIN)) sh test/extlink/run.sh 498 499 # test-ecosystem: real-world C build gate. Builds pinned upstream projects 500 # (SQLite, Lua, cJSON, LZ4, miniz, tinyexpr, yyjson) from the kit cache dir with 501 # kit, links a driver that exercises real functionality, and asserts the output 502 # against a checked-in golden AND against the same program built with clang. 503 # OPT-IN (not in DEFAULT_TEST_TARGETS): it needs sources provisioned first and a 504 # host clang for the differential. Provision once with `make provision-ecosystem` 505 # (network); the gate then runs fully offline. Known kit bugs are kept RED on 506 # purpose (see test/ecosystem/known_bugs/); failing artifacts are preserved 507 # under build/ecosystem-fail/. 508 .PHONY: test-ecosystem provision-ecosystem ecosystem-speed 509 provision-ecosystem: 510 @sh scripts/ecosystem.sh fetch all 511 512 test-ecosystem: bin 513 @KIT=$(abspath $(BIN)) sh test/ecosystem/run.sh 514 515 ECO_SPEED_AR ?= $(if $(filter command line,$(origin AR)),$(AR),llvm-ar) 516 517 ecosystem-speed: 518 @if [ ! -x build/release/kit ]; then \ 519 $(MAKE) --no-print-directory RELEASE=1 bin; \ 520 fi 521 @KIT=$(abspath build/release/kit) AR=$(ECO_SPEED_AR) bash scripts/ecosystem_speed.sh 522 523 # test-dist: one-command verification of the dist subsystem (content-addressed 524 # store + signed packaging). Runs the CAS and pkg driver corpora, which cover 525 # round-trip, integrity/tamper detection, trust store, and the read-side 526 # adversarial cases (untrusted-tree path-traversal and NUL-byte rejection) in 527 # test/cas/run.sh. 528 test-dist: test-driver-cas test-driver-pkg 529 530 test-driver-strings: bin 531 @KIT=$(abspath $(BIN)) sh test/strings/run.sh 532 533 test-driver-tools: bin 534 @KIT=$(abspath $(BIN)) sh test/tools/run.sh 535 536 test-driver-diagnostics: bin 537 @KIT=$(abspath $(BIN)) sh test/diagnostics/run.sh 538 539 test-driver-wasm: bin 540 @KIT=$(abspath $(BIN)) sh test/driver-wasm/run.sh 541 542 # test-gram: gram subsystem functional + diagnostic suite. Drives `kit gram` to 543 # generate parsers/lexers/machines, compiles the generated C + the test drivers 544 # against libkit.a, runs them, and checks the error fixtures. Drops -Wpedantic 545 # (the generated C targets portable C, like the harness binaries). 546 test-gram: bin 547 @KIT=$(abspath $(BIN)) \ 548 KIT_GRAM_CC='$(CC)' \ 549 KIT_GRAM_CFLAGS='$(filter-out -Wpedantic,$(HOST_CFLAGS)) -Iinclude' \ 550 KIT_GRAM_SYSROOT='$(HOST_SYSROOT_CFLAGS)' \ 551 KIT_GRAM_LIB='$(abspath $(LIB_AR))' \ 552 KIT_GRAM_BUILD='$(abspath $(BUILD_DIR)/test/gram)' \ 553 sh test/gram/run.sh 554 555 # test-driver-gram: `kit gram` CLI-behavior smoke (stdin, --dump-sexpr, 556 # --sample-tokens, default output naming, exit codes). 557 test-driver-gram: bin 558 @KIT=$(abspath $(BIN)) \ 559 KIT_GRAM_BUILD='$(abspath $(BUILD_DIR)/test/gram-driver)' \ 560 sh test/gram/run_driver.sh 561 562 # DWARF consumer unit test: builds a hand-crafted DWARF-bearing ELF in 563 # memory and exercises every kit_dwarf_* entry. It reaches into the 564 # internal object builder to synthesize the fixture, so link individual 565 # lib objects rather than libkit.a (which hides internal symbols). 566 DWARF_TEST_BIN = build/test/dwarf_test 567 568 test-dwarf: $(DWARF_TEST_BIN) 569 $(DWARF_TEST_BIN) 570 571 572 # DWARF producer self-roundtrip unit test. Drives Debug directly, calls 573 # debug_emit, asserts the produced sections have valid DWARF 5 structure 574 # (length fields, version, address sizes, expected relocations against 575 # function symbol). Deliberately bypasses the consumer (kit_dwarf_open) 576 # so encoder bugs aren't masked by matching decoder bugs. 577 DEBUG_TEST_BIN = build/test/debug_roundtrip_unit 578 CFI_TEST_BIN = build/test/debug_cfi_unit 579 580 test-debug: $(DEBUG_TEST_BIN) $(CFI_TEST_BIN) 581 $(DEBUG_TEST_BIN) 582 $(CFI_TEST_BIN) 583 584 585 # CFI/.eh_frame producer roundtrip for aa64/rv64/x64 (validates the per-arch 586 # CIE template: code/data-align, return-address reg, CFA-init reg). 587 588 test-dbg: bin 589 @KIT=$(abspath $(BIN)) sh test/dbg/run.sh 590 591 .PHONY: test-dbg-red 592 test-dbg-red: bin 593 @KIT=$(abspath $(BIN)) DBG_STRICT_XFAIL=1 sh test/dbg/run.sh 594 595 # aa64 ISA descriptor-table unit test (doc/ASM.md phase 2). Covers 596 # every AA64Format the table maps and the alias-precedence invariant 597 # (first-match disasm picks the alias spelling over the canonical 598 # form). Internal arch/ surface — needs -Isrc. 599 AA64_ISA_TEST_BIN = build/test/aa64_isa_test 600 RV64_DECODE_TEST_BIN = build/test/rv64_decode_test 601 RV32_DECODE_TEST_BIN = build/test/rv32_decode_test 602 ARM32_DECODE_TEST_BIN = build/test/arm32_decode_test 603 604 test-isa: $(AA64_ISA_TEST_BIN) $(RV64_DECODE_TEST_BIN) $(RV32_DECODE_TEST_BIN) \ 605 $(ARM32_DECODE_TEST_BIN) 606 $(AA64_ISA_TEST_BIN) 607 $(RV64_DECODE_TEST_BIN) 608 $(RV32_DECODE_TEST_BIN) 609 $(ARM32_DECODE_TEST_BIN) 610 611 612 613 # aa64_sweep_gen: emits one representative encoding per disasm-table row for the 614 # asm<->disasm self-symmetry sweep (test/asm/symmetry.sh). Needs the internal 615 # arch/aa64/isa.h surface, so -Isrc + LIB_OBJS like the ISA unit test. 616 AA64_SWEEP_GEN = build/test/aa64_sweep_gen 617 618 # test-emu: emulator end-to-end integration test. Builds tiny in-memory rv64 619 # ELFs and runs them to their exit syscall, asserting the exit code — entirely 620 # through the PUBLIC kit_emu_* API, so it links the public archive ($(LIB_AR), 621 # whose `ld -r` step localizes internal symbols). -Isrc is only for the 622 # header-only rv64 encoders / ELF constants the in-memory ELF builders use. 623 EMU_RV64_TEST_BIN = build/test/emu_rv64_test 624 625 test-emu: $(EMU_RV64_TEST_BIN) 626 $(EMU_RV64_TEST_BIN) 627 628 $(EMU_RV64_TEST_BIN): test/emu/rv64_smoke_test.c $(UNIT_HDR_DEPS) $(LIB_AR) 629 @mkdir -p $(dir $@) 630 $(CC) $(HOST_CFLAGS) -Iinclude -Isrc -Itest test/emu/rv64_smoke_test.c $(LIB_AR) -o $@ 631 632 # RISC-V ULEB128 diff-reloc application unit test. link_reloc_apply is an 633 # internal (hidden) symbol, so link the raw lib objects like the other 634 # internal-surface unit tests rather than libkit.a. 635 RELOC_ULEB128_TEST_BIN = build/test/reloc_uleb128_unit 636 637 test-link-reloc-uleb128: $(RELOC_ULEB128_TEST_BIN) 638 $(RELOC_ULEB128_TEST_BIN) 639 640 # Relocation-descriptor migration guard (doc/plan/RELOC.md, WS-B): pins 641 # reloc_desc()/reloc_kind_* to the frozen pre-refactor width + classification 642 # behaviour across every backend arch. Internal-surface, so links the raw lib 643 # objects like the other internal unit tests. 644 RELOC_DESC_TEST_BIN = build/test/reloc_desc_test 645 646 test-link-reloc-desc: $(RELOC_DESC_TEST_BIN) 647 $(RELOC_DESC_TEST_BIN) 648 649 # Relocation byte-encoder migration guard (doc/plan/RELOC.md, WS-C): pins 650 # link_reloc_apply to the frozen pre-refactor patched bytes for every 651 # instruction-immediate kind, so partitioning the encoders per-arch stays 652 # byte-identical. Internal-surface, so links the raw lib objects. 653 RELOC_APPLY_TEST_BIN = build/test/reloc_apply_test 654 655 test-link-reloc-apply: $(RELOC_APPLY_TEST_BIN) 656 $(RELOC_APPLY_TEST_BIN) 657 658 # In-process JIT TLS Local-Exec relaxation for the Windows (COFF) TEB idiom: 659 # pins the per-arch byte rewrite (jit_tls_le_relax) for x86-64 and aarch64. The 660 # aarch64 path is also covered end-to-end on the Windows VM; this is the only 661 # automated guard for the x86-64 idiom. Internal-surface (raw lib objects). 662 JIT_TLS_RELAX_TEST_BIN = build/test/jit_tls_relax_test 663 664 test-link-jit-tls-relax: $(JIT_TLS_RELAX_TEST_BIN) 665 $(JIT_TLS_RELAX_TEST_BIN) 666 667 # COFF WEAK_EXTERNAL alias capture in read_coff: pins the aux-TagIndex decode 668 # that lets the linker resolve mingw x86_64's `_setjmp` -> `__intrinsic_setjmp` 669 # alias (the x64-windows cross-link blocker). Internal-surface (raw lib objects). 670 COFF_WEAK_ALIAS_TEST_BIN = build/test/coff_weak_alias_test 671 672 test-link-coff-weak-alias: $(COFF_WEAK_ALIAS_TEST_BIN) 673 $(COFF_WEAK_ALIAS_TEST_BIN) 674 675 # test-emu-unit: white-box unit tests for the emulator's INTERNAL units (rv64 676 # decoder, EmuAddrSpace, Linux syscall handler) that have no public API. Reaches 677 # internal symbols -> links $(LIB_OBJS) (mirrors test-interp), not the archive. 678 EMU_RV64_UNIT_TEST_BIN = build/test/emu_rv64_unit_test 679 680 test-emu-unit: $(EMU_RV64_UNIT_TEST_BIN) 681 $(EMU_RV64_UNIT_TEST_BIN) 682 683 684 # test-interp: threaded-bytecode interpreter unit smoke test. Builds tiny CG IR 685 # by hand, runs opt_run_o1_interp + interp_lower + the engine, asserts the 686 # returned value. Reaches internal opt/interp symbols -> links $(LIB_OBJS) and 687 # needs -Isrc (mirrors test-opt). 688 INTERP_SMOKE_TEST_BIN = build/test/interp_smoke_test 689 690 test-interp: $(INTERP_SMOKE_TEST_BIN) 691 $(INTERP_SMOKE_TEST_BIN) 692 693 694 # test-interp-emu: differential test of the emulator's INTERP execution mode 695 # (doc/INTERPRETER.md Phase 4). Builds a tiny rv64 ELF with SD/LD/ecall and runs 696 # it through kit_emu_run in JIT and INTERP modes (both -O1), asserting the exit 697 # codes match. Public-API only, but links $(LIB_OBJS) like test-interp to dodge 698 # the visibility-hidden archive's localized internals. 699 INTERP_EMU_TEST_BIN = build/test/rv64_interp_smoke_test 700 701 test-interp-emu: $(INTERP_EMU_TEST_BIN) 702 $(INTERP_EMU_TEST_BIN) 703 704 705 # test-interp-toy: run the toy suite's interpreter (--no-jit) path only, 706 # asserting it matches the golden exit codes (and SKIPping unimplemented ops). 707 test-interp-toy: bin 708 @KIT=$(abspath $(BIN)) KIT_TEST_PATHS=I bash test/toy/run.sh 709 710 CG_API_TEST_BIN = build/test/cg_api_test 711 CG_SWITCH_TEST_BIN = build/test/cg_switch_test 712 CG_FP_CMP_TEST_BIN = build/test/cg_fp_cmp_test 713 CG_CONTROL_TEST_BIN = build/test/cg_control_test 714 CG_CONST_TEST_BIN = build/test/cg_const_test 715 STRENGTH_REDUCE_TEST_BIN = build/test/strength_reduce_test 716 TARGET_TEST_BIN = build/test/target_test 717 HASH_TEST_BIN = build/test/hash_test 718 CAS_TEST_BIN = build/test/cas_test 719 RELEASE_INDEX_TEST_BIN = build/test/release_index_test 720 PANIC_RECOVERY_TEST_BIN = build/test/panic_recovery_test 721 ABI_CLASSIFY_TEST_BIN = build/test/abi_classify_test 722 IR_RECORDER_TEST_BIN = build/test/ir_recorder_test 723 NATIVE_DIRECT_TARGET_TEST_BIN = build/test/native_direct_target_test 724 725 test-cg-api: $(TARGET_TEST_BIN) $(CG_API_TEST_BIN) $(CG_SWITCH_TEST_BIN) \ 726 $(CG_FP_CMP_TEST_BIN) $(CG_CONTROL_TEST_BIN) \ 727 $(CG_CONST_TEST_BIN) \ 728 $(STRENGTH_REDUCE_TEST_BIN) \ 729 $(PANIC_RECOVERY_TEST_BIN) 730 $(TARGET_TEST_BIN) 731 $(CG_API_TEST_BIN) 732 $(CG_SWITCH_TEST_BIN) 733 $(CG_FP_CMP_TEST_BIN) 734 $(CG_CONTROL_TEST_BIN) 735 $(CG_CONST_TEST_BIN) 736 $(STRENGTH_REDUCE_TEST_BIN) 737 $(PANIC_RECOVERY_TEST_BIN) 738 739 test-hash: $(HASH_TEST_BIN) 740 $(HASH_TEST_BIN) 741 742 test-cas-api: $(CAS_TEST_BIN) 743 $(CAS_TEST_BIN) 744 745 test-release-index: $(RELEASE_INDEX_TEST_BIN) 746 $(RELEASE_INDEX_TEST_BIN) 747 748 test-abi-classify: $(ABI_CLASSIFY_TEST_BIN) 749 $(ABI_CLASSIFY_TEST_BIN) 750 751 752 753 754 test-ir-recorder: $(IR_RECORDER_TEST_BIN) 755 $(IR_RECORDER_TEST_BIN) 756 757 758 test-native-direct-target: $(NATIVE_DIRECT_TARGET_TEST_BIN) 759 $(NATIVE_DIRECT_TARGET_TEST_BIN) 760 761 762 test-toy: bin 763 @KIT=$(abspath $(BIN)) test/toy/run.sh 764 765 # The Toy corpus on the FreeBSD/Windows VMs (test/toy/vm.sh) is now driven by 766 # make test-cross TARGET=freebsd|windows DEPTH=full 767 # which calls test/toy/vm.sh through the harmonized portability surface. See 768 # doc/plan/PORT.md. 769 770 # test-bootstrap-toy: run the Toy corpus through the bootstrapped (self-built) 771 # stage3 kit instead of the host-built binary, so the self-hosted compiler is 772 # exercised on real codegen (not just self-reproduction like `make bootstrap`). 773 # Split per build mode: -debug runs the debug stage3, -release the release 774 # (-O1) stage3; the aggregate target runs both. 775 test-bootstrap-toy: test-bootstrap-toy-debug test-bootstrap-toy-release 776 777 test-bootstrap-toy-debug: bootstrap-debug 778 @KIT='$(abspath $(BUILD_DIR)/debug/bootstrap/stage3/kit)' test/toy/run.sh 779 780 test-bootstrap-toy-release: bootstrap-release 781 @KIT='$(abspath $(BUILD_DIR)/release/bootstrap/stage3/kit)' test/toy/run.sh 782 783 784 # Public-API inline-asm backend tests. These emit a tiny function through CG, 785 # reopen the object through the public object reader, and assert the expected 786 # instruction bytes are present in .text. 787 AA64_INLINE_TEST_BIN = build/test/aa64_inline_test 788 789 test-aa64-inline: $(AA64_INLINE_TEST_BIN) 790 $(AA64_INLINE_TEST_BIN) 791 792 793 RV64_INLINE_TEST_BIN = build/test/rv64_inline_test 794 795 test-rv64-inline: $(RV64_INLINE_TEST_BIN) 796 $(RV64_INLINE_TEST_BIN) 797 798 ARM32_INLINE_TEST_BIN = build/test/arm32_inline_test 799 800 test-arm32-inline: $(ARM32_INLINE_TEST_BIN) 801 $(ARM32_INLINE_TEST_BIN) 802 803 804 # rv64 JIT smoke test. Builds a tiny rv64 ELF .o in memory, runs it 805 # through kit_link_session in JIT-output mode, and skips native execution 806 # on non-riscv64 hosts after exercising the JIT mapping/reloc path. 807 RV64_JIT_TEST_BIN = build/test/rv64_jit_test 808 809 test-rv64-jit: $(RV64_JIT_TEST_BIN) 810 @$(RV64_JIT_TEST_BIN); rc=$$?; \ 811 if [ $$rc -eq 77 ]; then \ 812 echo " (rv64_jit_test SKIPPED on non-rv64 host)"; \ 813 exit 0; \ 814 else \ 815 exit $$rc; \ 816 fi 817 818 # rv32 JIT smoke test. Mirror of test-rv64-jit: builds a tiny rv32 ELF .o in 819 # memory, runs it through kit_link_session in JIT-output mode, and skips native 820 # execution on non-riscv32 hosts after exercising the JIT mapping/reloc path. 821 RV32_JIT_TEST_BIN = build/test/rv32_jit_test 822 823 test-rv32-jit: $(RV32_JIT_TEST_BIN) 824 @$(RV32_JIT_TEST_BIN); rc=$$?; \ 825 if [ $$rc -eq 77 ]; then \ 826 echo " (rv32_jit_test SKIPPED on non-rv32 host)"; \ 827 exit 0; \ 828 else \ 829 exit $$rc; \ 830 fi 831 832 833 # Link-only regression for rv64 TLS Local-Exec lowering (runs on any host). 834 test-rv64-tls-link: bin 835 @KIT='$(abspath $(BIN))' bash test/smoke/rv64_tls_link.sh 836 837 X64_INLINE_TEST_BIN = build/test/x64_inline_test 838 839 test-x64-inline: $(X64_INLINE_TEST_BIN) 840 $(X64_INLINE_TEST_BIN) 841 842 843 X64_DBG_TEST_BIN = build/test/x64_dbg_test 844 845 test-x64-dbg: $(X64_DBG_TEST_BIN) 846 $(X64_DBG_TEST_BIN) 847 848 # Reaches the internal arch/arch.h surface (arch_lookup, ArchDbgOps) -> links 849 # $(LIB_OBJS), not the archive, whose relocatable merge localizes non-public 850 # symbols (mirrors the aa64/rv64 arch unit tests above). 851 852 RT_HEADER_TEST_TARGETS = \ 853 aarch64-linux-gnu \ 854 x86_64-linux-gnu \ 855 riscv64-linux-gnu \ 856 aarch64-apple-darwin \ 857 x86_64-apple-darwin 858 859 test-rt-headers: bin 860 @set -e; \ 861 for target in $(RT_HEADER_TEST_TARGETS); do \ 862 out="build/test/rt-headers/$$target/smoke.o"; \ 863 mkdir -p "$$(dirname "$$out")"; \ 864 $(BIN) cc -target "$$target" -Werror -c test/rt/smoke.c -o "$$out"; \ 865 done 866 867 # Arch token -> linux rt variant target. The cross-target test harnesses link 868 # the matching LINUX runtime archive (compiler-rt-style helpers like 869 # __kit_sext64ti, __kit_assert_fail) rather than the native `rt` target, 870 # which builds only the host's own variant. Shared by the single-arch 871 # parse/asm/macho/link tests (via KIT_TEST_ARCH/TEST_RT_DEP) and by 872 # test-rt-runtime, which sweeps several arches at once. 873 KIT_TEST_ARCH ?= aa64 874 _TEST_RT_aa64 = rt-aarch64-linux 875 _TEST_RT_aarch64 = rt-aarch64-linux 876 _TEST_RT_arm64 = rt-aarch64-linux 877 _TEST_RT_x64 = rt-x86_64-linux 878 _TEST_RT_x86_64 = rt-x86_64-linux 879 _TEST_RT_amd64 = rt-x86_64-linux 880 _TEST_RT_rv64 = rt-riscv64-linux 881 _TEST_RT_riscv64 = rt-riscv64-linux 882 TEST_RT_DEP = $(_TEST_RT_$(KIT_TEST_ARCH)) 883 884 # test-rt-runtime compiles each case for the configured arches and links it 885 # against that arch's LINUX runtime archive, so it must depend on each variant 886 # (not the host `rt`). A stale per-arch archive otherwise silently breaks the 887 # link — e.g. a dropped __kit_assert_fail weak def surfaces as an undefined 888 # reference. KIT_RT_RUNTIME_ARCHES mirrors the default in test/rt/run.sh. 889 KIT_RT_RUNTIME_ARCHES ?= aa64 x64 rv64 890 RT_RUNTIME_DEPS := $(foreach a,$(KIT_RT_RUNTIME_ARCHES),$(_TEST_RT_$(a))) 891 LINK_EXE_RUNNER = build/test/link-exe-runner 892 LINK_SCRIPT_TEST_BIN = build/test/link_script_test 893 LINK_COMPAT_TEST_BIN = build/test/link_compat_test 894 895 test-rt-runtime: bin $(RT_RUNTIME_DEPS) $(LINK_EXE_RUNNER) 896 @bash test/rt/run.sh 897 898 # L3a backtrace round-trip: run a kit-compiled program that prints its own 899 # backtrace, then symbolize the captured addresses two ways — `kit addr2line` 900 # (bare addresses) and `kit symbolize` (the raw "#N 0xADDR" stream, annotated 901 # in place). Same per-arch deps as test-rt-runtime (each arch's linux rt 902 # archive + the Path-E link runner). See test/rt/addr2line.sh and 903 # doc/plan/BACKTRACE.md (L3a / WS5). 904 test-rt-backtrace: bin $(RT_RUNTIME_DEPS) $(LINK_EXE_RUNNER) 905 @bash test/rt/addr2line.sh 906 907 # Test harness binaries shared by test-elf and test-link. 908 # Declared as Make targets (not built by the run.sh scripts) so they pick 909 # up libkit.a changes deterministically. 910 # 911 # HARNESS_CFLAGS drops -Wpedantic from the normal host flags; the runners cast 912 # kit_jit_lookup's void* to a function pointer, which pedantic rejects under 913 # C11. 914 HARNESS_CFLAGS = $(filter-out -Wpedantic,$(HOST_CFLAGS)) -Iinclude -Itest 915 916 ROUNDTRIP_BIN = build/test/kit-roundtrip 917 ROUNDTRIP_BIN_MACHO = build/test/kit-roundtrip-macho 918 ROUNDTRIP_BIN_COFF = build/test/kit-roundtrip-coff 919 COFF_IMPORT_SMOKE_BIN = build/test/pe-import-smoke 920 COFF_IMPORT_MINGW_BIN = build/test/pe-import-mingw 921 COFF_DSO_FORWARDER_BIN = build/test/pe-dso-forwarder 922 COFF_MIXED_ARCHIVE_BIN = build/test/pe-mixed-archive 923 COFF_IMAGE_READ_BIN = build/test/pe-image-read 924 LLVM_MINGW_RELEASE := 20260602 925 _LLVM_MINGW_UCRT_ROOT = $(or $(KIT_LLVM_MINGW_ROOT),$(KIT_SYSROOTS_DIR)/windows/$(LLVM_MINGW_RELEASE)/ucrt) 926 LLVM_MINGW_SYSROOT_X64_MARKER = $(_LLVM_MINGW_UCRT_ROOT)/x86_64-w64-mingw32/PROVENANCE 927 LLVM_MINGW_SYSROOT_AARCH64_MARKER = $(_LLVM_MINGW_UCRT_ROOT)/aarch64-w64-mingw32/PROVENANCE 928 JIT_RUNNER = build/test/jit-runner 929 PARSE_RUNNER = build/test/parse-runner 930 ASM_RUNNER = build/test/asm-runner 931 WASM_TOOL = build/test/wasm-tool 932 933 $(ROUNDTRIP_BIN): test/elf/kit-roundtrip.c $(LIB_AR) 934 @mkdir -p $(dir $@) 935 $(CC) $(HARNESS_CFLAGS) test/elf/kit-roundtrip.c $(LIB_AR) -o $@ 936 937 # Mach-O peer of kit-roundtrip — read_macho + emit_macho. Used by 938 # test-link's path R when KIT_TEST_OBJ=macho. 939 $(ROUNDTRIP_BIN_MACHO): test/macho/kit-roundtrip-macho.c $(LIB_AR) 940 @mkdir -p $(dir $@) 941 $(CC) $(HARNESS_CFLAGS) -Isrc test/macho/kit-roundtrip-macho.c $(LIB_AR) -o $@ 942 943 # PE/COFF round-trip harness (test/coff/). All-in-one binary: builds 944 # hand-crafted ObjBuilders and asserts emit_coff/read_coff round-trip 945 # stability for both x86_64-windows and aarch64-windows. 946 $(ROUNDTRIP_BIN_COFF): test/coff/kit-roundtrip-coff.c $(LIB_OBJS) 947 @mkdir -p $(dir $@) 948 $(CC) $(HARNESS_CFLAGS) -Isrc test/coff/kit-roundtrip-coff.c $(LIB_OBJS) -o $@ 949 950 # PE import-directory smoke test (test/coff/pe-import-smoke.c). 951 # Exercises the full chain: short-import shim bytes -> link_add_obj_bytes 952 # (reclassified as DSO) -> link_resolve -> link_emit_coff. Verifies the 953 # produced PE32+ via x86_64-w64-mingw32-objdump; skips cleanly if absent. 954 $(COFF_IMPORT_SMOKE_BIN): test/coff/pe-import-smoke.c $(LIB_OBJS) 955 @mkdir -p $(dir $@) 956 $(CC) $(HARNESS_CFLAGS) -Isrc test/coff/pe-import-smoke.c $(LIB_OBJS) -o $@ 957 958 # PE import test against a real mingw archive (test/coff/pe-import-mingw.c). 959 # Exercises the long-form import-archive absorption path 960 # (link_add_archive_bytes -> classify_coff_archive_member). Skips cleanly 961 # when the mingw toolchain isn't installed. 962 $(COFF_IMPORT_MINGW_BIN): test/coff/pe-import-mingw.c $(LIB_OBJS) 963 @mkdir -p $(dir $@) 964 $(CC) $(HARNESS_CFLAGS) -Isrc test/coff/pe-import-mingw.c $(LIB_OBJS) -o $@ 965 966 # read_coff_dso forwarder-export contract (test/coff/pe-dso-forwarder.c). 967 # Synthesizes a tiny PE32+ DLL with one direct and one forwarder export 968 # and asserts both surface as OBJ_SEC_NONE globals on the ObjBuilder. 969 $(COFF_DSO_FORWARDER_BIN): test/coff/pe-dso-forwarder.c $(LIB_OBJS) 970 @mkdir -p $(dir $@) 971 $(CC) $(HARNESS_CFLAGS) -Isrc test/coff/pe-dso-forwarder.c $(LIB_OBJS) -o $@ 972 973 # Mixed-member archive (test/coff/pe-mixed-archive.c). Verifies that 974 # one archive containing both a short-import member and a long-form 975 # COFF object with a defined data symbol satisfies references through 976 # both shapes — the same composition libucrt.a uses (API-set imports 977 # alongside lib64_libucrt_extra_a-*.o helpers). 978 $(COFF_MIXED_ARCHIVE_BIN): test/coff/pe-mixed-archive.c $(LIB_OBJS) 979 @mkdir -p $(dir $@) 980 $(CC) $(HARNESS_CFLAGS) -Isrc test/coff/pe-mixed-archive.c $(LIB_OBJS) -o $@ 981 982 # PE32+ linked-image reader round-trip (test/coff/pe-image-read.c). Links a 983 # tiny PIE .exe in memory (import + base reloc), re-opens it via kit_obj_open, 984 # and asserts the neutral image view + raw escape hatch. Needs no external 985 # toolchain — runs on every host. 986 $(COFF_IMAGE_READ_BIN): test/coff/pe-image-read.c $(LIB_OBJS) 987 @mkdir -p $(dir $@) 988 $(CC) $(HARNESS_CFLAGS) -Isrc test/coff/pe-image-read.c $(LIB_OBJS) -o $@ 989 990 $(LLVM_MINGW_SYSROOT_X64_MARKER): scripts/llvm_mingw_sysroot.sh 991 @bash scripts/llvm_mingw_sysroot.sh prepare x64 992 993 $(LLVM_MINGW_SYSROOT_AARCH64_MARKER): scripts/llvm_mingw_sysroot.sh 994 @bash scripts/llvm_mingw_sysroot.sh prepare aarch64 995 996 windows-ucrt-sysroots: $(LLVM_MINGW_SYSROOT_X64_MARKER) $(LLVM_MINGW_SYSROOT_AARCH64_MARKER) 997 998 $(LINK_EXE_RUNNER): test/link/harness/link_exe_runner.c $(LIB_AR) 999 @mkdir -p $(dir $@) 1000 $(CC) $(HARNESS_CFLAGS) test/link/harness/link_exe_runner.c $(LIB_AR) -o $@ 1001 1002 $(JIT_RUNNER): test/link/harness/jit_runner.c $(LIB_AR) 1003 @mkdir -p $(dir $@) 1004 $(CC) $(HARNESS_CFLAGS) test/link/harness/jit_runner.c $(LIB_AR) -o $@ 1005 1006 $(PARSE_RUNNER): test/parse/harness/parse_runner.c $(LIB_AR) 1007 @mkdir -p $(dir $@) 1008 $(CC) $(HARNESS_CFLAGS) test/parse/harness/parse_runner.c $(LIB_AR) -o $@ 1009 1010 $(ASM_RUNNER): test/asm/harness/asm_runner.c $(LIB_AR) 1011 @mkdir -p $(dir $@) 1012 $(CC) $(HARNESS_CFLAGS) test/asm/harness/asm_runner.c $(LIB_AR) -o $@ 1013 1014 $(WASM_TOOL): test/wasm/harness/wasm_tool.c $(LIB_AR) 1015 @mkdir -p $(dir $@) 1016 $(CC) $(HARNESS_CFLAGS) -I. test/wasm/harness/wasm_tool.c $(LIB_AR) -o $@ 1017 1018 test-elf: lib bin-soft $(ROUNDTRIP_BIN) 1019 KIT_ELF_UNIT_CFLAGS='$(HOST_MODE_CFLAGS)' \ 1020 KIT_ELF_UNIT_LDFLAGS='$(HOST_MODE_LDFLAGS)' \ 1021 bash test/elf/run.sh 1022 1023 # PE/COFF round-trip harness plus optional hosted Windows smoke. The 1024 # UCRT smoke self-skips when llvm-mingw is not installed. 1025 test-coff: lib bin rt-aarch64-windows $(ROUNDTRIP_BIN_COFF) $(COFF_IMPORT_SMOKE_BIN) $(COFF_DSO_FORWARDER_BIN) $(COFF_MIXED_ARCHIVE_BIN) $(COFF_IMAGE_READ_BIN) 1026 $(ROUNDTRIP_BIN_COFF) 1027 $(COFF_IMPORT_SMOKE_BIN) 1028 $(COFF_DSO_FORWARDER_BIN) 1029 $(COFF_MIXED_ARCHIVE_BIN) 1030 $(COFF_IMAGE_READ_BIN) 1031 bash test/coff/windows-ucrt-hosted-smoke.sh 1032 bash test/coff/windows-system-dlls-smoke.sh 1033 1034 # Separate target so it can be skipped gracefully if mingw isn't 1035 # installed. The test itself self-skips on missing tooling, but the 1036 # build target only fires when explicitly requested. 1037 test-coff-mingw-import: lib $(COFF_IMPORT_MINGW_BIN) 1038 $(COFF_IMPORT_MINGW_BIN) 1039 1040 test-coff-windows-ucrt: bin rt-x86_64-pc-windows rt-aarch64-windows windows-ucrt-sysroots 1041 KIT_SYSROOT=$(abspath $(_LLVM_MINGW_UCRT_ROOT)) bash test/coff/windows-ucrt-hosted-smoke.sh 1042 KIT_SYSROOT=$(abspath $(_LLVM_MINGW_UCRT_ROOT)) bash test/coff/windows-system-dlls-smoke.sh 1043 KIT_SYSROOT=$(abspath $(_LLVM_MINGW_UCRT_ROOT)) bash test/coff/windows-o1-abi-smoke.sh 1044 1045 test-coff-windows-o1-abi: bin rt-x86_64-pc-windows rt-aarch64-windows windows-ucrt-sysroots 1046 KIT_SYSROOT=$(abspath $(_LLVM_MINGW_UCRT_ROOT)) bash test/coff/windows-o1-abi-smoke.sh 1047 1048 # Opt-in: run the COFF/PE hosted smokes against a real Windows 11 ARM64 VM, so 1049 # their per-program run lanes execute for real instead of self-skipping. On 1050 # Apple Silicon a single hvf-accelerated VM serves both targets: aarch64-windows 1051 # runs natively and x86_64-windows runs via the in-box x64 emulator, so both run 1052 # lanes point at the same endpoint. Requires a provisioned VM and a user-supplied 1053 # Windows ISO (see doc/WINDOWS.md), then boots it, waits for SSH, and runs the 1054 # smokes against it. 1055 KIT_WINDOWS_VM_USER ?= kit 1056 KIT_WINDOWS_VM_PORT ?= 2227 1057 # SSH key is left unset so windows_vm.sh uses its default in the durable cache 1058 # (~/.cache/kit/windows-vm/ssh/id_ed25519); the working disk auto-restores from 1059 # the cached golden, so a clean build/ still finds a ready VM. 1060 _WIN_VM_ENV = KIT_SYSROOT=$(abspath $(_LLVM_MINGW_UCRT_ROOT)) \ 1061 KIT_WINDOWS_VM_AARCH64=$(KIT_WINDOWS_VM_USER)@127.0.0.1 KIT_WINDOWS_VM_AARCH64_PORT=$(KIT_WINDOWS_VM_PORT) \ 1062 KIT_WINDOWS_VM_X64=$(KIT_WINDOWS_VM_USER)@127.0.0.1 KIT_WINDOWS_VM_X64_PORT=$(KIT_WINDOWS_VM_PORT) 1063 1064 test-coff-windows-vm: bin rt-x86_64-pc-windows rt-aarch64-windows windows-ucrt-sysroots 1065 bash scripts/windows_vm.sh boot 1066 bash scripts/windows_vm.sh wait-ssh 600 1067 $(_WIN_VM_ENV) bash test/coff/windows-ucrt-hosted-smoke.sh 1068 $(_WIN_VM_ENV) bash test/coff/windows-system-dlls-smoke.sh 1069 $(_WIN_VM_ENV) bash test/coff/windows-o1-abi-smoke.sh 1070 1071 # Opt-in linked-PE runtime acceptance. Both architectures execute in the one 1072 # provisioned Windows 11 ARM64 VM (x64 through the in-box compatibility layer). 1073 .PHONY: test-driver-strip-windows-vm 1074 test-driver-strip-windows-vm: bin windows-ucrt-sysroots 1075 bash scripts/windows_vm.sh boot 1076 bash scripts/windows_vm.sh wait-ssh 600 1077 $(_WIN_VM_ENV) KIT=$(abspath $(BIN)) bash test/strip/windows-vm.sh 1078 1079 # The parse/asm/macho harnesses select a cross-target via KIT_TEST_ARCH 1080 # (default aa64); the link rt dependency is resolved through the shared 1081 # _TEST_RT_<arch> map defined above (near test-rt-runtime). 1082 test-link-compat: bin $(LINK_COMPAT_TEST_BIN) 1083 $(LINK_COMPAT_TEST_BIN) 1084 KIT=$(abspath $(BIN)) sh test/link/compat-driver.sh 1085 1086 test-link-riscv-flags: bin 1087 KIT=$(abspath $(BIN)) sh test/link/riscv-flags.sh 1088 1089 test-link: bin $(ROUNDTRIP_BIN) $(ROUNDTRIP_BIN_MACHO) $(LINK_EXE_RUNNER) \ 1090 $(JIT_RUNNER) $(LINK_SCRIPT_TEST_BIN) $(LINK_COMPAT_TEST_BIN) 1091 $(LINK_SCRIPT_TEST_BIN) 1092 $(LINK_COMPAT_TEST_BIN) 1093 KIT=$(abspath $(BIN)) sh test/link/compat-driver.sh 1094 bash test/link/run.sh 1095 1096 # x64 ELF link/reloc-application coverage. test-link defaults to aa64, so 1097 # kit's x64 static-link reloc fixups (R_X64_PLT32/GOTPCREL/TPOFF/...) were 1098 # only ever run via a manual KIT_TEST_ARCH=x64 override. Opt-in (not in the 1099 # default set) because the E path links + runs under podman/qemu-x86_64; the R 1100 # path (roundtrip + reloc layout) runs on any host. 1101 test-link-x64: lib rt-x86_64-linux $(ROUNDTRIP_BIN) $(LINK_EXE_RUNNER) $(JIT_RUNNER) 1102 @KIT_TEST_ARCH=x64 KIT_TEST_PATHS=RE bash test/link/run.sh 1103 1104 # test-link-dso-aa64: ELF shared-library (DSO) harness targeting aarch64-linux. 1105 # Uses kit cc/ld to produce DSOs and freestanding consumers, runs readelf 1106 # structural checks, and executes consumers inside podman containers when 1107 # provisioned. The make target provisions the musl sysroot so the libc 1108 # dependency lane is active; direct script runs skip that lane if it is absent. 1109 # Opt-in: requires readelf; runtime checks need provisioned images. 1110 test-link-dso-aa64: bin $(MUSL_SYSROOT_MARKER) 1111 bash test/link/elf-dso-aa64/run.sh 1112 1113 test-macho: lib $(TEST_RT_DEP) $(ROUNDTRIP_BIN_MACHO) $(LINK_EXE_RUNNER) $(JIT_RUNNER) 1114 KIT_TEST_OBJ=macho \ 1115 KIT_TEST_ARCH=$${KIT_TEST_ARCH:-aa64} \ 1116 KIT_TEST_PATHS=$${KIT_TEST_PATHS:-RJ} \ 1117 KIT_TEST_ALLOW_SKIP=$${KIT_TEST_ALLOW_SKIP:-1} \ 1118 bash test/link/run.sh 1119 1120 .PHONY: test-link-macho-symbols 1121 test-link-macho-symbols: bin $(LINK_EXE_RUNNER) 1122 bash test/link/macho-symbols.sh 1123 1124 OPT_TEST_BIN = build/test/cg_ir_lower_test 1125 TINY_INLINE_TEST_BIN = build/test/tiny_inline_test 1126 REG_EFFECTS_TEST_BIN = build/test/reg_effects_test 1127 LOCATION_MIR_TEST_BIN = build/test/location_mir_test 1128 COMBINE_CSE_TEST_BIN = build/test/combine_cse_test 1129 NATIVE_EMIT_FRAME_DST_TEST_BIN = build/test/native_emit_frame_dst_test 1130 FRAME_VALUE_BACKEND_TEST_BIN = build/test/frame_value_backend_test 1131 NATIVE_PART_CHUNK_TEST_BIN = build/test/native_part_chunk_test 1132 1133 test-opt: bin $(OPT_TEST_BIN) $(REG_EFFECTS_TEST_BIN) $(LOCATION_MIR_TEST_BIN) $(COMBINE_CSE_TEST_BIN) $(NATIVE_EMIT_FRAME_DST_TEST_BIN) $(FRAME_VALUE_BACKEND_TEST_BIN) $(NATIVE_PART_CHUNK_TEST_BIN) test-opt-tiny-inline test-opt-inline test-opt-zero-arg test-opt-static-prune-aa64 test-opt-aa64-tail test-opt-aa64-apple-varargs test-opt-x64-win-tail-sret test-opt-prologue-tier test-opt-whole-program-inline test-opt-lto-phase1 test-opt-redundant-copy-ext test-opt-redundant-frame-sub test-opt-o1-branch-cleanup test-opt-macho-block-alt-entry test-opt-hot-slot-order test-opt-o1-remat test-opt-aa64-x29-bottom test-opt-o1-coalesce test-opt-o1-switch-imm test-opt-o1-inline-cap test-opt-rv64-far-slot test-opt-o1-cmp-imm test-opt-o1-stack-dse test-opt-arm32-emit-temp-pressure test-opt-o1-local-cse test-opt-o1p-aa64 test-opt-o1p-const-divmul test-opt-o1p-combine test-opt-o1p-rider 1134 $(OPT_TEST_BIN) 1135 $(REG_EFFECTS_TEST_BIN) 1136 $(LOCATION_MIR_TEST_BIN) 1137 $(COMBINE_CSE_TEST_BIN) 1138 $(NATIVE_EMIT_FRAME_DST_TEST_BIN) 1139 $(FRAME_VALUE_BACKEND_TEST_BIN) 1140 $(NATIVE_PART_CHUNK_TEST_BIN) 1141 1142 1143 # Structural disasm check: the -O1 redundant copy / extension folds 1144 # (addr_of[base+0] -> copy, same-width convert -> copy, zext-of-load -> copy). 1145 .PHONY: test-opt-redundant-copy-ext 1146 test-opt-redundant-copy-ext: bin 1147 @KIT=$(abspath $(BIN)) bash test/opt/redundant_copy_ext.sh 1148 1149 # Structural disasm check: the -O1 local frame-address sub-CSE (a back-to-back 1150 # rebuild of the same frame/GOT address is dropped while the holder is live). 1151 .PHONY: test-opt-redundant-frame-sub 1152 test-opt-redundant-frame-sub: bin 1153 @KIT=$(abspath $(BIN)) bash test/opt/redundant_frame_sub.sh 1154 1155 # Structural+behavioral check: the one-pass O1 branch cleanup + constant 1156 # cmp_branch folding (same-target collapse, x==x fold, computed-goto preserved). 1157 .PHONY: test-opt-o1-branch-cleanup 1158 test-opt-o1-branch-cleanup: bin 1159 @KIT=$(abspath $(BIN)) bash test/opt/o1_branch_cleanup.sh 1160 1161 .PHONY: test-opt-macho-block-alt-entry 1162 test-opt-macho-block-alt-entry: bin $(ROUNDTRIP_BIN_MACHO) 1163 @KIT=$(abspath $(BIN)) bash test/opt/macho_block_alt_entry.sh 1164 1165 # Structural disasm check: hot-slot-low frame ordering keeps the hottest spill 1166 # slots in cheap displacement range (x64 disp8, rv64 imm12 single-instruction). 1167 .PHONY: test-opt-hot-slot-order 1168 test-opt-hot-slot-order: bin 1169 @KIT=$(abspath $(BIN)) bash test/opt/hot_slot_order.sh 1170 1171 # Structural disasm check: O1 rematerialization recomputes cheap spilled values 1172 # (small load_imm, addr_of[local]) at the use instead of reloading from a slot. 1173 .PHONY: test-opt-o1-remat 1174 test-opt-o1-remat: bin 1175 @KIT=$(abspath $(BIN)) bash test/opt/o1_remat.sh 1176 1177 # Structural disasm check: aa64 x29-at-bottom known-frame layout addresses every 1178 # spill slot as positive ldr/str [x29,#k] (or add-build) -- no sub xN,x29,# at O1. 1179 .PHONY: test-opt-aa64-x29-bottom 1180 test-opt-aa64-x29-bottom: bin 1181 @KIT=$(abspath $(BIN)) bash test/opt/aa64_x29_bottom.sh 1182 1183 # Behavioral disasm check: linear O1 move coalescing removes copy-chain movs and 1184 # preserves the imm-through-copy fold (the explicit opt_o1_coalescing flag). 1185 .PHONY: test-opt-o1-coalesce 1186 test-opt-o1-coalesce: bin 1187 @KIT=$(abspath $(BIN)) bash test/opt/o1_coalesce.sh 1188 1189 # Structural disasm check: O1 switch chains compare case values as immediates 1190 # (cmp wN,#k) instead of materializing each into a scratch; selector stays pinned. 1191 .PHONY: test-opt-o1-switch-imm 1192 test-opt-o1-switch-imm: bin 1193 @KIT=$(abspath $(BIN)) bash test/opt/o1_switch_imm.sh 1194 1195 # Behavioral check: the O1 whole-program inliner backs off inlining into an 1196 # already-huge / high-pressure caller, while small + always_inline still fuse. 1197 .PHONY: test-opt-o1-inline-cap 1198 test-opt-o1-inline-cap: bin 1199 @KIT=$(abspath $(BIN)) bash test/opt/o1_inline_cap.sh 1200 1201 # Structural disasm check (rv64): after W1.0 hot-slot ordering, hot frame slots 1202 # are single-instruction ld/sd off(s0) within the imm12 window -- no far-slot 1203 # lui;addiw;add rebuilds in hot code (O1.md W1.2 -- assessment, no codegen change). 1204 .PHONY: test-opt-rv64-far-slot 1205 test-opt-rv64-far-slot: bin 1206 @KIT=$(abspath $(BIN)) bash test/opt/rv64_far_slot.sh 1207 1208 # Structural disasm check: O1 folds a load_imm feeding a cmp into cmp #imm, and 1209 # merges add #k; ldr [#j] into ldr [#k+j] when the offset is legal (O1.md W6). 1210 .PHONY: test-opt-o1-cmp-imm 1211 test-opt-o1-cmp-imm: bin 1212 @KIT=$(abspath $(BIN)) bash test/opt/o1_cmp_imm.sh 1213 1214 # Behavioral check: same-block stack dead-store elimination is correct (deletes 1215 # a fully-overwritten spill store, preserves stores across reads/barriers, 1216 # never touches volatile/atomic) (O1.md W8). 1217 .PHONY: test-opt-o1-stack-dse 1218 test-opt-o1-stack-dse: bin 1219 @KIT=$(abspath $(BIN)) bash test/opt/o1_stack_dse.sh 1220 1221 # Compile-only ARMv7-M pressure guard: location MIR leaves spill values in 1222 # frame homes, and the native emitter must stage operand-facing values from its 1223 # explicit r0-r3 bank without borrowing backend-private IP/LR. 1224 .PHONY: test-opt-arm32-emit-temp-pressure 1225 test-opt-arm32-emit-temp-pressure: bin 1226 @KIT=$(abspath $(BIN)) bash test/opt/arm32_emit_temp_pressure.sh 1227 1228 # Behavioral+structural check: same-block redundant-load/expression CSE reuses 1229 # the last load/compute, but never across a may-alias store, call, or volatile. 1230 .PHONY: test-opt-o1-local-cse 1231 test-opt-o1-local-cse: bin 1232 @KIT=$(abspath $(BIN)) bash test/opt/o1_local_cse.sh 1233 1234 # Structural check (aa64): L3 widens AGG_SET zero-init to wide stores (no long 1235 # strb run); L10 elides the frame on no-spill leaf functions (O1-PATTERNS L3/L10). 1236 .PHONY: test-opt-o1p-aa64 1237 test-opt-o1p-aa64: bin 1238 @KIT=$(abspath $(BIN)) bash test/opt/o1p_aa64.sh 1239 1240 # Structural check: constant-operand div/mul folds (sizeof/sizeof, SIZE_MAX 1241 # guard, /1) while divide-by-zero / runtime divisors keep the op (O1-PATTERNS L9). 1242 .PHONY: test-opt-o1p-const-divmul 1243 test-opt-o1p-const-divmul: bin 1244 @KIT=$(abspath $(BIN)) bash test/opt/o1p_const_divmul.sh 1245 1246 # Structural+behavioral check: L1 store->load forwarding, L6 sxt-after-load drop, 1247 # L2 cmp;cset;cbnz->cmp_branch fusion, L4 double-cset drop, L5 copy coalescing 1248 # (O1-PATTERNS L1/L2/L4/L5/L6). Red-green degrades to green-only without KIT_BASE. 1249 .PHONY: test-opt-o1p-combine 1250 test-opt-o1p-combine: bin 1251 @KIT=$(abspath $(BIN)) bash test/opt/o1p_combine.sh 1252 1253 # Structural+correctness check: L7 folds a single-use shift into the ALU op 1254 # (add xD,xB,xS,lsl#k); L8 folds a sxtw/uxtw index into the addressing mode 1255 # ([Xb,Wm,sxtw#s]); aa64 only, multiply-used not folded (O1-PATTERNS L7/L8). 1256 .PHONY: test-opt-o1p-rider 1257 test-opt-o1p-rider: bin 1258 @KIT=$(abspath $(BIN)) bash test/opt/o1p_rider.sh 1259 1260 1261 test-opt-tiny-inline: bin $(TINY_INLINE_TEST_BIN) 1262 $(TINY_INLINE_TEST_BIN) 1263 1264 1265 # Behavioral disasm check: tiny callee `bl` disappears from its caller at -O1. 1266 test-opt-inline: bin 1267 @KIT=$(abspath $(BIN)) bash test/opt/run.sh 1268 1269 # Behavioral disasm check: a pointer-typed null call arg is not routed through 1270 # a scratch temp at -O1 (PERCALL.md item 3, "zero through a temp"). 1271 test-opt-zero-arg: bin 1272 @KIT=$(abspath $(BIN)) bash test/opt/zero_arg.sh 1273 1274 .PHONY: test-opt-static-prune-aa64 1275 test-opt-static-prune-aa64: bin 1276 @KIT=$(abspath $(BIN)) bash test/opt/static_prune_aa64.sh 1277 1278 .PHONY: test-opt-aa64-tail 1279 test-opt-aa64-tail: bin 1280 @KIT=$(abspath $(BIN)) bash test/opt/aa64_tail_call.sh 1281 1282 .PHONY: test-opt-aa64-apple-varargs 1283 test-opt-aa64-apple-varargs: bin 1284 @KIT=$(abspath $(BIN)) bash test/opt/aa64_apple_varargs.sh 1285 1286 .PHONY: test-opt-x64-win-tail-sret 1287 test-opt-x64-win-tail-sret: bin 1288 @KIT=$(abspath $(BIN)) bash test/opt/x64_win_tail_sret.sh 1289 1290 # Structural disasm check: the -O1 known-frame prologue cost-model tiers 1291 # (aa64 reference + ported x64 slim/red-zone and rv64 leaf shapes). 1292 .PHONY: test-opt-prologue-tier 1293 test-opt-prologue-tier: bin 1294 @KIT=$(abspath $(BIN)) bash test/opt/prologue_tier.sh 1295 1296 # Whole-program (LTO Phase 0) cross-function inlining: a small static callee 1297 # fuses into its caller at -O1 on every arch, and opt_inline actually fires. 1298 .PHONY: test-opt-whole-program-inline 1299 test-opt-whole-program-inline: bin 1300 @KIT=$(abspath $(BIN)) bash test/opt/whole_program_inline.sh 1301 1302 .PHONY: test-opt-lto-phase1 1303 test-opt-lto-phase1: bin 1304 @KIT=$(abspath $(BIN)) bash test/opt/lto_phase1.sh 1305 1306 test-parse: test-parse-ok test-parse-err 1307 1308 test-parse-ok: lib $(TEST_RT_DEP) $(PARSE_RUNNER) $(ROUNDTRIP_BIN) $(LINK_EXE_RUNNER) $(JIT_RUNNER) 1309 bash test/parse/run.sh 1310 1311 test-parse-err: lib $(PARSE_RUNNER) 1312 sh test/parse/run_errors.sh 1313 1314 # test-asm: aggregate alias running every per-arch asm lane (aa64 + x64 + rv64) 1315 # so `make test` covers all three through one target. The harness runs one arch 1316 # per invocation (KIT_TEST_ARCH); each lane scopes its scratch per arch, so 1317 # the prerequisites are safe to run in parallel under `make -j`. 1318 test-asm: test-asm-aa64 test-asm-x64 test-asm-rv64 test-asm-rv32 1319 1320 # test-asm-aa64: the reference lane. aa64 is the default cross-target, and on 1321 # aa64 hosts the exec paths (D/E/J) run natively, so it uses the full default 1322 # path set (HTLDJE). The Makefile owns the harness binaries so they inherit host 1323 # flags consistently with the rest of the test suite. 1324 test-asm-aa64: lib $(TEST_RT_DEP) $(ASM_RUNNER) $(LINK_EXE_RUNNER) $(JIT_RUNNER) 1325 @KIT_TEST_ARCH=aa64 bash test/asm/run.sh 1326 1327 # x64/rv64 exercise the encode (H), decode (T) and listing (L) corpora on any 1328 # host: H/T/L need no native execution (they only produce/compare bytes), so the 1329 # exec paths (D/E/J) are deliberately excluded and left to the smoke/qemu 1330 # targets. 1331 test-asm-x64: lib $(ASM_RUNNER) 1332 @KIT_TEST_ARCH=x64 KIT_TEST_PATHS=HTL bash test/asm/run.sh 1333 test-asm-rv64: lib $(ASM_RUNNER) 1334 @KIT_TEST_ARCH=rv64 KIT_TEST_PATHS=HT bash test/asm/run.sh 1335 # riscv32-none-elf is freestanding (no qemu-user exec lane), so like rv64 it 1336 # runs the host-independent encode (H) + decode (T) lanes only. The rv32_* 1337 # goldens use a no-compressed ISA so encodings stay a stable 4 bytes. 1338 test-asm-rv32: lib $(ASM_RUNNER) 1339 @KIT_TEST_ARCH=rv32 KIT_TEST_PATHS=HT bash test/asm/run.sh 1340 1341 # test-toy-rv32: the rv32 cross lane (path X) of the Toy corpus, scoped to the 1342 # rv32 arch only. test/toy/run.sh's cross_one_rv32 compiles each case with 1343 # `kit cc -target riscv32-none-elf` and runs the freestanding ELF bare-metal 1344 # under qemu-system-riscv32 via test/lib/exec_bare.sh (the qemu exit code 1345 # is the exit-code oracle). Self-skips per case when the rv32 toolchain 1346 # (clang riscv32 + qemu-system-riscv32) is absent. The corpus is green; this 1347 # lane is opt-in (not in DEFAULT_TEST_TARGETS) because it needs that toolchain, 1348 # matching the rv64 cross lanes. The only non-passing cases are intentionally 1349 # unsupported on rv32 (__int128, binary128 long double, LP64-data-model 1350 # assumptions, aa64-only intrinsics) and carry committed .rv32.skip sidecars. 1351 test-toy-rv32: bin rt-riscv32-elf-hardfloat 1352 @KIT=$(abspath $(BIN)) KIT_TOY_CROSS_ARCHS=rv32 KIT_TEST_PATHS=X \ 1353 test/toy/run.sh 1354 1355 # test-parse-rv32: the C-parser corpus run for riscv32-none-elf, exec lane (E) 1356 # only. parse-runner --emit -> kit ld + start crt -> qemu-system-riscv32 1357 # (test/parse/run.sh's rv32 freestanding E path via exec_bare.sh). Models 1358 # test-parse-rv64-wide; opt-in (needs the rv32 toolchain/qemu), so excluded 1359 # from DEFAULT_TEST_TARGETS, matching test-parse-rv64-wide. The corpus is green; 1360 # the only skips are intentionally-unsupported cases (__int128, binary128 long 1361 # double, LP64-data-model assumptions) with committed .rv32.skip sidecars. 1362 test-parse-rv32: lib rt-riscv32-elf-hardfloat $(PARSE_RUNNER) $(ROUNDTRIP_BIN) \ 1363 $(LINK_EXE_RUNNER) 1364 @KIT_TEST_ARCH=rv32 KIT_TEST_PATHS=E bash test/parse/run.sh 1365 1366 # Codegen round-trip completeness (doc/ASM_ROUNDTRIP_TESTING.md). These drive 1367 # the `kit` binary itself (cc -S / as / objdump) over a C corpus rather than 1368 # a hand-written asm corpus, so coverage tracks codegen automatically. 1369 # 1370 # test-disasm-complete L0: cc -S must decode every in-function word 1371 # (no `.inst` markers). Host-independent, no exec. 1372 # test-asm-roundtrip L0+L1: also assert cc -c bytes/relocs == cc -S | as. 1373 # test-asm-roundtrip-exec L0+L1+L2: also run direct vs round-tripped object 1374 # and compare exit codes (native arch; opt-in). 1375 # 1376 # Vertical slice: aa64 only for now; L1/L2 run at -O1 (branch-free), L0 at both 1377 # opt levels. Broadening to -O0, other arches, and the default suite is tracked 1378 # in doc/ASM_ROUNDTRIP_TESTING.md once -S symbolization (Phase 2) lands. 1379 test-disasm-complete: bin 1380 @KIT_TEST_ARCH=aa64 KIT_TEST_OPTS="O0 O1" KIT_TEST_PATHS=0 \ 1381 bash test/asm/roundtrip.sh 1382 test-asm-roundtrip: bin 1383 @KIT_TEST_ARCH=aa64 KIT_TEST_OPTS="O0 O1" KIT_TEST_PATHS=01 \ 1384 bash test/asm/roundtrip.sh 1385 test-asm-roundtrip-exec: bin $(JIT_RUNNER) 1386 @KIT_TEST_ARCH=aa64 KIT_TEST_OPTS="O0 O1" KIT_TEST_PATHS=012 \ 1387 bash test/asm/roundtrip.sh 1388 1389 # test-asm-symmetry: asm<->disasm self-symmetry sweep (aa64). Decode-side sweeps 1390 # every disasm-table form (decode->encode->decode fixed point); encode-side 1391 # asserts every byte the assembler emits over the encode corpus is decodable. 1392 # Catches encode/decode asymmetries the codegen round-trip can't reach (e.g. a 1393 # form one tool handles and the other doesn't). Host-independent, no exec. 1394 test-asm-symmetry: $(ASM_RUNNER) $(AA64_SWEEP_GEN) 1395 @bash test/asm/symmetry.sh 1396 1397 # test-diff-llvm: differential cross-check of kit against llvm (aa64), as a 1398 # second oracle. Encode lane: kit as vs llvm-mc bytes over the encode corpus. 1399 # Disasm lane: cc -c bytes vs llvm-mc of cc -S (validates kit's disassembler; 1400 # the benign same-section-call reloc-vs-resolve difference is recognized). 1401 # Opt-in; skips cleanly when llvm-mc is absent. 1402 test-diff-llvm: bin 1403 @KIT_TEST_OPTS="O0 O1" bash test/asm/diff_llvm.sh 1404 1405 # test-asm-roundtrip-toy: L2 exec round-trip over the Toy corpus (native arch). 1406 # Reuses the ~150 toy cases (full CG op set, exit-code oracle) for free 1407 # round-trip coverage: kit cc -S | kit as | kit run, exit must match. 1408 # Opt-in; native target. Found a real miscompile (dropped .inst) the hand 1409 # corpus never reached. 1410 test-asm-roundtrip-toy: bin 1411 @bash test/asm/roundtrip_toy.sh 1412 1413 # test-hostas-toy: feed one native `cc -S` to BOTH kit's own `as` and clang (a 1414 # third-party host assembler), link + run each, and assert the toy exit-code 1415 # oracle. Only the assembler differs between the two lanes, so the clang lane is 1416 # the real test: a standard assembler can't paper over a private-dialect quirk 1417 # the way kit's own `as` can (cf. test/asm/diff_llvm.sh, but by execution). 1418 # cc -S is now object-format-aware, so the native Mach-O clang lane GATES by 1419 # default (both lanes 312/0); KIT_HOSTAS_ENFORCE_CLANG=0 demotes it to XFAIL. 1420 # Opt-in; skips cleanly if clang is absent. 1421 test-hostas-toy: bin 1422 @bash test/asm/hostas_toy.sh 1423 1424 # test-hostas-cross: the same two-assembler-by-execution idea as test-hostas-toy, 1425 # but CROSS — `cc -S -target <triple>` for ELF Linux arches (aarch64/x86_64/ 1426 # riscv64), assembled by kit-as AND clang, linked static (+ the start.c crt) 1427 # with kit ld, and run under podman/qemu via test/lib/exec_target.sh. Each 1428 # target self-skips unless the host has a clang cross target, a runner, a 1429 # working `cc -S | kit as` for that arch, and a passing bounded exec smoke — 1430 # so it runs green on whatever the host supports (aarch64-linux today; x86_64 1431 # pends the x64 cc -S symbolizer, riscv64 pends a working rv64 user-mode 1432 # emulator). Opt-in; skips cleanly if clang/podman are absent. 1433 test-hostas-cross: bin 1434 @bash test/asm/hostas_cross.sh 1435 1436 test-wasm: test-wasm-front test-wasm-target test-wasm-toy 1437 1438 test-wasm-front: bin $(WASM_TOOL) $(LINK_EXE_RUNNER) $(JIT_RUNNER) 1439 bash test/wasm/run.sh 1440 1441 # test-wasm-target: structural checks on `kit cc -target wasm32-none` 1442 # output. test/wasm-target/run.sh is a Type C corpus harness whose lanes each 1443 # compile a tiny C or toy fixture and assert a property of the produced module 1444 # bytes (inline-asm opcodes, memory.copy/fill opcodes, exported "memory", 1445 # (import ...) decls). Opt-in: not in the default `test` target because the 1446 # checks depend on the bulk-memory + (import ...) backend work landing first. 1447 test-wasm-target: bin 1448 @KIT=$(abspath $(BIN)) bash test/wasm-target/run.sh 1449 1450 # test-smoke-x64: phase-1 sanity check for the multi-arch bring-up. Builds a 1451 # tiny freestanding x86_64 ELF with clang --target=x86_64-linux-gnu and 1452 # runs it through test/lib/exec_target.sh's podman/qemu pipeline, 1453 # proving the harness end-to-end before any kit-emitted x64 bytes 1454 # exist. Excluded from the default `test` target because it needs 1455 # podman + lld; opt-in via `make test-smoke-x64`. 1456 test-smoke-x64: 1457 bash test/smoke/x64.sh 1458 1459 # test-smoke-x64-macos: end-to-end check of kit's OWN x86_64 Mach-O 1460 # compile→link→execute path. kit compiles + links a hello-world to an 1461 # x86_64-macos Mach-O executable (driving the __stubs/__got import path) and 1462 # runs it via Rosetta 2 on an Apple-silicon host, asserting stdout + exit 1463 # code. Excluded from the default `test` target because it needs a Darwin 1464 # host with Rosetta + a macOS SDK; opt-in via `make test-smoke-x64-macos`. 1465 test-smoke-x64-macos: 1466 bash test/smoke/x64_macos.sh 1467 1468 # test-smoke-ios-app: C-only UIKit smoke for the iOS simulator. It compiles 1469 # test/smoke/ios_app.c with kit, links UIKit/Foundation/CoreGraphics SDK stubs 1470 # into an arm64 iOS simulator Mach-O, bundles and ad-hoc signs a minimal .app. 1471 # Set KIT_IOS_SIM_LAUNCH=1 with a booted simulator to install and launch it. 1472 test-smoke-ios-app: 1473 bash test/smoke/ios_app.sh 1474 1475 # test-smoke-rv64: phase-2 counterpart of test-smoke-x64. Builds a 1476 # tiny freestanding riscv64 ELF with clang --target=riscv64-linux-gnu 1477 # and runs it through test/lib/exec_target.sh, proving the rv64 lane 1478 # of the harness end-to-end before any kit-emitted rv64 bytes 1479 # exist. Excluded from the default `test` target because it needs 1480 # qemu-riscv64 (or podman with riscv64 emulation) + lld; opt-in via 1481 # `make test-smoke-rv64`. 1482 test-smoke-rv64: 1483 bash test/smoke/rv64.sh 1484 1485 # test-smoke-rv32: behavioral oracle for riscv32-none-elf codegen under 1486 # qemu-system-riscv32 (ilp32f + ilp32 lanes, i64 + soft-float). Skips if the 1487 # rv32 toolchain/qemu prerequisites are absent (see test/lib/check_rv32_env.sh). 1488 test-smoke-rv32: 1489 bash test/smoke/rv32.sh 1490 1491 # test-smoke-arm32: behavioral oracle for arm-none-eabi (Cortex-M3, Thumb-2) 1492 # codegen under qemu-system-arm -machine mps2-an385 (single soft-float lane, 1493 # i64 + soft-double + a <=4-int-arg call + a switch). Skips if the arm32 1494 # toolchain/qemu prerequisites are absent (see test/lib/check_arm32_env.sh). 1495 # The macro lane (arm32_macros.sh) verifies the -march/-mcpu/-mfpu/-mfloat-abi 1496 # __ARM_* predefines via a #error-guarded compile; it needs only `kit` (and 1497 # host clang, when present, for the cross-check) — no qemu/lld. 1498 test-smoke-arm32: 1499 bash test/smoke/arm32_macros.sh 1500 bash test/smoke/arm32.sh 1501 1502 # The whole-toolchain bare-metal smoke (compile + assemble reset stub + link + 1503 # boot under qemu-system, for aarch64/x86_64/riscv64/riscv32) is now driven by 1504 # make test-cross TARGET=freestanding 1505 # whose exec_bare backend (test/lib/exec_bare.sh) owns the per-arch reset stubs, 1506 # linker scripts, and exit oracles. See doc/plan/PORT.md. 1507 1508 # test-parse-rv64-wide: end-to-end coverage of the rv64 128-bit scalar types 1509 # — __int128 (i128_*) and IEEE-754 binary128 long double (ldbl128_*) — built 1510 # with kit and run on riscv64. Exercises the soft-float / i128 lowering to 1511 # the compiler-rt-style runtime (fp_tf, fp_ti, int64), the LP64D register-pair 1512 # ABI for 16-byte scalars, and the conditional-branch range fix that large 1513 # soft-float helpers depend on. Opt-in (needs qemu-riscv64 or podman with 1514 # riscv64 emulation), so excluded from the default `test` target; mirrors 1515 # test-smoke-rv64. Run a single case with 1516 # KIT_TEST_ARCH=rv64 bash test/parse/run.sh ldbl128_03_arith 1517 test-parse-rv64-wide: lib rt-riscv64-linux $(PARSE_RUNNER) $(ROUNDTRIP_BIN) \ 1518 $(LINK_EXE_RUNNER) 1519 @KIT_TEST_ARCH=rv64 KIT_TEST_PATHS=RE bash test/parse/run.sh 128 1520 1521 # test-bounce: format-bounce stress test. Compiles small programs with 1522 # kit, then bounces each object through chains of format conversions 1523 # (ELF<->Mach-O<->COFF), partial links (ld -r), strip, and archive 1524 # round-trips, relinks, and runs the result, asserting the exit code 1525 # matches a host-cc reference. Stresses obj read/write/reloc, ar, and 1526 # partial-link paths rather than the arches. Defaults to the host-native 1527 # Linux arch (no emulation); sweep others with 1528 # KIT_BOUNCE_ARCHES="aarch64 x64 rv64". Excluded from the default `test` 1529 # target because it needs podman/qemu + a host cc; opt-in via 1530 # `make test-bounce`. 1531 test-bounce: $(BIN) 1532 bash test/bounce/bounce.sh 1533 1534 # test-libc: aggregate alias that runs test-libc-musl and test-libc-glibc. 1535 # test-libc-musl / test-libc-glibc: end-to-end static + dynamic libc link/run 1536 # on aarch64. Each variant pulls its own pinned sysroot (podman, ~30s on 1537 # first run) and shares the same case files under test/libc/cases/: 1538 # 1539 # test-libc-musl — Alpine 3.20 + musl 1.2.5 (test/libc/musl/) 1540 # test-libc-glibc — Debian bookworm + glibc 2.36 (test/libc/glibc/) 1541 # 1542 # Both build build/rt/aarch64-linux/libkit_rt.a for soft-float / TF 1543 # builtins, and run `kit ld` against the real libc.a (static) and 1544 # libc.so / libc.so.6 (dynamic). Excluded from the 1545 # default `test` target because they need podman; opt-in via 1546 # `make test-libc-musl` / `make test-libc-glibc` (or `make test-libc` for both). 1547 # 1548 # Each sysroot is treated as a real prerequisite via its PROVENANCE 1549 # marker so subsequent runs skip extraction and re-extract only when 1550 # the file is removed (or extract.sh -f forces a rebuild). 1551 MUSL_SYSROOT_MARKER = $(KIT_SYSROOTS_DIR)/linux-musl/PROVENANCE 1552 MUSL_SYSROOT_X64_MARKER = $(KIT_SYSROOTS_DIR)/linux-musl-x64/PROVENANCE 1553 MUSL_SYSROOT_RV64_MARKER = $(KIT_SYSROOTS_DIR)/linux-musl-rv64/PROVENANCE 1554 GLIBC_SYSROOT_MARKER = $(KIT_SYSROOTS_DIR)/linux-glibc/PROVENANCE 1555 GLIBC_SYSROOT_X64_MARKER = $(KIT_SYSROOTS_DIR)/linux-glibc-x64/PROVENANCE 1556 GLIBC_SYSROOT_RV64_MARKER = $(KIT_SYSROOTS_DIR)/linux-glibc-rv64/PROVENANCE 1557 1558 $(MUSL_SYSROOT_MARKER): test/libc/musl/extract.sh test/libc/musl/Containerfile 1559 @bash test/libc/musl/extract.sh 1560 1561 $(MUSL_SYSROOT_X64_MARKER): test/libc/musl/extract.sh test/libc/musl/Containerfile.x64 1562 @bash test/libc/musl/extract.sh -a x64 1563 1564 $(MUSL_SYSROOT_RV64_MARKER): test/libc/musl/extract.sh test/libc/musl/Containerfile.rv64 1565 @bash test/libc/musl/extract.sh -a rv64 1566 1567 $(GLIBC_SYSROOT_MARKER): test/libc/glibc/extract.sh test/libc/glibc/Containerfile 1568 @bash test/libc/glibc/extract.sh 1569 1570 $(GLIBC_SYSROOT_X64_MARKER): test/libc/glibc/extract.sh test/libc/glibc/Containerfile.x64 1571 @bash test/libc/glibc/extract.sh -a x64 1572 1573 $(GLIBC_SYSROOT_RV64_MARKER): test/libc/glibc/extract.sh test/libc/glibc/Containerfile.rv64 1574 @bash test/libc/glibc/extract.sh -a rv64 1575 1576 # test-libc-musl / test-libc-glibc honor KIT_LIBC_ARCHES (default "aa64"; 1577 # values: aa64, x64, rv64). Each enabled arch contributes its sysroot 1578 # PROVENANCE marker and its rt archive to the prerequisite list, so 1579 # `KIT_LIBC_ARCHES="aa64 x64" make test-libc-musl` builds both sysroots 1580 # + both rt archives before the runner script picks them up. 1581 KIT_LIBC_ARCHES ?= aa64 1582 1583 # Map an arch token to its musl/glibc sysroot marker and rt target. 1584 _LIBC_MUSL_SYSROOT_aa64 = $(MUSL_SYSROOT_MARKER) 1585 _LIBC_MUSL_SYSROOT_x64 = $(MUSL_SYSROOT_X64_MARKER) 1586 _LIBC_MUSL_SYSROOT_rv64 = $(MUSL_SYSROOT_RV64_MARKER) 1587 _LIBC_GLIBC_SYSROOT_aa64 = $(GLIBC_SYSROOT_MARKER) 1588 _LIBC_GLIBC_SYSROOT_x64 = $(GLIBC_SYSROOT_X64_MARKER) 1589 _LIBC_GLIBC_SYSROOT_rv64 = $(GLIBC_SYSROOT_RV64_MARKER) 1590 _LIBC_RT_aa64 = rt-aarch64-linux 1591 _LIBC_RT_x64 = rt-x86_64-linux 1592 _LIBC_RT_rv64 = rt-riscv64-linux 1593 1594 LIBC_MUSL_DEPS = $(foreach a,$(KIT_LIBC_ARCHES),$(_LIBC_MUSL_SYSROOT_$(a)) $(_LIBC_RT_$(a))) 1595 LIBC_GLIBC_DEPS = $(foreach a,$(KIT_LIBC_ARCHES),$(_LIBC_GLIBC_SYSROOT_$(a)) $(_LIBC_RT_$(a))) 1596 1597 test-libc: test-libc-musl test-libc-glibc 1598 1599 test-libc-musl: bin $(LIBC_MUSL_DEPS) 1600 @KIT_LIBC_ARCHES="$(KIT_LIBC_ARCHES)" bash test/libc/musl/run.sh 1601 1602 test-libc-glibc: bin $(LIBC_GLIBC_DEPS) 1603 @KIT_LIBC_ARCHES="$(KIT_LIBC_ARCHES)" bash test/libc/glibc/run.sh 1604 1605 # FreeBSD hosted executable smoke (static + dynamic). Sysroots come from 1606 # scripts/freebsd_sysroot.sh (cached base.txz extracts under ~/.cache/kit). By 1607 # default these validate compile/link + ELF metadata; set KIT_FREEBSD_RUN_VM=1 1608 # to boot the cached FreeBSD VMs and execute each binary under real FreeBSD. 1609 test-freebsd: bin 1610 @KIT_FREEBSD_LINK=both bash test/libc/freebsd/run.sh 1611 1612 test-freebsd-static: bin 1613 @KIT_FREEBSD_LINK=static bash test/libc/freebsd/run.sh 1614 1615 test-freebsd-dynamic: bin 1616 @KIT_FREEBSD_LINK=dynamic bash test/libc/freebsd/run.sh 1617 1618 test-libc-musl-rv64: 1619 @$(MAKE) test-libc-musl KIT_LIBC_ARCHES=rv64 1620 1621 test-libc-glibc-rv64: 1622 @$(MAKE) test-libc-glibc KIT_LIBC_ARCHES=rv64 1623 1624 # The hosted cross-compile-and-run suite is now `make test-cross` (engine: 1625 # scripts/cross_test.sh, source of truth: scripts/hosted.sh). See doc/plan/PORT.md. 1626 # hosted-glibc-images is kept: scripts/provision.sh pulls the per-arch Debian run 1627 # images for the linux-glibc run lanes through it (alpine/musl uses test-images). 1628 HOSTED_GLIBC_IMAGES = \ 1629 docker.io/arm64v8/debian:bookworm-slim \ 1630 docker.io/amd64/debian:bookworm-slim \ 1631 docker.io/riscv64/debian:trixie-slim 1632 1633 hosted-glibc-images: 1634 @for img in $(HOSTED_GLIBC_IMAGES); do \ 1635 podman image exists "$$img" 2>/dev/null || podman pull "$$img" || \ 1636 echo "warn: could not pull $$img (linux-glibc run lanes will SKIP)"; \ 1637 done 1638 1639 # Fail if libkit.a depends on any external symbol not in the allowlist, or 1640 # if a relocatable link exposes non-public global definitions. 1641 # External dependency drift in either direction (new dep, or stale entry) is a 1642 # failure. 1643 # 1644 # Inspect the RELEASE artifacts only: the debug build is ASan/UBSan-instrumented 1645 # and pulls in __asan_*/__ubsan_* externals that are not part of the shipped 1646 # library's dependency surface. 1647 LIB_DEPS_RELEASE_DIR = build/release 1648 LIB_DEPS_AR = $(LIB_DEPS_RELEASE_DIR)/libkit.a 1649 LIB_DEPS_ACTUAL = $(LIB_DEPS_RELEASE_DIR)/libkit.deps.txt 1650 LIB_RELOC = $(LIB_DEPS_RELEASE_DIR)/libkit.reloc.o 1651 LIB_RELOC_BAD = $(LIB_DEPS_RELEASE_DIR)/libkit.reloc.bad-symbols.txt 1652 1653 test-lib-deps: 1654 @$(MAKE) lib RELEASE=1 1655 @mkdir -p $(dir $(LIB_DEPS_ACTUAL)) 1656 @python3 scripts/lib_external_deps.py $(LIB_DEPS_AR) > $(LIB_DEPS_ACTUAL) 1657 @diff -u scripts/lib_deps.allowlist $(LIB_DEPS_ACTUAL) \ 1658 || { echo "libkit.a external symbol set drifted from scripts/lib_deps.allowlist"; exit 1; } 1659 @python3 scripts/lib_reloc_defined_prefixes.py $(LIB_DEPS_AR) \ 1660 --output $(LIB_RELOC) --ar $(AR) --cc $(CC) > $(LIB_RELOC_BAD) 1661 @test ! -s $(LIB_RELOC_BAD) \ 1662 || { echo "libkit relocatable link exposes non-public symbols"; cat $(LIB_RELOC_BAD); exit 1; }