kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

run.sh (12704B)


      1 #!/bin/sh
      2 # Driver-level checks for the kit-native build verbs `build-exe` / `build-lib` /
      3 # `build-obj` (the trio that replaced `compile`). Self-checking (no golden
      4 # files): we assert exit status, output existence, symbol/text markers, ld -r
      5 # parity, and — for build-exe — native execution of the produced binary.
      6 #
      7 # Coverage:
      8 #   build-obj : per-language compile (C / toy / wasm), --emit=obj|asm|c|ir,
      9 #               -fsyntax-only, default output naming, -o - to stdout, the
     10 #               -X<lang> frontend-flag router, target features, the multi-source
     11 #               relocatable combine (with ld -r parity), and the negative paths.
     12 #   build-lib : static .a from mixed sources, then link against it.
     13 #   build-exe : polyglot relocatable combine, native link+exec, --group scoping
     14 #               (verified through the produced exit code), and -L/-l.
     15 
     16 set -u
     17 
     18 script_dir=$(cd "$(dirname "$0")" && pwd)
     19 repo_root=$(cd "$script_dir/../.." && pwd)
     20 
     21 KIT="${KIT:-$repo_root/build/kit}"
     22 
     23 if [ ! -x "$KIT" ]; then
     24     echo "build: kit binary not found at $KIT" >&2
     25     exit 2
     26 fi
     27 
     28 work=$(mktemp -d "${TMPDIR:-/tmp}/kit-build-test.XXXXXX")
     29 trap 'rm -rf "$work"' EXIT
     30 
     31 KIT_KIT_DIR="$repo_root/test/lib"
     32 . "$repo_root/test/lib/kit_sh_kit.sh"
     33 kit_report_init
     34 
     35 # ---- fixtures (all local to $work so default-name tests are isolated) -------
     36 mkdir -p "$work/inc"
     37 printf '#define ZERO 0\n' > "$work/inc/h.h"
     38 printf '#include "h.h"\nint helper(void);\nint main(void){return ZERO+helper();}\n' > "$work/hello.c"
     39 printf 'int helper(void){return 0;}\n' > "$work/helper.c"
     40 printf '#include <stdint.h>\nint32_t f(void){return 1;}\n' > "$work/std.c"
     41 cp "$(ls "$repo_root"/test/toy/cases/*.toy | head -1)" "$work/prog.toy"
     42 cp "$repo_root/test/wasm/cases/if_return.wat" "$work/prog.wat"
     43 printf 'int wasm_add(int a, int b);\nint wasm_main(void){return wasm_add(1,2)==3?0:1;}\n' > "$work/wasm_main.c"
     44 printf 'int wasm_add(int a, int b){return a+b;}\n' > "$work/wasm_helper.c"
     45 printf 'int wexe_add(int a, int b);\nint test_main(void){return wexe_add(2,3)==5?0:1;}\n' > "$work/wexe_main.c"
     46 printf 'int wexe_add(int a, int b){return a+b;}\nint dead_fn(void){return 99;}\n' > "$work/wexe_add.c"
     47 
     48 cd "$work"
     49 
     50 # ===========================================================================
     51 # build-obj — the compile replacement
     52 # ===========================================================================
     53 
     54 # ---- C: preprocessor flags + object output ---------------------------------
     55 run_ok bo-c-obj "$KIT" build-obj -c -Iinc -DUNUSED=1 hello.c -o hello.o
     56 assert_file_exists bo-c-obj-exists hello.o
     57 "$KIT" nm hello.o > nm.out 2>/dev/null
     58 contains bo-c-obj-has-main nm.out main
     59 
     60 # C freestanding system header (<stdint.h>) resolves via the rt include set.
     61 run_ok bo-c-freestanding-header "$KIT" build-obj -c std.c -o std.o
     62 
     63 # Default output name: <basename>.o next to cwd when -o is omitted.
     64 run_ok bo-c-default-name "$KIT" build-obj -c -Iinc hello.c
     65 assert_file_exists bo-c-default-name-file hello.o
     66 
     67 # ---- toy + wasm: non-C frontends through the generic driver -----------------
     68 run_ok bo-toy "$KIT" build-obj -c prog.toy -o prog_toy.o
     69 assert_file_exists bo-toy-exists prog_toy.o
     70 run_ok bo-wasm "$KIT" build-obj -c prog.wat -o prog_wat.o
     71 assert_file_exists bo-wasm-exists prog_wat.o
     72 
     73 # Target-owned option: the driver lowers feature flags into KitTargetOptions.
     74 run_ok bo-wasm-target-feature "$KIT" build-obj -target wasm32-none -c \
     75     -mattr=-tail-calls prog.wat -o prog_wat2.o
     76 
     77 # Per-language frontend flag via -X<lang> (routed to the wasm frontend parser).
     78 run_ok bo-Xwasm "$KIT" build-obj -target wasm32-none -c \
     79     -Xwasm -mno-feature=tail-calls prog.wat -o prog_wat3.o
     80 
     81 # ---- emit modes ------------------------------------------------------------
     82 run_ok bo-emit-asm "$KIT" build-obj -S -Iinc hello.c -o hello.s
     83 contains bo-emit-asm-text hello.s .text
     84 run_ok bo-emit-asm-long "$KIT" build-obj --emit=asm -Iinc hello.c -o hello2.s
     85 run_ok bo-emit-c "$KIT" build-obj --emit=c prog.toy -o prog.c
     86 assert_file_exists bo-emit-c-file prog.c
     87 run_ok bo-emit-ir "$KIT" build-obj --emit=ir -O1 prog.toy -o prog.ir
     88 assert_file_exists bo-emit-ir-file prog.ir
     89 
     90 # -o - sends the emit to stdout (reusing the cc stdout writer).
     91 "$KIT" build-obj --emit=ir -O1 prog.toy -o - > ir.stdout 2>/dev/null
     92 if [ -s ir.stdout ]; then ok bo-emit-ir-stdout; else not_ok bo-emit-ir-stdout; fi
     93 
     94 # ---- check-only writes no object -------------------------------------------
     95 rm -f hello.o
     96 run_ok bo-check-only "$KIT" build-obj -fsyntax-only -Iinc hello.c helper.c
     97 if [ ! -f hello.o ]; then ok bo-check-no-output; else not_ok bo-check-no-output; fi
     98 
     99 # ---- multi-source relocatable combine (ld -r) ------------------------------
    100 run_ok bo-reloc-combine "$KIT" build-obj -Iinc hello.c helper.c -o combined.o
    101 assert_file_exists bo-reloc-combine-file combined.o
    102 "$KIT" nm combined.o > combined.nm 2>/dev/null
    103 contains bo-reloc-has-helper combined.nm helper
    104 contains bo-reloc-has-main combined.nm main
    105 
    106 # ld -r parity: the in-memory combine matches a separate compile + `ld -r`.
    107 "$KIT" build-obj -c -Iinc hello.c -o sep_hello.o 2>/dev/null
    108 "$KIT" build-obj -c helper.c -o sep_helper.o 2>/dev/null
    109 "$KIT" ld -r sep_hello.o sep_helper.o -o ldr.o 2>/dev/null
    110 "$KIT" nm combined.o | sort > combine.sorted 2>/dev/null
    111 "$KIT" nm ldr.o | sort > ldr.sorted 2>/dev/null
    112 same_file bo-reloc-ld-r-parity ldr.sorted combine.sorted
    113 
    114 # Polyglot combine: C + toy in one relocatable object.
    115 run_ok bo-polyglot-combine "$KIT" build-obj -Iinc helper.c prog.toy -o poly.o
    116 
    117 # ---- wasm multi-source combine (CG-merge path) -----------------------------
    118 # Two C files merged into one .wasm module (magic \0asm + non-empty content).
    119 run_ok bo-wasm-multi "$KIT" build-obj -target wasm32-none \
    120     wasm_main.c wasm_helper.c -o multi.wasm
    121 assert_file_exists bo-wasm-multi-file multi.wasm
    122 # Wasm magic (\0asm = 00 61 73 6d): check first 4 bytes via od (avoids null-byte
    123 # issues with cmp on BSD).
    124 _wasm_hdr=$(od -A n -t x1 -N 4 multi.wasm | tr -d ' \t\n')
    125 [ "$_wasm_hdr" = "0061736d" ] \
    126     && ok bo-wasm-multi-magic || not_ok bo-wasm-multi-magic
    127 # Non-trivial module: size must exceed the 8-byte magic+version stub.
    128 _wasm_size=$(wc -c < multi.wasm | tr -d ' ')
    129 [ "$_wasm_size" -gt 8 ] \
    130     && ok bo-wasm-multi-nontrivial || not_ok bo-wasm-multi-nontrivial
    131 
    132 # Polyglot wasm: C + toy in one .wasm module.
    133 run_ok bo-wasm-polyglot "$KIT" build-obj -target wasm32-none \
    134     wasm_helper.c prog.toy -o poly.wasm
    135 assert_file_exists bo-wasm-polyglot-file poly.wasm
    136 _poly_hdr=$(od -A n -t x1 -N 4 poly.wasm | tr -d ' \t\n')
    137 [ "$_poly_hdr" = "0061736d" ] \
    138     && ok bo-wasm-polyglot-magic || not_ok bo-wasm-polyglot-magic
    139 
    140 # Negative: duplicate strong symbol definition must be rejected (at -O1 the
    141 # optimizer runs opt_resolve_duplicate_funcs which fires the ODR check).
    142 printf 'int wasm_add(int a, int b){return a-b;}\n' > wasm_dup.c
    143 run_fail bo-wasm-dup "$KIT" build-obj -O1 -target wasm32-none \
    144     wasm_helper.c wasm_dup.c -o dup.wasm
    145 contains bo-wasm-dup-diag "$work/bo-wasm-dup.err" "duplicate definition"
    146 
    147 # ---- negative paths --------------------------------------------------------
    148 # A frontend with an unknown -X flag is rejected by that frontend's parser.
    149 run_fail bo-neg-bad-Xflag "$KIT" build-obj -c -Xtoy --bogus prog.toy -o x.o
    150 # The target parser rejects an unknown feature name.
    151 run_fail bo-neg-bad-feature "$KIT" build-obj -target wasm32-none \
    152     -mattr=+nope -c prog.wat -o x.o
    153 # build-obj never links: object/archive inputs are refused.
    154 run_fail bo-neg-link-input "$KIT" build-obj hello.o
    155 # --emit=c needs an explicit destination.
    156 run_fail bo-neg-emit-c-needs-o "$KIT" build-obj --emit=c prog.toy
    157 # IR is only available with the optimizer on.
    158 run_fail bo-neg-ir-needs-opt "$KIT" build-obj --emit=ir prog.toy -o x.ir
    159 # -o cannot fan out across multiple sources in a per-source emit.
    160 run_fail bo-neg-o-multi-asm "$KIT" build-obj -S -Iinc hello.c std.c -o both.s
    161 # A per-output flag is not allowed inside a --group.
    162 run_fail bo-neg-global-in-group "$KIT" build-obj -Iinc --group -O2 -- hello.c
    163 # A missing -x argument before a --group source separator should not treat `--`
    164 # as a language name.
    165 run_fail bo-neg-group-x-missing-arg "$KIT" build-obj --group -x -- hello.c
    166 contains bo-neg-group-x-missing-arg-diag "$work/bo-neg-group-x-missing-arg.err" \
    167     "requires an argument"
    168 # -dynamic is a build-lib concept.
    169 run_fail bo-neg-dynamic "$KIT" build-obj -dynamic prog.toy
    170 # unknown flag.
    171 run_fail bo-neg-unknown-flag "$KIT" build-obj --nope -c prog.toy -o x.o
    172 
    173 # ===========================================================================
    174 # build-lib — static archive
    175 # ===========================================================================
    176 
    177 run_ok bl-static "$KIT" build-lib -Iinc -o libmix.a helper.c std.c prog.toy
    178 assert_file_exists bl-static-file libmix.a
    179 "$KIT" nm libmix.a > libmix.nm 2>/dev/null
    180 contains bl-static-has-helper libmix.nm helper
    181 # -o is required (no obvious base name across N sources).
    182 run_fail bl-neg-needs-o "$KIT" build-lib helper.c std.c
    183 # build-lib takes only sources.
    184 run_fail bl-neg-link-input "$KIT" build-lib -o x.a helper.o
    185 # Dynamic/shared libraries are not yet supported.
    186 run_fail bl-neg-dynamic "$KIT" build-lib -dynamic -o x.a helper.c
    187 
    188 # ===========================================================================
    189 # build-exe — native link + exec (the headline path)
    190 # ===========================================================================
    191 
    192 # A hosted executable (-lc) that returns 0; build, then run it.
    193 run_ok be-link "$KIT" build-exe -lc -Iinc hello.c helper.c -o app
    194 is_executable be-link-exec app
    195 run_ok be-run ./app
    196 
    197 # build-exe should reject the shared-library spelling instead of ignoring it.
    198 run_fail be-neg-shared "$KIT" build-exe -shared -lc -Iinc hello.c helper.c \
    199     -o shared-nope
    200 contains be-neg-shared-diag "$work/be-neg-shared.err" "shared"
    201 
    202 # Default output name a.out when -o is omitted.
    203 run_ok be-default-name "$KIT" build-exe -lc -Iinc hello.c helper.c
    204 assert_file_exists be-default-name-file a.out
    205 
    206 # -no-pie must cancel an earlier -pie for build-exe's link state.
    207 printf 'void _start(void) { for (;;) {} }\n' > no_pie_start.c
    208 run_ok be-no-pie "$KIT" build-exe -target x86_64-linux -nostdlib \
    209     -pie -no-pie no_pie_start.c -o no-pie-exe
    210 e_type=$(od -An -tx1 -j 16 -N 2 no-pie-exe | tr -d ' \n')
    211 if [ "$e_type" = "0200" ]; then ok be-no-pie-et-exec; else
    212     printf 'e_type bytes=%s want=0200\n' "$e_type" \
    213         > "$work/be-no-pie-et-exec.diag"
    214     not_ok be-no-pie-et-exec "$work/be-no-pie-et-exec.diag"
    215 fi
    216 
    217 # --group scoping is observable through the program's exit code: the bare TU
    218 # sees -DRET=0 (global), the grouped TU overrides it to a non-zero value.
    219 printf '#ifndef RET\n#define RET 7\n#endif\nint ret_val(void){return RET;}\n' > rv.c
    220 printf 'int ret_val(void);\nint main(void){return ret_val();}\n' > rmain.c
    221 run_ok be-group-link "$KIT" build-exe -lc -DRET=0 rmain.c \
    222     --group -DRET=3 -- rv.c -o appg
    223 if ./appg; then code=0; else code=$?; fi
    224 if [ "$code" -eq 3 ]; then ok be-group-scope; else
    225     echo "expected exit 3 from grouped -DRET, got $code" > "$work/be-group-scope.diag"
    226     not_ok be-group-scope "$work/be-group-scope.diag"
    227 fi
    228 
    229 # Link against the static library built above via -L/-l, then run.
    230 printf 'int helper(void);\nint main(void){return helper();}\n' > usemix.c
    231 run_ok be-link-archive "$KIT" build-exe -lc usemix.c -L. -lmix -o app2
    232 run_ok be-run-archive ./app2
    233 
    234 # ===========================================================================
    235 # build-exe — wasm target
    236 # ===========================================================================
    237 
    238 # Multi-source: produces a .wasm with DCE/internalization, runnable via kit run.
    239 run_ok be-wasm-exe "$KIT" build-exe -target wasm32-none \
    240     wexe_main.c wexe_add.c -e test_main -o wexe.wasm
    241 assert_file_exists be-wasm-exe-file wexe.wasm
    242 _wexe_hdr=$(od -A n -t x1 -N 4 wexe.wasm | tr -d ' \t\n')
    243 [ "$_wexe_hdr" = "0061736d" ] && ok be-wasm-exe-magic || not_ok be-wasm-exe-magic
    244 run_ok be-wasm-exe-run "$KIT" run -e test_main wexe.wasm
    245 
    246 # Default output name a.wasm when -o is omitted.
    247 run_ok be-wasm-exe-default-name "$KIT" build-exe -target wasm32-none \
    248     wexe_main.c wexe_add.c -e test_main
    249 assert_file_exists be-wasm-exe-default-name-file a.wasm
    250 
    251 # kit run without -e reads the kit-entry custom section from the module.
    252 run_ok be-wasm-exe-autoentry "$KIT" run wexe.wasm
    253 
    254 # Unknown entry symbol is rejected with a clear diagnostic.
    255 run_fail be-wasm-exe-bad-entry "$KIT" build-exe -target wasm32-none \
    256     wexe_main.c wexe_add.c -e no_such_fn -o bad_entry.wasm
    257 contains be-wasm-exe-bad-entry-diag "$work/be-wasm-exe-bad-entry.err" \
    258     "entry symbol"
    259 
    260 kit_summary build-driver
    261 kit_exit