255 lines
7.3 KiB
Bash
Executable File
255 lines
7.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Build, test, and relaunch camera-qrng locally.
|
|
#
|
|
# 1. Kills any running camera-qrng process
|
|
# 2. Runs cargo check and cargo test
|
|
# 3. Builds release for native + all installed cross targets
|
|
# 4. Verifies each built binary
|
|
# 5. Relaunches the native binary in the background
|
|
#
|
|
# Usage:
|
|
# ./scripts/build-test.sh # full build-test cycle
|
|
# ./scripts/build-test.sh --no-launch # build + test only, don't relaunch
|
|
# ./scripts/build-test.sh --quick # native only, skip cross targets
|
|
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
|
LOG_FILE="$PROJECT_DIR/camera-qrng.log"
|
|
PID_FILE="$PROJECT_DIR/.camera-qrng.pid"
|
|
BINARY_NAME="camera-qrng"
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
err() { echo -e "${RED}[ERR]${NC} $1"; }
|
|
step() { echo -e "${CYAN}[STEP]${NC} $1"; }
|
|
|
|
# --- Parse flags ---
|
|
NO_LAUNCH=false
|
|
QUICK=false
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--no-launch) NO_LAUNCH=true ;;
|
|
--quick) QUICK=true ;;
|
|
-h|--help)
|
|
echo "Usage: $0 [--no-launch] [--quick]"
|
|
echo " --no-launch Build and test only, don't relaunch the service"
|
|
echo " --quick Native build only, skip cross-compilation targets"
|
|
exit 0
|
|
;;
|
|
*) err "Unknown flag: $arg"; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
cd "$PROJECT_DIR"
|
|
|
|
# ==================================================
|
|
# 1. Kill previous instance
|
|
# ==================================================
|
|
step "Killing any running $BINARY_NAME..."
|
|
|
|
killed=false
|
|
if [[ -f "$PID_FILE" ]]; then
|
|
old_pid=$(cat "$PID_FILE")
|
|
if kill -0 "$old_pid" 2>/dev/null; then
|
|
kill "$old_pid" 2>/dev/null && killed=true
|
|
# Wait up to 5s for graceful shutdown
|
|
for i in $(seq 1 10); do
|
|
kill -0 "$old_pid" 2>/dev/null || break
|
|
sleep 0.5
|
|
done
|
|
# Force kill if still alive
|
|
if kill -0 "$old_pid" 2>/dev/null; then
|
|
kill -9 "$old_pid" 2>/dev/null
|
|
sleep 0.5
|
|
fi
|
|
fi
|
|
rm -f "$PID_FILE"
|
|
fi
|
|
|
|
# Also kill any stray processes not tracked by PID file
|
|
pgrep -f "target/release/$BINARY_NAME" 2>/dev/null | while read -r pid; do
|
|
if [[ "$pid" != "$$" ]]; then
|
|
kill "$pid" 2>/dev/null && killed=true
|
|
fi
|
|
done
|
|
sleep 0.5
|
|
|
|
if [[ "$killed" == true ]]; then
|
|
info "Previous instance stopped"
|
|
else
|
|
info "No previous instance running"
|
|
fi
|
|
|
|
# ==================================================
|
|
# 2. Check and test
|
|
# ==================================================
|
|
step "Running cargo check..."
|
|
cargo check 2>&1 | tail -3
|
|
info "Check passed"
|
|
|
|
step "Running cargo test..."
|
|
cargo test 2>&1 | tail -5
|
|
info "Tests passed"
|
|
|
|
# ==================================================
|
|
# 3. Build targets
|
|
# ==================================================
|
|
|
|
# Detect native target triple
|
|
ARCH=$(uname -m)
|
|
OS=$(uname -s)
|
|
case "${ARCH}-${OS}" in
|
|
arm64-Darwin) NATIVE_TARGET="aarch64-apple-darwin" ;;
|
|
x86_64-Darwin) NATIVE_TARGET="x86_64-apple-darwin" ;;
|
|
aarch64-Linux) NATIVE_TARGET="aarch64-unknown-linux-gnu" ;;
|
|
x86_64-Linux) NATIVE_TARGET="x86_64-unknown-linux-gnu" ;;
|
|
*) NATIVE_TARGET="native" ;;
|
|
esac
|
|
|
|
# Build targets: always native, optionally cross
|
|
CROSS_TARGETS=()
|
|
if [[ "$QUICK" == false ]]; then
|
|
case "$OS" in
|
|
Darwin)
|
|
# Build both macOS architectures
|
|
if [[ "$ARCH" == "arm64" ]]; then
|
|
CROSS_TARGETS+=("x86_64-apple-darwin")
|
|
else
|
|
CROSS_TARGETS+=("aarch64-apple-darwin")
|
|
fi
|
|
# Linux targets if cross is installed
|
|
if command -v cross &>/dev/null; then
|
|
CROSS_TARGETS+=("aarch64-unknown-linux-gnu" "x86_64-unknown-linux-gnu")
|
|
else
|
|
warn "Skipping Linux targets (install 'cross': cargo install cross)"
|
|
fi
|
|
;;
|
|
Linux)
|
|
if [[ "$ARCH" == "aarch64" ]]; then
|
|
CROSS_TARGETS+=("x86_64-unknown-linux-gnu")
|
|
else
|
|
CROSS_TARGETS+=("aarch64-unknown-linux-gnu")
|
|
fi
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
success=0
|
|
failed=0
|
|
|
|
# --- Native build ---
|
|
step "Building native release ($NATIVE_TARGET)..."
|
|
cargo build --release 2>&1 | tail -3
|
|
NATIVE_BIN="target/release/$BINARY_NAME"
|
|
if [[ -f "$NATIVE_BIN" ]]; then
|
|
info "Native: $(file "$NATIVE_BIN" | sed "s|$PROJECT_DIR/||")"
|
|
success=$((success + 1))
|
|
else
|
|
err "Native binary not found at $NATIVE_BIN"
|
|
failed=$((failed + 1))
|
|
fi
|
|
|
|
# --- Cross targets ---
|
|
for target in "${CROSS_TARGETS[@]}"; do
|
|
step "Building $target..."
|
|
|
|
use_cross=false
|
|
if [[ "$OS" == "Darwin" ]] && [[ "$target" == *"linux"* ]]; then
|
|
use_cross=true
|
|
fi
|
|
|
|
if [[ "$use_cross" == true ]]; then
|
|
if cross build --release --target "$target" 2>&1 | tail -3; then
|
|
bin="target/$target/release/$BINARY_NAME"
|
|
if [[ -f "$bin" ]]; then
|
|
info "$target: $(file "$bin" | sed "s|$PROJECT_DIR/||")"
|
|
success=$((success + 1))
|
|
else
|
|
err "$target binary not found"
|
|
failed=$((failed + 1))
|
|
fi
|
|
else
|
|
err "$target build failed"
|
|
failed=$((failed + 1))
|
|
fi
|
|
else
|
|
if cargo build --release --target "$target" 2>&1 | tail -3; then
|
|
bin="target/$target/release/$BINARY_NAME"
|
|
if [[ -f "$bin" ]]; then
|
|
info "$target: $(file "$bin" | sed "s|$PROJECT_DIR/||")"
|
|
success=$((success + 1))
|
|
else
|
|
err "$target binary not found"
|
|
failed=$((failed + 1))
|
|
fi
|
|
else
|
|
err "$target build failed"
|
|
failed=$((failed + 1))
|
|
fi
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
info "Build results: $success succeeded, $failed failed"
|
|
|
|
if [[ $failed -gt 0 ]]; then
|
|
err "Some builds failed - check output above"
|
|
if [[ "$NO_LAUNCH" == true ]]; then
|
|
exit 1
|
|
fi
|
|
warn "Continuing to launch native binary despite cross-build failures..."
|
|
fi
|
|
|
|
# ==================================================
|
|
# 4. Verify native binary runs
|
|
# ==================================================
|
|
step "Verifying native binary..."
|
|
if [[ -x "$NATIVE_BIN" ]]; then
|
|
info "Binary OK: $(ls -lh "$NATIVE_BIN" | awk '{print $5}') $(file "$NATIVE_BIN" | grep -o 'Mach-O\|ELF\|PE32' || echo 'binary')"
|
|
else
|
|
err "Native binary not executable"
|
|
exit 1
|
|
fi
|
|
|
|
# ==================================================
|
|
# 5. Relaunch
|
|
# ==================================================
|
|
if [[ "$NO_LAUNCH" == true ]]; then
|
|
info "Skipping launch (--no-launch)"
|
|
exit 0
|
|
fi
|
|
|
|
step "Launching $BINARY_NAME in background..."
|
|
nohup "$NATIVE_BIN" > "$LOG_FILE" 2>&1 &
|
|
NEW_PID=$!
|
|
echo "$NEW_PID" > "$PID_FILE"
|
|
|
|
# Give it a moment to start
|
|
sleep 2
|
|
|
|
if kill -0 "$NEW_PID" 2>/dev/null; then
|
|
info "$BINARY_NAME running (PID $NEW_PID)"
|
|
info "Log: $LOG_FILE"
|
|
info "PID file: $PID_FILE"
|
|
echo ""
|
|
head -10 "$LOG_FILE" 2>/dev/null | while IFS= read -r line; do
|
|
echo " $line"
|
|
done
|
|
echo ""
|
|
info "Health check: http://localhost:${PORT:-8787}/health"
|
|
else
|
|
err "$BINARY_NAME failed to start. Log output:"
|
|
cat "$LOG_FILE" 2>/dev/null
|
|
rm -f "$PID_FILE"
|
|
exit 1
|
|
fi
|