426e9eeabd
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Waiting to run
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Waiting to run
Build Agent Image / build-and-push (push) Waiting to run
Chat shell gestures / Chat shell gesture + parity e2e (push) Waiting to run
ci / test (push) Waiting to run
ci / lint-and-format (push) Waiting to run
ci / build (push) Waiting to run
ci / dev-startup (push) Waiting to run
Cloud Gateway Discord / Test (push) Waiting to run
Cloud Gateway Webhook / Test (push) Waiting to run
Cloud Tests / lint-and-types (push) Waiting to run
Cloud Tests / unit-tests (push) Waiting to run
Cloud Tests / integration-tests (push) Waiting to run
Cloud Tests / e2e-tests (push) Blocked by required conditions
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Apps Worker (Product 2) / Determine environment (push) Waiting to run
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Blocked by required conditions
Deploy Eliza Provisioning Worker / Determine environment (push) Waiting to run
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Blocked by required conditions
Dev Smoke / Classify changed paths (push) Waiting to run
Dev Smoke / bun run dev onboarding chat (push) Blocked by required conditions
Dev Smoke / Vite HMR dependency-level smoke (push) Blocked by required conditions
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Waiting to run
gitleaks / gitleaks (push) Waiting to run
Markdown Links / Relative Markdown Links (push) Waiting to run
Publish @elizaos/example-code / check_npm (push) Waiting to run
Publish @elizaos/example-code / publish_npm (push) Blocked by required conditions
Publish @elizaos/plugin-elizacloud / verify_version (push) Waiting to run
Publish @elizaos/plugin-elizacloud / publish_npm (push) Blocked by required conditions
Quality (Extended) / Homepage Build (PR smoke) (push) Waiting to run
Quality (Extended) / Comment-only diff guard (push) Waiting to run
Quality (Extended) / Format + Type Safety Ratchet (push) Waiting to run
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Waiting to run
Quality (Extended) / Develop Gate (lint) (push) Waiting to run
Sandbox Live Smoke / Sandbox live smoke (push) Waiting to run
Snap Build & Test / Build Snap (amd64) (push) Waiting to run
Snap Build & Test / Build Snap (arm64) (push) Waiting to run
supply-chain / sbom (push) Waiting to run
supply-chain / vulnerability-scan (push) Waiting to run
Build, Push & Deploy to Phala Cloud / build-and-push (push) Waiting to run
Test Packaging / Validate Packaging Configs (push) Waiting to run
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Waiting to run
Test Packaging / Pack & Test JS Tarballs (push) Waiting to run
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Waiting to run
UI Fixture E2E / ui-fixture-e2e (push) Waiting to run
UI Fixture E2E / fixture-e2e (push) Waiting to run
UI Story Gate / story-gate (push) Waiting to run
vault-ci / test (macos-latest) (push) Waiting to run
vault-ci / test (ubuntu-latest) (push) Waiting to run
vault-ci / test (windows-latest) (push) Waiting to run
vault-ci / app-core wiring tests (push) Waiting to run
verify-patches / verify patches/CHECKSUMS.sha256 (push) Waiting to run
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Waiting to run
Voice Benchmark Smoke / voice bench smoke summary (push) Blocked by required conditions
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Waiting to run
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Waiting to run
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Waiting to run
Test Packaging / Build & Test PyPI Package (push) Waiting to run
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
524 lines
19 KiB
Bash
Executable File
524 lines
19 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# verify-riscv64-buildpaths.sh — exercise every in-sandbox riscv64
|
|
# cross-build path and emit a verification report.
|
|
#
|
|
# Validates Wave 1 + Wave 3 RVV cross-compilation of the four CPU-side
|
|
# native plugins (qjl-cpu, polarquant-cpu, turboquant-cpu, silero-vad-cpp)
|
|
# against the repo-root Zig toolchain at
|
|
# `packages/native/cmake/toolchain-riscv64-linux-musl.cmake`. Inspects every produced
|
|
# artifact with `file(1)` to confirm `ELF 64-bit LSB ... UCB RISC-V`.
|
|
# Optionally runs the shipped smokes under `qemu-riscv64-static` when
|
|
# present; logs a clean SKIP otherwise.
|
|
#
|
|
# Usage:
|
|
# bash scripts/verify-riscv64-buildpaths.sh # build + report
|
|
# bash scripts/verify-riscv64-buildpaths.sh --jobs 8 # parallel
|
|
# bash scripts/verify-riscv64-buildpaths.sh --out reports/foo.md # custom report path
|
|
# bash scripts/verify-riscv64-buildpaths.sh --keep-build # don't rm build dirs at the end
|
|
# ELIZA_RISCV64_BOOTSTRAP_ZIG=0 bash scripts/verify-riscv64-buildpaths.sh
|
|
# # require zig on PATH/ZIG_BIN
|
|
#
|
|
# Exit code:
|
|
# 0 — every package builds and every artifact validates rv64+lp64d
|
|
# 1 — at least one package fails or one artifact is the wrong ELF arch
|
|
#
|
|
# Zig 0.13 vs 0.14:
|
|
# The Wave 1 RVV TUs (qjl_*_rvv.c, polar_*_rvv.c, tbq_*_rvv.c) expect
|
|
# `-march=rv64gcv1p0`, which some Zig/LLVM releases accept directly.
|
|
# On releases that reject it, we drive the per-package escape hatches
|
|
# (QJL_RVV_COMPILE_OPTIONS / POLARQUANT_RVV_COMPILE_OPTIONS /
|
|
# TURBOQUANT_RVV_FLAGS) with a CPU name. TurboQuant uses
|
|
# `-mcpu=generic_rv64+v+m+a+f+d+c` rather than a named core
|
|
# (e.g. sifive_x280) because LLVM bakes the named core's VLEN into the
|
|
# zvl* attribute, and the resulting code silently truncates at a
|
|
# smaller actual VLEN (qemu-user reports VLEN=128, the spec minimum).
|
|
|
|
set -euo pipefail
|
|
|
|
repo_root="$(cd "$(dirname "$0")/.." && pwd)"
|
|
cd "$repo_root"
|
|
|
|
JOBS="${JOBS:-$(nproc 2>/dev/null || echo 4)}"
|
|
OUT="$repo_root/reports/riscv64-buildpath-verification.md"
|
|
KEEP_BUILD=0
|
|
RM_PATH_RECURSIVE="$repo_root/packages/scripts/rm-path-recursive.mjs"
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--jobs) JOBS="$2"; shift 2;;
|
|
--out) OUT="$2"; shift 2;;
|
|
--keep-build) KEEP_BUILD=1; shift;;
|
|
-h|--help)
|
|
sed -n '2,/^$/p' "$0" | sed 's/^# //; s/^#//'
|
|
exit 0;;
|
|
*) echo "unknown argument: $1" >&2; exit 2;;
|
|
esac
|
|
done
|
|
|
|
mkdir -p "$(dirname "$OUT")"
|
|
|
|
have_cmd() {
|
|
command -v "$1" >/dev/null 2>&1
|
|
}
|
|
|
|
remove_path_recursive() {
|
|
local node_bin
|
|
node_bin="${NODE_BIN:-$(command -v node || true)}"
|
|
if [ -z "$node_bin" ]; then
|
|
echo "[verify-riscv64] node not on PATH; cannot remove recursively via $RM_PATH_RECURSIVE." >&2
|
|
return 1
|
|
fi
|
|
"$node_bin" "$RM_PATH_RECURSIVE" "$@"
|
|
}
|
|
|
|
host_zig_platform() {
|
|
local os arch
|
|
os="$(uname -s | tr '[:upper:]' '[:lower:]')"
|
|
arch="$(uname -m)"
|
|
case "$os:$arch" in
|
|
linux:x86_64|linux:amd64) echo "x86_64-linux";;
|
|
linux:aarch64|linux:arm64) echo "aarch64-linux";;
|
|
darwin:arm64|darwin:aarch64) echo "aarch64-macos";;
|
|
darwin:x86_64|darwin:amd64) echo "x86_64-macos";;
|
|
*)
|
|
echo ""
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
sha256_file() {
|
|
if have_cmd sha256sum; then
|
|
sha256sum "$1" | awk '{ print $1 }'
|
|
else
|
|
shasum -a 256 "$1" | awk '{ print $1 }'
|
|
fi
|
|
}
|
|
|
|
bootstrap_zig() {
|
|
local version="${ELIZA_RISCV64_ZIG_VERSION:-0.14.1}"
|
|
local platform
|
|
platform="$(host_zig_platform)" || {
|
|
echo "[verify-riscv64] zig not on PATH and no bootstrap platform for $(uname -s)/$(uname -m)." >&2
|
|
return 1
|
|
}
|
|
|
|
if ! have_cmd curl || ! have_cmd python3; then
|
|
echo "[verify-riscv64] zig not on PATH; install Zig 0.13+ or provide curl+python3 for bootstrap." >&2
|
|
return 1
|
|
fi
|
|
|
|
local cache_dir="$repo_root/.tmp/riscv64-verify-zig"
|
|
local install_dir="$cache_dir/zig-$version-$platform"
|
|
local zig_bin="$install_dir/zig"
|
|
if [ -x "$zig_bin" ]; then
|
|
printf '%s\n' "$zig_bin"
|
|
return 0
|
|
fi
|
|
|
|
mkdir -p "$cache_dir"
|
|
local metadata archive expected actual top_dir
|
|
metadata="$(
|
|
python3 - "$version" "$platform" <<'PY'
|
|
import json
|
|
import sys
|
|
import urllib.request
|
|
|
|
version, platform = sys.argv[1], sys.argv[2]
|
|
with urllib.request.urlopen("https://ziglang.org/download/index.json", timeout=30) as response:
|
|
index = json.load(response)
|
|
try:
|
|
entry = index[version][platform]
|
|
except KeyError:
|
|
raise SystemExit(f"missing Zig {version} metadata for {platform}")
|
|
print(entry["tarball"])
|
|
print(entry["shasum"])
|
|
PY
|
|
)" || return 1
|
|
local tarball_url
|
|
tarball_url="$(printf '%s\n' "$metadata" | sed -n '1p')"
|
|
expected="$(printf '%s\n' "$metadata" | sed -n '2p')"
|
|
archive="$cache_dir/$(basename "$tarball_url")"
|
|
|
|
echo "[verify-riscv64] zig not on PATH; downloading Zig $version for $platform." >&2
|
|
curl -fsSL --retry 3 --retry-delay 2 -o "$archive" "$tarball_url"
|
|
actual="$(sha256_file "$archive")"
|
|
if [ "$actual" != "$expected" ]; then
|
|
echo "[verify-riscv64] Zig archive checksum mismatch: expected $expected got $actual" >&2
|
|
rm -f "$archive"
|
|
return 1
|
|
fi
|
|
|
|
remove_path_recursive "$install_dir"
|
|
top_dir="$(tar -tf "$archive" | sed -n '1s#/.*##p')"
|
|
tar -xf "$archive" -C "$cache_dir"
|
|
if [ -z "$top_dir" ] || [ ! -x "$cache_dir/$top_dir/zig" ]; then
|
|
echo "[verify-riscv64] downloaded Zig archive did not contain an executable zig binary." >&2
|
|
return 1
|
|
fi
|
|
mv "$cache_dir/$top_dir" "$install_dir"
|
|
printf '%s\n' "$zig_bin"
|
|
}
|
|
|
|
# Probe toolchain.
|
|
if [ -n "${ZIG_BIN:-}" ]; then
|
|
if [ ! -x "$ZIG_BIN" ]; then
|
|
echo "[verify-riscv64] ZIG_BIN is set but not executable: $ZIG_BIN" >&2
|
|
exit 1
|
|
fi
|
|
elif have_cmd zig; then
|
|
ZIG_BIN="$(command -v zig)"
|
|
elif [ "${ELIZA_RISCV64_BOOTSTRAP_ZIG:-1}" = "1" ]; then
|
|
ZIG_BIN="$(bootstrap_zig)"
|
|
else
|
|
echo "[verify-riscv64] zig not on PATH; install Zig 0.13+ and re-run." >&2
|
|
exit 1
|
|
fi
|
|
export ZIG_BIN
|
|
|
|
ZIG_VERSION="$($ZIG_BIN version)"
|
|
ZIG_MAJOR_MINOR="$(printf '%s' "$ZIG_VERSION" | awk -F. '{ print $1"."$2 }')"
|
|
|
|
# Pick the right RVV recipe for the host Zig. Several Zig/LLVM releases
|
|
# disagree on whether `-march=rv64gcv1p0` or `-mcpu=...+v` is accepted, so
|
|
# probe the installed compiler instead of assuming by version.
|
|
if printf 'int main(void){return 0;}\n' \
|
|
| "$ZIG_BIN" cc -target riscv64-linux-musl -march=rv64gcv1p0 -mabi=lp64d -x c - -c -o /dev/null >/dev/null 2>&1; then
|
|
RVV_OVERRIDE_REASON="Zig $ZIG_MAJOR_MINOR accepts \`-march=rv64gcv1p0\`"
|
|
QJL_RVV=""
|
|
POLAR_RVV=""
|
|
TBQ_RVV=""
|
|
else
|
|
RVV_OVERRIDE_REASON="Zig $ZIG_MAJOR_MINOR rejects \`-march=rv64gcv1p0\`; using \`-mcpu=generic_rv64+v\` RVV overrides"
|
|
QJL_RVV="-DQJL_RVV_COMPILE_OPTIONS=-mcpu=generic_rv64+v;-mabi=lp64d"
|
|
POLAR_RVV="-DELIZA_RISCV_RVV_FLAGS=-mcpu=generic_rv64+v;-mabi=lp64d"
|
|
TBQ_RVV="-DTURBOQUANT_RVV_FLAGS=-mcpu=generic_rv64+v+m+a+f+d+c"
|
|
fi
|
|
|
|
TOOL_WRAPPER_DIR="$repo_root/.tmp/riscv64-verify-tools"
|
|
mkdir -p "$TOOL_WRAPPER_DIR"
|
|
cat > "$TOOL_WRAPPER_DIR/zig-ar" <<EOF
|
|
#!/usr/bin/env bash
|
|
exec "$ZIG_BIN" ar "\$@"
|
|
EOF
|
|
cat > "$TOOL_WRAPPER_DIR/zig-ranlib" <<EOF
|
|
#!/usr/bin/env bash
|
|
exec "$ZIG_BIN" ranlib "\$@"
|
|
EOF
|
|
chmod +x "$TOOL_WRAPPER_DIR/zig-ar" "$TOOL_WRAPPER_DIR/zig-ranlib"
|
|
|
|
QEMU_BIN="$(command -v qemu-riscv64-static 2>/dev/null || command -v qemu-riscv64 2>/dev/null || true)"
|
|
|
|
now_iso() { date -u +'%Y-%m-%dT%H:%M:%SZ'; }
|
|
run_started_iso="$(now_iso)"
|
|
|
|
# Per-package configs. The escape-hatch flag is passed unquoted so the
|
|
# semicolon in the CMake list survives.
|
|
build_package() {
|
|
local pkg="$1"
|
|
local extra_flag="$2"
|
|
local pkgdir="packages/native/plugins/$pkg"
|
|
local builddir="$pkgdir/build/riscv64-verify"
|
|
local target
|
|
|
|
if [ ! -f "$pkgdir/CMakeLists.txt" ]; then
|
|
echo "fail: $pkgdir/CMakeLists.txt missing"
|
|
return 1
|
|
fi
|
|
|
|
remove_path_recursive "$builddir"
|
|
|
|
local config_log="$builddir.config.log"
|
|
local build_log="$builddir.build.log"
|
|
mkdir -p "$(dirname "$config_log")"
|
|
|
|
if [ -n "$extra_flag" ]; then
|
|
cmake -S "$pkgdir" -B "$builddir" \
|
|
-DCMAKE_TOOLCHAIN_FILE="$repo_root/packages/native/cmake/toolchain-riscv64-linux-musl.cmake" \
|
|
-DCMAKE_AR="$TOOL_WRAPPER_DIR/zig-ar" \
|
|
-DCMAKE_RANLIB="$TOOL_WRAPPER_DIR/zig-ranlib" \
|
|
"$extra_flag" > "$config_log" 2>&1 || {
|
|
echo "fail: cmake configure (see $config_log)"
|
|
return 1
|
|
}
|
|
else
|
|
cmake -S "$pkgdir" -B "$builddir" \
|
|
-DCMAKE_TOOLCHAIN_FILE="$repo_root/packages/native/cmake/toolchain-riscv64-linux-musl.cmake" \
|
|
-DCMAKE_AR="$TOOL_WRAPPER_DIR/zig-ar" \
|
|
-DCMAKE_RANLIB="$TOOL_WRAPPER_DIR/zig-ranlib" \
|
|
> "$config_log" 2>&1 || {
|
|
echo "fail: cmake configure (see $config_log)"
|
|
return 1
|
|
}
|
|
fi
|
|
case "$pkg" in
|
|
qjl-cpu) target="qjl";;
|
|
polarquant-cpu) target="polarquant";;
|
|
turboquant-cpu) target="turboquant";;
|
|
silero-vad-cpp) target="silero_vad";;
|
|
*) target="";;
|
|
esac
|
|
|
|
if [ -n "$target" ]; then
|
|
cmake --build "$builddir" --target "$target" -j"$JOBS" > "$build_log" 2>&1 || {
|
|
echo "fail: cmake build (see $build_log)"
|
|
return 1
|
|
}
|
|
else
|
|
cmake --build "$builddir" -j"$JOBS" > "$build_log" 2>&1 || {
|
|
echo "fail: cmake build (see $build_log)"
|
|
return 1
|
|
}
|
|
fi
|
|
echo "ok"
|
|
}
|
|
|
|
inspect_artifacts() {
|
|
local pkg="$1"
|
|
local builddir="packages/native/plugins/$pkg/build/riscv64-verify"
|
|
if [ ! -d "$builddir" ]; then return; fi
|
|
# Static libs (.a), shared libs (.so), and top-level executables.
|
|
# We exclude CMake's own machinery (build.make, cmake_install.cmake,
|
|
# CMakeFiles/, *.cmake) which can pick up +x bits on some hosts and
|
|
# produce false negatives. Output is sorted unique so a file present
|
|
# at both maxdepth-1 and maxdepth-2 is only counted once.
|
|
{
|
|
find "$builddir" -maxdepth 2 \( -name "*.a" -o -name "*.so" -o -name "*.so.*" \) -type f -print
|
|
find "$builddir" -maxdepth 1 -type f \( -perm -111 -o -perm -010 -o -perm -001 \) \
|
|
! -name "*.cmake" ! -name "Makefile" ! -name "*.txt" \
|
|
! -name "*.json" ! -name "*.log" ! -name "*.ninja" \
|
|
-print
|
|
} | sort -u
|
|
}
|
|
|
|
is_riscv64_elf() {
|
|
local f="$1"
|
|
local info
|
|
info="$(file -b "$f" 2>/dev/null || true)"
|
|
case "$info" in
|
|
*"UCB RISC-V"*"double-float ABI"*) return 0;;
|
|
"current ar archive") return 0;; # ar archive — element check below
|
|
*) return 1;;
|
|
esac
|
|
}
|
|
|
|
ar_members_are_rv64() {
|
|
local archive="$1"
|
|
# Resolve to an absolute path before we cd into the extract dir,
|
|
# otherwise `ar x` (run from inside extract_dir) can't find a
|
|
# relative archive path.
|
|
case "$archive" in
|
|
/*) ;;
|
|
*) archive="$(cd "$(dirname "$archive")" && pwd)/$(basename "$archive")";;
|
|
esac
|
|
local extract_dir="$archive.verify-extract"
|
|
remove_path_recursive "$extract_dir"
|
|
mkdir -p "$extract_dir"
|
|
( cd "$extract_dir" && ar x "$archive" >/dev/null 2>&1 ) || {
|
|
remove_path_recursive "$extract_dir"
|
|
return 1
|
|
}
|
|
local bad=0
|
|
for member in "$extract_dir"/*.o; do
|
|
[ -f "$member" ] || continue
|
|
if ! file -b "$member" | grep -q "UCB RISC-V"; then
|
|
bad=1
|
|
break
|
|
fi
|
|
done
|
|
remove_path_recursive "$extract_dir"
|
|
[ "$bad" -eq 0 ]
|
|
}
|
|
|
|
pkg_var_name() {
|
|
printf '%s_%s' "$1" "$(printf '%s' "$2" | tr '[:lower:]-' '[:upper:]_')"
|
|
}
|
|
|
|
set_pkg_value() {
|
|
local prefix="$1"
|
|
local pkg="$2"
|
|
local value="$3"
|
|
local name
|
|
name="$(pkg_var_name "$prefix" "$pkg")"
|
|
printf -v "$name" '%s' "$value"
|
|
}
|
|
|
|
get_pkg_value() {
|
|
local prefix="$1"
|
|
local pkg="$2"
|
|
local default="${3:-}"
|
|
local name
|
|
name="$(pkg_var_name "$prefix" "$pkg")"
|
|
eval "printf '%s' \"\${$name:-$default}\""
|
|
}
|
|
|
|
inc_pkg_value() {
|
|
local prefix="$1"
|
|
local pkg="$2"
|
|
local current
|
|
current="$(get_pkg_value "$prefix" "$pkg" 0)"
|
|
set_pkg_value "$prefix" "$pkg" "$((current + 1))"
|
|
}
|
|
|
|
smoke_name_for_pkg() {
|
|
case "$1" in
|
|
qjl-cpu) echo "qjl_int8_smoke";;
|
|
polarquant-cpu) echo "polar_simd_parity_test";;
|
|
turboquant-cpu) echo "turboquant_smoke";;
|
|
silero-vad-cpp) echo "silero_vad_abi_smoke";;
|
|
*) echo "";;
|
|
esac
|
|
}
|
|
|
|
# ── Build phase ───────────────────────────────────────────────────────
|
|
echo "[verify-riscv64] Zig: $ZIG_VERSION ($RVV_OVERRIDE_REASON)"
|
|
echo "[verify-riscv64] Building qjl-cpu …"
|
|
set_pkg_value BUILD_STATUS qjl-cpu "$(build_package qjl-cpu "$QJL_RVV")"
|
|
echo "[verify-riscv64] $(get_pkg_value BUILD_STATUS qjl-cpu | head -1)"
|
|
|
|
echo "[verify-riscv64] Building polarquant-cpu …"
|
|
set_pkg_value BUILD_STATUS polarquant-cpu "$(build_package polarquant-cpu "$POLAR_RVV")"
|
|
echo "[verify-riscv64] $(get_pkg_value BUILD_STATUS polarquant-cpu | head -1)"
|
|
|
|
echo "[verify-riscv64] Building turboquant-cpu …"
|
|
set_pkg_value BUILD_STATUS turboquant-cpu "$(build_package turboquant-cpu "$TBQ_RVV")"
|
|
echo "[verify-riscv64] $(get_pkg_value BUILD_STATUS turboquant-cpu | head -1)"
|
|
|
|
echo "[verify-riscv64] Building silero-vad-cpp …"
|
|
set_pkg_value BUILD_STATUS silero-vad-cpp "$(build_package silero-vad-cpp "")"
|
|
echo "[verify-riscv64] $(get_pkg_value BUILD_STATUS silero-vad-cpp | head -1)"
|
|
|
|
# ── Inspect phase ─────────────────────────────────────────────────────
|
|
for pkg in qjl-cpu polarquant-cpu turboquant-cpu silero-vad-cpp; do
|
|
set_pkg_value ARTIFACT_OK "$pkg" 0
|
|
set_pkg_value ARTIFACT_BAD "$pkg" 0
|
|
if [ "$(get_pkg_value BUILD_STATUS "$pkg")" != "ok" ]; then continue; fi
|
|
while IFS= read -r f; do
|
|
case "$f" in
|
|
*CMakeFiles/*) continue;;
|
|
esac
|
|
if [ -f "$f" ]; then
|
|
if [[ "$f" == *.a ]]; then
|
|
if ar_members_are_rv64 "$f"; then
|
|
inc_pkg_value ARTIFACT_OK "$pkg"
|
|
else
|
|
inc_pkg_value ARTIFACT_BAD "$pkg"
|
|
fi
|
|
elif is_riscv64_elf "$f"; then
|
|
inc_pkg_value ARTIFACT_OK "$pkg"
|
|
else
|
|
inc_pkg_value ARTIFACT_BAD "$pkg"
|
|
fi
|
|
fi
|
|
done < <(inspect_artifacts "$pkg")
|
|
done
|
|
|
|
# ── QEMU smoke phase (optional) ───────────────────────────────────────
|
|
run_smoke_under_qemu() {
|
|
local pkg="$1"
|
|
local smoke_name="$2"
|
|
local smoke_path="packages/native/plugins/$pkg/build/riscv64-verify/$smoke_name"
|
|
if [ -z "$QEMU_BIN" ]; then
|
|
set_pkg_value QEMU_RESULT "$pkg" "skip-no-qemu"
|
|
return
|
|
fi
|
|
if [ ! -x "$smoke_path" ]; then
|
|
set_pkg_value QEMU_RESULT "$pkg" "skip-no-smoke-binary"
|
|
return
|
|
fi
|
|
local log="$smoke_path.qemu.log"
|
|
if "$QEMU_BIN" "$smoke_path" > "$log" 2>&1; then
|
|
set_pkg_value QEMU_RESULT "$pkg" "pass"
|
|
else
|
|
set_pkg_value QEMU_RESULT "$pkg" "fail (exit $?; see $log)"
|
|
fi
|
|
}
|
|
|
|
for pkg in qjl-cpu polarquant-cpu turboquant-cpu silero-vad-cpp; do
|
|
run_smoke_under_qemu "$pkg" "$(smoke_name_for_pkg "$pkg")"
|
|
done
|
|
|
|
# ── Report ────────────────────────────────────────────────────────────
|
|
{
|
|
echo "# RISC-V cross-build verification report"
|
|
echo
|
|
echo "- Generated: \`$run_started_iso\` → \`$(now_iso)\`"
|
|
echo "- Repo root: \`$repo_root\`"
|
|
echo "- Zig: \`$ZIG_VERSION\` ($RVV_OVERRIDE_REASON)"
|
|
echo "- Toolchain: \`packages/native/cmake/toolchain-riscv64-linux-musl.cmake\`"
|
|
echo "- QEMU: \`${QEMU_BIN:-not installed}\`"
|
|
echo
|
|
echo "## Wave 1 + Wave 3 RVV native-plugin cross-build matrix"
|
|
echo
|
|
printf '%-20s | %-10s | %-15s | %s\n' "package" "build" "artifacts (ok/bad)" "qemu smoke"
|
|
printf '%-20s | %-10s | %-15s | %s\n' "--------" "-----" "------------------" "-----------"
|
|
for pkg in qjl-cpu polarquant-cpu turboquant-cpu silero-vad-cpp; do
|
|
local_ok="$(get_pkg_value ARTIFACT_OK "$pkg" 0)"
|
|
local_bad="$(get_pkg_value ARTIFACT_BAD "$pkg" 0)"
|
|
printf '%-20s | %-10s | %3d / %-9d | %s\n' \
|
|
"$pkg" "$(get_pkg_value BUILD_STATUS "$pkg")" "$local_ok" "$local_bad" "$(get_pkg_value QEMU_RESULT "$pkg")"
|
|
done
|
|
echo
|
|
echo "## Per-package ELF inventory"
|
|
echo
|
|
for pkg in qjl-cpu polarquant-cpu turboquant-cpu silero-vad-cpp; do
|
|
echo "### $pkg"
|
|
echo
|
|
if [ "$(get_pkg_value BUILD_STATUS "$pkg")" != "ok" ]; then
|
|
echo "_Build did not succeed; see \`packages/native/plugins/$pkg/build/riscv64-verify.{config,build}.log\`._"
|
|
echo
|
|
continue
|
|
fi
|
|
echo '```'
|
|
inspect_artifacts "$pkg" | while IFS= read -r f; do
|
|
case "$f" in
|
|
*CMakeFiles/*) continue;;
|
|
esac
|
|
short="${f#$repo_root/}"
|
|
short="${short#packages/native/plugins/$pkg/build/riscv64-verify/}"
|
|
info="$(file -b "$f" 2>/dev/null)"
|
|
echo "$short → $info"
|
|
done
|
|
echo '```'
|
|
echo
|
|
done
|
|
echo "## Verdict"
|
|
echo
|
|
verdict_fail=0
|
|
for pkg in qjl-cpu polarquant-cpu turboquant-cpu silero-vad-cpp; do
|
|
if [ "$(get_pkg_value BUILD_STATUS "$pkg")" != "ok" ]; then verdict_fail=$((verdict_fail+1)); fi
|
|
if [ "$(get_pkg_value ARTIFACT_BAD "$pkg" 0)" -gt 0 ]; then verdict_fail=$((verdict_fail+1)); fi
|
|
done
|
|
if [ "$verdict_fail" -eq 0 ]; then
|
|
echo "All 4 native-plugin packages cross-compile to rv64gc / lp64d / RVC. RVV intrinsic TUs are included (gated behind \`*_HAVE_RVV=1\` at the dispatcher level). QEMU smoke status above is informational — without a \`qemu-riscv64-static\` binary the smoke phase is a clean SKIP."
|
|
else
|
|
echo "One or more packages failed verification; see the matrix and per-package logs ($verdict_fail signal(s) tripped)."
|
|
fi
|
|
echo
|
|
echo "## What this report does NOT cover"
|
|
echo
|
|
echo "- Boot of \`cf_riscv64_phone\` Cuttlefish image (needs Linux x86_64 build host + KVM)."
|
|
echo "- Bun-on-riscv64 (upstream \`oven-sh/bun#6266\`; source-build via \`packages/app-core/scripts/bun-riscv64/build.sh\`)."
|
|
echo "- Real-hardware execution of the produced ELFs (this report only verifies cross-compile + ELF arch tag)."
|
|
echo "- RVV kernel numerical parity vs scalar (requires QEMU-V or rv64gcv hardware; deferred)."
|
|
} > "$OUT"
|
|
|
|
echo "[verify-riscv64] Report written: $OUT"
|
|
|
|
if [ "$KEEP_BUILD" = "0" ]; then
|
|
for pkg in qjl-cpu polarquant-cpu turboquant-cpu silero-vad-cpp; do
|
|
remove_path_recursive \
|
|
"packages/native/plugins/$pkg/build/riscv64-verify" \
|
|
"packages/native/plugins/$pkg/build/riscv64-verify.config.log" \
|
|
"packages/native/plugins/$pkg/build/riscv64-verify.build.log"
|
|
done
|
|
fi
|
|
|
|
# Exit code reflects the verdict.
|
|
fail_count=0
|
|
for pkg in qjl-cpu polarquant-cpu turboquant-cpu silero-vad-cpp; do
|
|
if [ "$(get_pkg_value BUILD_STATUS "$pkg")" != "ok" ]; then fail_count=$((fail_count+1)); fi
|
|
if [ "$(get_pkg_value ARTIFACT_BAD "$pkg" 0)" -gt 0 ]; then fail_count=$((fail_count+1)); fi
|
|
done
|
|
exit $fail_count
|