commit 3fbd50380ffc8175756f8decd961fa5f90e40c7c
parent e588f2ff4cc4f95d7eab3cfd1847b490eb157c5f
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Wed, 17 Jun 2026 16:26:13 -0700
test: expand tier1 kitchen coverage
Diffstat:
15 files changed, 222 insertions(+), 23 deletions(-)
diff --git a/mk/flags.mk b/mk/flags.mk
@@ -118,12 +118,13 @@ KIT_VERSION_DEFS = -DKIT_VERSION_STR='"$(KIT_VERSION)"' \
VERSION_CONFIG = $(BUILD_DIR)/.version-config
$(VERSION_CONFIG): FORCE
@mkdir -p $(dir $@)
- @{ \
+ @tmp="$@.$$$$.tmp"; \
+ { \
printf '%s\n' 'KIT_VERSION=$(KIT_VERSION)'; \
printf '%s\n' 'KIT_BUILD_ID=$(KIT_BUILD_ID)'; \
printf '%s\n' 'KIT_HOST_TRIPLE=$(KIT_HOST_TRIPLE)'; \
- } > $@.tmp
- @if ! cmp -s $@.tmp $@; then mv $@.tmp $@; else rm -f $@.tmp; fi
+ } > "$$tmp"; \
+ if ! cmp -s "$$tmp" "$@"; then mv "$$tmp" "$@"; else rm -f "$$tmp"; fi
# Freestanding objects must not see host SDK/libc headers. Homebrew clang can
# also inject a configured sysroot before command-line flags; use
diff --git a/mk/test.mk b/mk/test.mk
@@ -276,6 +276,7 @@ test-t1-obj: $(ROUNDTRIP_BIN)
test-t1-link-jit: $(LINK_EXE_RUNNER)
@$(T1_LOG) link test/tier1/objlink/link.sh
@$(T1_LOG) jit-relax $(MAKE) --no-print-directory test-link-jit-tls-relax
+ @$(T1_LOG) interop env KIT=$(abspath $(BIN)) test/tier1/objlink/interop.sh
test-t1-cross: bin
@$(T1_LOG) cross env KIT=$(abspath $(BIN)) test/tier1/cross/run.sh
diff --git a/test/tier1/cross/run.sh b/test/tier1/cross/run.sh
@@ -5,6 +5,7 @@ ROOT="$(cd "$(dirname "$0")/../../.." && pwd)"
KIT="${KIT:-$ROOT/build/kit}"
HOSTED="$ROOT/scripts/hosted.sh"
CASES="$ROOT/test/cross/cases"
+KITCHEN="$ROOT/test/tier1/kitchen/cross"
WORK="$ROOT/build/test/tier1/cross"
SELECTOR="${T1_CROSS_TARGETS:-all}"
@@ -134,6 +135,51 @@ android_lane() {
run_cmd "$label:ld" "$dir/ld.log" \
"$HOSTED" cc "$token" -shared "$obj" -landroid -o "$so" || return 0
if [ -s "$so" ]; then kit_pass "$label"; else kit_fail "$label" "shared object missing"; fi
+ android_shared_lane "$sysroot"
+}
+
+android_shared_lane() {
+ local sysroot="$1" label=android-aa64:shared dir dep_obj dep_so user_obj user_so
+ dir="$WORK/android-aa64-shared"
+ mkdir -p "$dir"
+ dep_obj="$dir/dep.o"
+ dep_so="$dir/libt1dep.so"
+ user_obj="$dir/user.o"
+ user_so="$dir/libt1user.so"
+ : "$sysroot"
+ run_cmd "$label:dep-cc" "$dir/dep-cc.log" \
+ "$HOSTED" cc android-aa64 -O1 -fPIC -c "$KITCHEN/shared_dep.c" -o "$dep_obj" || return 0
+ run_cmd "$label:dep-so" "$dir/dep-so.log" \
+ "$HOSTED" cc android-aa64 -shared "$dep_obj" -o "$dep_so" || return 0
+ run_cmd "$label:user-cc" "$dir/user-cc.log" \
+ "$HOSTED" cc android-aa64 -O1 -fPIC -c "$KITCHEN/shared_main.c" -o "$user_obj" || return 0
+ run_cmd "$label:user-so" "$dir/user-so.log" \
+ "$HOSTED" cc android-aa64 -shared "$user_obj" -L "$dir" -lt1dep -o "$user_so" || return 0
+ if [ -s "$dep_so" ] && [ -s "$user_so" ]; then kit_pass "$label"; else kit_fail "$label" "shared object missing"; fi
+}
+
+linux_shared_lane() {
+ local token="$1" label="$1:shared" sysroot dir dep_obj dep_so main_obj exe
+ match_selector "$token" || return 0
+ sysroot="$(hosted_path "$token")"
+ if [ -z "$sysroot" ] || [ ! -d "$sysroot" ]; then
+ return 0
+ fi
+ dir="$WORK/$token-shared"
+ mkdir -p "$dir"
+ dep_obj="$dir/dep.o"
+ dep_so="$dir/libt1dep.so"
+ main_obj="$dir/main.o"
+ exe="$dir/main"
+ run_cmd "$label:dep-cc" "$dir/dep-cc.log" \
+ "$HOSTED" cc "$token" -O1 -fPIC -c "$KITCHEN/shared_dep.c" -o "$dep_obj" || return 0
+ run_cmd "$label:dep-so" "$dir/dep-so.log" \
+ "$HOSTED" cc "$token" -shared "$dep_obj" -o "$dep_so" || return 0
+ run_cmd "$label:main-cc" "$dir/main-cc.log" \
+ "$HOSTED" cc "$token" -O1 -c "$KITCHEN/shared_main.c" -o "$main_obj" || return 0
+ run_cmd "$label:main-link" "$dir/main-link.log" \
+ "$HOSTED" cc "$token" "$main_obj" -L "$dir" -lt1dep -o "$exe" || return 0
+ if [ -s "$dep_so" ] && [ -s "$exe" ]; then kit_pass "$label"; else kit_fail "$label" "shared linked artifact missing"; fi
}
apple_sdk_path() {
@@ -206,8 +252,10 @@ freestanding_lane() {
for arch in aa64 x64 rv64; do
hosted_lane "linux-glibc-$arch" default
+ linux_shared_lane "linux-glibc-$arch"
hosted_lane "linux-musl-$arch" static
hosted_lane "linux-musl-$arch" dynamic
+ linux_shared_lane "linux-musl-$arch"
hosted_lane "freebsd-$arch" static
done
diff --git a/test/tier1/frontend/run-kitchen.sh b/test/tier1/frontend/run-kitchen.sh
@@ -32,6 +32,15 @@ check_rc() {
fi
}
+run_expect_rc() {
+ local label="$1"
+ local want="$2"
+ shift 2
+ "$@" >/dev/null 2>&1
+ local got=$?
+ check_rc "$label" "$got" "$want"
+}
+
normalize_tokens() {
tr '\n' ' ' < "$1" | tr -s '[:space:]' ' ' | sed -e 's/^ //' -e 's/ $//'
}
@@ -53,33 +62,56 @@ run_pp() {
run_c() {
local src="$fixture_root/c_kitchen.c"
local expected
- local run_rc
- local obj="$1/c_kitchen.o"
- local dump="$1/c_kitchen.dump"
+ local obj="$1/c_kitchen.o" dump="$1/c_kitchen.dump"
+ local exe="$1/c_kitchen.exe"
+ local emit_c="$1/c_kitchen.emit.c" emit_exe="$1/c_kitchen.emit.exe"
+ local asm="$1/c_kitchen.s" asm_obj="$1/c_kitchen.s.o" asm_exe="$1/c_kitchen.s.exe"
expected=$(expected_rc "$fixture_root/c_kitchen.expected")
[ -x "$KIT" ] || { printf 'missing kit binary: %s\n' "$KIT" >&2; return 2; }
"$KIT" cc -O0 -c "$src" -o "$obj"
"$KIT" objdump -h -t "$obj" > "$dump"
grep -Eq '(^|[[:space:]])main($|[[:space:]])' "$dump"
- "$KIT" run "$src"
- run_rc=$?
- check_rc "c/kitchen" "$run_rc" "$expected"
+
+ "$KIT" cc -O0 "$src" -lc -o "$exe"
+ run_expect_rc "c/kitchen-link-exec" "$expected" "$exe"
+
+ "$KIT" cc --emit=c -O0 "$src" -o "$emit_c"
+ "${CC:-cc}" "$emit_c" -o "$emit_exe"
+ run_expect_rc "c/kitchen-emit-c-exec" "$expected" "$emit_exe"
+
+ "$KIT" cc -S -O0 "$src" -o "$asm"
+ "$KIT" as "$asm" -o "$asm_obj"
+ "$KIT" cc "$asm_obj" -lc -o "$asm_exe"
+ run_expect_rc "c/kitchen-emit-s-exec" "$expected" "$asm_exe"
+
+ run_expect_rc "c/kitchen-jit" "$expected" "$KIT" run "$src"
}
run_toy() {
local src="$fixture_root/toy_kitchen.toy"
local expected
- local run_rc
+ local exe="$1/toy_kitchen.exe"
+ local emit_c="$1/toy_kitchen.emit.c" emit_exe="$1/toy_kitchen.emit.exe"
+ local asm="$1/toy_kitchen.s" asm_obj="$1/toy_kitchen.s.o" asm_exe="$1/toy_kitchen.s.exe"
expected=$(expected_rc "$fixture_root/toy_kitchen.expected")
[ -x "$KIT" ] || { printf 'missing kit binary: %s\n' "$KIT" >&2; return 2; }
- "$KIT" run "$src"
- run_rc=$?
- check_rc "toy/kitchen-jit" "$run_rc" "$expected"
- "$KIT" run --no-jit "$src"
- run_rc=$?
- check_rc "toy/kitchen-interp" "$run_rc" "$expected"
+
+ "$KIT" cc -O0 "$src" -lc -o "$exe"
+ run_expect_rc "toy/kitchen-link-exec" "$expected" "$exe"
+
+ "$KIT" cc --emit=c -O0 "$src" -o "$emit_c"
+ "${CC:-cc}" "$emit_c" -o "$emit_exe"
+ run_expect_rc "toy/kitchen-emit-c-exec" "$expected" "$emit_exe"
+
+ "$KIT" cc -S -O0 "$src" -o "$asm"
+ "$KIT" as "$asm" -o "$asm_obj"
+ "$KIT" cc "$asm_obj" -lc -o "$asm_exe"
+ run_expect_rc "toy/kitchen-emit-s-exec" "$expected" "$asm_exe"
+
+ run_expect_rc "toy/kitchen-jit" "$expected" "$KIT" run "$src"
+ run_expect_rc "toy/kitchen-interp" "$expected" "$KIT" run --no-jit "$src"
}
run_wasm() {
diff --git a/test/tier1/kitchen/cross/shared_dep.c b/test/tier1/kitchen/cross/shared_dep.c
@@ -0,0 +1,3 @@
+int t1_shared_add(int a, int b) {
+ return a + b;
+}
diff --git a/test/tier1/kitchen/cross/shared_main.c b/test/tier1/kitchen/cross/shared_main.c
@@ -0,0 +1,5 @@
+int t1_shared_add(int, int);
+
+int main(void) {
+ return t1_shared_add(20, 22);
+}
diff --git a/test/tier1/kitchen/objlink/interop/clang_value.c b/test/tier1/kitchen/objlink/interop/clang_value.c
@@ -0,0 +1,3 @@
+int clang_value(void) {
+ return 42;
+}
diff --git a/test/tier1/kitchen/objlink/interop/kit_main.c b/test/tier1/kitchen/objlink/interop/kit_main.c
@@ -0,0 +1,5 @@
+extern int clang_value(void);
+
+int main(void) {
+ return clang_value();
+}
diff --git a/test/tier1/manifests/system/debug-dwarf.txt b/test/tier1/manifests/system/debug-dwarf.txt
@@ -4,4 +4,4 @@ make:test-dwarf
make:test-debug
driver:objdump-dwarf/01-dwarf-all
driver:dbg/repl-help
-
+driver:addr2line-symbolize
diff --git a/test/tier1/manifests/system/tools.txt b/test/tier1/manifests/system/tools.txt
@@ -1,4 +1,8 @@
# Cheap driver-tool Tier 1 sentinel targets.
+test-driver-ar
+test-driver-cpio
test-driver-tools
test-driver-strings
test-driver-objdump
+test-driver-objcopy
+test-driver-strip
diff --git a/test/tier1/objlink/README.md b/test/tier1/objlink/README.md
@@ -11,6 +11,8 @@ Fixtures live under `test/tier1/kitchen/objlink/`:
`kit-roundtrip` and compared through the ELF normalizer.
- `link/`: a tiny multi-object program linked through `link-exe-runner` with an
archive member and `--gc-sections`, then inspected as an executable image.
+- `interop/`: a kit-produced object linked by clang/lld when available, and a
+ clang-produced object linked back through kit.
Run all:
diff --git a/test/tier1/objlink/interop.sh b/test/tier1/objlink/interop.sh
@@ -0,0 +1,91 @@
+#!/usr/bin/env bash
+set -u
+
+ROOT="$(cd "$(dirname "$0")/../../.." && pwd)"
+KIT="${KIT:-$ROOT/build/kit}"
+KITCHEN="$ROOT/test/tier1/kitchen/objlink/interop"
+WORK="$ROOT/build/test/tier1/objlink/interop"
+
+mkdir -p "$WORK"
+
+. "$ROOT/test/lib/kit_sh_report.sh"
+kit_report_init
+KIT_SKIP_IS_FAILURE=0
+
+if [ ! -x "$KIT" ]; then
+ kit_fail "interop/setup" "kit not built at $KIT"
+ kit_summary test-t1-objlink-interop
+ kit_exit
+fi
+if ! command -v clang >/dev/null 2>&1; then
+ kit_skip "clang-link" "clang not found"
+ kit_skip "clang-object-kit-link" "clang not found"
+ kit_summary test-t1-objlink-interop
+ kit_exit
+fi
+
+run_expect_rc() {
+ local label="$1" want="$2" exe="$3"
+ "$exe" >/dev/null 2>&1
+ local got=$?
+ if [ "$got" -eq "$want" ]; then
+ kit_pass "$label"
+ else
+ kit_fail "$label" "expected rc $want, got $got"
+ fi
+}
+
+run_cmd() {
+ local label="$1" log="$2"
+ shift 2
+ if "$@" >"$log" 2>&1; then
+ return 0
+ fi
+ kit_fail "$label" "see $log"
+ return 1
+}
+
+kit_obj="$WORK/kit_main.o"
+clang_obj="$WORK/clang_value.o"
+clang_exe="$WORK/clang_link.exe"
+kit_exe="$WORK/kit_link.exe"
+clang_probe_c="$WORK/clang_probe.c"
+clang_probe_exe="$WORK/clang_probe.exe"
+clang_args=()
+
+case "$(uname -s 2>/dev/null)" in
+ Darwin)
+ sdk="$(xcrun --sdk macosx --show-sdk-path 2>/dev/null || true)"
+ if [ -n "$sdk" ] && [ -d "$sdk" ]; then
+ clang_args=(-isysroot "$sdk")
+ fi ;;
+ Linux)
+ if command -v ld.lld >/dev/null 2>&1; then
+ clang_args=(-fuse-ld=lld)
+ fi ;;
+esac
+
+printf '%s\n' 'int main(void) { return 0; }' > "$clang_probe_c"
+
+run_cmd "kit-object" "$WORK/kit-object.log" \
+ "$KIT" cc -O0 -c "$KITCHEN/kit_main.c" -o "$kit_obj"
+run_cmd "clang-object" "$WORK/clang-object.log" \
+ clang -O0 -c "$KITCHEN/clang_value.c" -o "$clang_obj"
+
+if [ -f "$kit_obj" ] && [ -f "$clang_obj" ]; then
+ if clang "${clang_args[@]}" "$clang_probe_c" -o "$clang_probe_exe" >"$WORK/clang-link-probe.log" 2>&1; then
+ if run_cmd "clang-link" "$WORK/clang-link.log" \
+ clang "${clang_args[@]}" "$kit_obj" "$clang_obj" -o "$clang_exe"; then
+ run_expect_rc "clang-link-exec" 42 "$clang_exe"
+ fi
+ else
+ kit_skip "clang-link" "host clang cannot link an executable; see $WORK/clang-link-probe.log"
+ fi
+ if run_cmd "clang-object-kit-link" "$WORK/kit-link.log" \
+ "$KIT" cc "$kit_obj" "$clang_obj" -o "$kit_exe"; then
+ run_expect_rc "clang-object-kit-link-exec" 42 "$kit_exe"
+ fi
+fi
+
+kit_summary test-t1-objlink-interop
+kit_exit
diff --git a/test/tier1/objlink/run.sh b/test/tier1/objlink/run.sh
@@ -23,3 +23,4 @@ run_one() {
run_one asm "$ROOT/test/tier1/objlink/asm.sh"
run_one object "$ROOT/test/tier1/objlink/object.sh"
run_one link "$ROOT/test/tier1/objlink/link.sh"
+run_one interop "$ROOT/test/tier1/objlink/interop.sh"
diff --git a/test/tier1/system/README.md b/test/tier1/system/README.md
@@ -10,14 +10,16 @@ tails the captured log.
## Coverage
-- `tools.sh` runs existing cheap tool-driver sentinels: `test-driver-tools`
- (`xxd`, `cmp`, `hash`, `disas`, `mc`, `compress`, `image`),
- `test-driver-strings`, and `test-driver-objdump`.
+- `tools.sh` runs existing cheap tool-driver sentinels: `test-driver-ar`
+ (`ar`, `ranlib`), `test-driver-cpio`, `test-driver-tools` (`xxd`, `cmp`,
+ `hash`, `sha256sum`, `b2sum`, `crc32`, `disas`, `mc`, `compress`, `image`),
+ `test-driver-strings`, `test-driver-objdump`, `test-driver-objcopy`, and
+ `test-driver-strip`.
- `runtime-headers.sh` runs `test-rt-headers`, compiling `test/rt/smoke.c`
against the runtime headers for the cheap configured target triples.
- `debug-dwarf.sh` runs DWARF reader and debug producer unit targets, one
- committed `objdump --dwarf` golden, and the lightweight `kit dbg` help
- transcript.
+ committed `objdump --dwarf` golden, the lightweight `kit dbg` help transcript,
+ and the `addr2line`/`symbolize` backtrace smoke.
- `dist.sh` runs the local CAS and package driver suites through
`test-driver-cas` and `test-driver-pkg`.
diff --git a/test/tier1/system/debug-dwarf.sh b/test/tier1/system/debug-dwarf.sh
@@ -61,4 +61,5 @@ run_step test-dwarf make -C "$repo_root" test-dwarf || exit $?
run_step test-debug make -C "$repo_root" test-debug || exit $?
run_objdump_dwarf || exit $?
run_step dbg-repl-help env KIT="$repo_root/build/kit" DBG_CASE=repl-help \
- sh "$repo_root/test/dbg/run.sh"
+ sh "$repo_root/test/dbg/run.sh" || exit $?
+run_step addr2line-symbolize make -C "$repo_root" test-rt-backtrace