#!/usr/bin/env bash # Build camera-qrng for multiple platforms. # Usage: ./scripts/build-release.sh [target...] # # Targets: # native - Build for current platform (default) # aarch64-apple - Apple Silicon (M1/M2/M3) # x86_64-apple - Intel Mac # aarch64-linux - Linux ARM64 (Raspberry Pi 4/5, etc.) # x86_64-linux - Linux x86_64 # all - Build all targets # # Prerequisites: # - Rust toolchain with cross-compilation targets # - For Linux cross-compile from macOS: cross (cargo install cross) # # Install targets: # rustup target add aarch64-apple-darwin x86_64-apple-darwin # rustup target add aarch64-unknown-linux-gnu x86_64-unknown-linux-gnu set -e SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" OUTPUT_DIR="$PROJECT_DIR/release" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' info() { echo -e "${GREEN}[INFO]${NC} $1"; } warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; } get_rust_target() { case "$1" in aarch64-apple) echo "aarch64-apple-darwin" ;; x86_64-apple) echo "x86_64-apple-darwin" ;; aarch64-linux) echo "aarch64-unknown-linux-gnu" ;; x86_64-linux) echo "x86_64-unknown-linux-gnu" ;; *) echo "" ;; esac } get_friendly_name() { case "$1" in aarch64-apple) echo "Apple Silicon (M1/M2/M3)" ;; x86_64-apple) echo "Intel Mac" ;; aarch64-linux) echo "Linux ARM64 (Raspberry Pi)" ;; x86_64-linux) echo "Linux x86_64" ;; *) echo "$1" ;; esac } get_output_name() { case "$1" in aarch64-apple) echo "camera-qrng-aarch64-macos" ;; x86_64-apple) echo "camera-qrng-x86_64-macos" ;; aarch64-linux) echo "camera-qrng-aarch64-linux" ;; x86_64-linux) echo "camera-qrng-x86_64-linux" ;; *) echo "camera-qrng-$1" ;; esac } build_native() { info "Building for native platform..." cargo build --release local binary="$PROJECT_DIR/target/release/camera-qrng" if [[ -f "$binary" ]]; then cp "$binary" "$OUTPUT_DIR/camera-qrng-native" info "Built: $OUTPUT_DIR/camera-qrng-native" file "$OUTPUT_DIR/camera-qrng-native" fi } build_target() { local shortname=$1 local target target=$(get_rust_target "$shortname") local friendly friendly=$(get_friendly_name "$shortname") local output_name output_name=$(get_output_name "$shortname") if [[ -z "$target" ]]; then error "Unknown target: $shortname" fi info "Building for $friendly ($target)..." # Check if target is installed if ! rustup target list --installed 2>/dev/null | grep -q "$target"; then warn "Target $target not installed. Installing..." rustup target add "$target" || { warn "Failed to add target $target. Skipping." return 1 } fi # For Linux targets from macOS, try cross first local use_cross=false if [[ "$OSTYPE" == "darwin"* ]] && [[ "$target" == *"linux"* ]]; then if command -v cross &> /dev/null; then use_cross=true else warn "Linux cross-compilation requires 'cross'. Install with: cargo install cross" warn "Attempting native cargo build (may fail due to linker issues)..." fi fi if [[ "$use_cross" == true ]]; then cross build --release --target "$target" 2>&1 || { warn "Cross build failed for $target" return 1 } else cargo build --release --target "$target" 2>&1 || { warn "Build failed for $target" return 1 } fi local binary="$PROJECT_DIR/target/$target/release/camera-qrng" if [[ -f "$binary" ]]; then cp "$binary" "$OUTPUT_DIR/$output_name" info "Built: $OUTPUT_DIR/$output_name" file "$OUTPUT_DIR/$output_name" else warn "Binary not found at $binary" return 1 fi } install_manpage() { info "Copying manpage..." if [[ -f "$PROJECT_DIR/man/camera-qrng.1" ]]; then cp "$PROJECT_DIR/man/camera-qrng.1" "$OUTPUT_DIR/" gzip -c "$PROJECT_DIR/man/camera-qrng.1" > "$OUTPUT_DIR/camera-qrng.1.gz" info "Manpage: $OUTPUT_DIR/camera-qrng.1.gz" fi } show_usage() { cat << EOF Usage: $0 [target...] Targets: native Build for current platform (default) aarch64-apple Apple Silicon (M1/M2/M3) x86_64-apple Intel Mac aarch64-linux Linux ARM64 (Raspberry Pi 4/5) x86_64-linux Linux x86_64 all Build all targets Examples: $0 # Build native only $0 all # Build all platforms $0 aarch64-apple # Build Apple Silicon only $0 aarch64-linux x86_64-linux # Build Linux targets EOF } main() { cd "$PROJECT_DIR" mkdir -p "$OUTPUT_DIR" local success=0 local failed=0 # Default to native if no args if [[ $# -eq 0 ]]; then set -- "native" fi # Process targets for target in "$@"; do case "$target" in -h|--help) show_usage exit 0 ;; all) for t in native aarch64-apple x86_64-apple aarch64-linux x86_64-linux; do if [[ "$t" == "native" ]]; then build_native && success=$((success+1)) || failed=$((failed+1)) else build_target "$t" && success=$((success+1)) || failed=$((failed+1)) fi done ;; native) build_native && success=$((success+1)) || failed=$((failed+1)) ;; *) build_target "$target" && success=$((success+1)) || failed=$((failed+1)) ;; esac done install_manpage echo "" info "Build complete: $success succeeded, $failed failed" echo "" info "Release artifacts in: $OUTPUT_DIR/" ls -la "$OUTPUT_DIR/" if [[ $failed -gt 0 ]]; then exit 1 fi } main "$@"