check_rv32_env.sh (3774B)
1 #!/usr/bin/env bash 2 # test/lib/check_rv32_env.sh — kit rv32 "doctor". 3 # 4 # Prerequisite check for the rv32 behavioral-oracle lane (test/smoke/rv32.sh). 5 # Unlike rv64 (qemu-user / podman, a riscv64-linux ELF), the rv32 target is 6 # freestanding `-none-elf`: it runs as a bare-metal image under 7 # qemu-system-riscv32 -machine virt, with a startup stub that enables the FPU 8 # (mstatus.FS) for the single-hard-float (ilp32f) variant and a SiFive test 9 # finisher at 0x100000 to turn a program result into a qemu exit code. 10 # 11 # Each checked tool is reported as a one-liner (OK / MISSING) with what was 12 # looked for and how to install it. Source it and call check_rv32_env to 13 # populate the RV32_* globals; run it directly for a standalone report. 14 # 15 # After check_rv32_env returns, these globals are set: 16 # RV32_HAVE_CLANG_TARGET 0/1 — clang accepts --target=riscv32-unknown-elf 17 # RV32_HAVE_LLD 0/1 — ld.lld on PATH (bare-metal link fallback) 18 # RV32_HAVE_QEMU_SYSTEM 0/1 — qemu-system-riscv32 on PATH 19 # RV32_QEMU_SYSTEM_BIN path or empty 20 # RV32_READY 0/1 — clang target + qemu-system both usable 21 22 _rv32_os_tag() { 23 case "$(uname -s 2>/dev/null)" in 24 Darwin) echo darwin ;; 25 Linux) 26 if [ -r /etc/os-release ]; then 27 . /etc/os-release 28 case "${ID:-}:${ID_LIKE:-}" in 29 *alpine*) echo alpine ;; 30 *debian*|*ubuntu*) echo debian ;; 31 *fedora*|*rhel*) echo fedora ;; 32 *) echo linux ;; 33 esac 34 else echo linux; fi ;; 35 *) echo other ;; 36 esac 37 } 38 39 _rv32_hint_clang() { 40 case "$(_rv32_os_tag)" in 41 darwin) echo "brew install llvm (clang 16+ ships the riscv32 target)" ;; 42 debian) echo "apt install clang lld" ;; 43 fedora) echo "dnf install clang lld" ;; 44 alpine) echo "apk add clang lld" ;; 45 *) echo "install an LLVM/clang with the riscv32 target" ;; 46 esac 47 } 48 49 _rv32_hint_qemu_system() { 50 case "$(_rv32_os_tag)" in 51 darwin) echo "brew install qemu" ;; 52 debian) echo "apt install qemu-system-misc" ;; 53 fedora) echo "dnf install qemu-system-riscv" ;; 54 alpine) echo "apk add qemu-system-riscv32" ;; 55 *) echo "install qemu (qemu-system-riscv32)" ;; 56 esac 57 } 58 59 check_rv32_env() { 60 RV32_HAVE_CLANG_TARGET=0 61 RV32_HAVE_LLD=0 62 RV32_HAVE_QEMU_SYSTEM=0 63 RV32_QEMU_SYSTEM_BIN="" 64 65 # clang with the riscv32 target: probe by compiling an empty TU. 66 if command -v clang >/dev/null 2>&1; then 67 if echo 'int _e(void){return 0;}' | \ 68 clang --target=riscv32-unknown-elf -march=rv32imac -mabi=ilp32 \ 69 -ffreestanding -nostdlib -c -x c - -o /dev/null >/dev/null 2>&1; then 70 RV32_HAVE_CLANG_TARGET=1 71 echo " OK clang --target=riscv32-unknown-elf" 72 else 73 echo " MISSING clang riscv32 target — install: $(_rv32_hint_clang)" 74 fi 75 else 76 echo " MISSING clang — install: $(_rv32_hint_clang)" 77 fi 78 79 if command -v ld.lld >/dev/null 2>&1; then 80 RV32_HAVE_LLD=1 81 echo " OK ld.lld" 82 else 83 echo " MISSING ld.lld — install: $(_rv32_hint_clang)" 84 fi 85 86 if command -v qemu-system-riscv32 >/dev/null 2>&1; then 87 RV32_HAVE_QEMU_SYSTEM=1 88 RV32_QEMU_SYSTEM_BIN="$(command -v qemu-system-riscv32)" 89 echo " OK qemu-system-riscv32 ($RV32_QEMU_SYSTEM_BIN)" 90 else 91 echo " MISSING qemu-system-riscv32 — install: $(_rv32_hint_qemu_system)" 92 fi 93 94 RV32_READY=0 95 if [ "$RV32_HAVE_CLANG_TARGET" -eq 1 ] && [ "$RV32_HAVE_QEMU_SYSTEM" -eq 1 ]; then 96 RV32_READY=1 97 echo " READY rv32 behavioral oracle available" 98 else 99 echo " BLOCKED rv32 behavioral oracle needs clang riscv32 target + qemu-system-riscv32" 100 fi 101 } 102 103 # Run standalone: report and exit non-zero if blocked. 104 if [ "${BASH_SOURCE[0]}" = "${0}" ]; then 105 check_rv32_env 106 [ "${RV32_READY:-0}" -eq 1 ] 107 fi