#!/usr/bin/env bash # build-targets.sh — Build the El VM (elvm) for all supported platforms. # # Usage: # ./build-targets.sh # build all targets # ./build-targets.sh --list # list targets and prerequisites # ./build-targets.sh x86_64-apple-darwin # build a specific target # # Prerequisites: # - Rust toolchain (rustup) with cross-compilation targets installed # - For Linux targets: cross-linkers (see comments below) # # Install a target: # rustup target add # # For cross-compilation from macOS to Linux: # brew install FiloSottile/musl-cross/musl-cross # # or use `cross` (https://github.com/cross-rs/cross): # cargo install cross --git https://github.com/cross-rs/cross set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" OUTPUT_DIR="${SCRIPT_DIR}/dist/elvm" # ── Target definitions ──────────────────────────────────────────────────────── # Format: "target:description:linker_hint" declare -a TARGETS=( "x86_64-unknown-linux-gnu:Linux x86_64 (glibc):brew install FiloSottile/musl-cross/musl-cross or use 'cross'" "aarch64-unknown-linux-gnu:Linux ARM64 (glibc):brew install FiloSottile/musl-cross/musl-cross or use 'cross'" "x86_64-unknown-linux-musl:Linux x86_64 (musl, static):brew install FiloSottile/musl-cross/musl-cross" "aarch64-unknown-linux-musl:Linux ARM64 (musl, static):brew install aarch64-unknown-linux-musl cross-linker" "x86_64-apple-darwin:macOS Intel:native (no cross tooling needed on macOS)" "aarch64-apple-darwin:macOS Apple Silicon:native (no cross tooling needed on macOS)" "x86_64-pc-windows-gnu:Windows x86_64:brew install mingw-w64" "aarch64-pc-windows-msvc:Windows ARM64:requires Windows MSVC SDK (Windows only)" ) # ── Helpers ─────────────────────────────────────────────────────────────────── RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color ok() { echo -e " ${GREEN}✓${NC} $*"; } warn() { echo -e " ${YELLOW}⚠${NC} $*"; } fail() { echo -e " ${RED}✗${NC} $*"; } # ── List mode ───────────────────────────────────────────────────────────────── if [[ "${1:-}" == "--list" ]]; then echo "" echo "El VM cross-compilation targets" echo "================================" echo "" for entry in "${TARGETS[@]}"; do IFS=':' read -r target desc hint <<< "$entry" printf " %-42s %s\n" "$target" "$desc" printf " %-42s Prereq: %s\n" "" "$hint" echo "" done echo "Install a target: rustup target add " echo "List installed: rustup target list --installed" exit 0 fi # ── Filter targets ──────────────────────────────────────────────────────────── if [[ $# -gt 0 && "${1:-}" != "--list" ]]; then # Build only the specified target(s). SELECTED=("$@") else # Build all targets. SELECTED=() for entry in "${TARGETS[@]}"; do IFS=':' read -r target _ _ <<< "$entry" SELECTED+=("$target") done fi # ── Build ───────────────────────────────────────────────────────────────────── echo "" echo -e "${BLUE}El VM — cross-platform build${NC}" echo "Output directory: $OUTPUT_DIR" echo "" mkdir -p "$OUTPUT_DIR" BUILT=0 SKIPPED=0 FAILED=0 for target in "${SELECTED[@]}"; do # Find description for this target. desc="$target" for entry in "${TARGETS[@]}"; do IFS=':' read -r t d _ <<< "$entry" if [[ "$t" == "$target" ]]; then desc="$d"; break; fi done echo -e "${BLUE}→ Building $target${NC} ($desc)" # Check if the Rust target is installed. if ! rustup target list --installed 2>/dev/null | grep -q "^$target\b"; then warn "Target $target not installed — installing..." if rustup target add "$target" 2>/dev/null; then ok "Installed $target" else fail "Cannot install $target — skipping" ((SKIPPED++)) continue fi fi # Attempt to build. binary_suffix="" if [[ "$target" == *"windows"* ]]; then binary_suffix=".exe" fi binary_name="elvm-${target}${binary_suffix}" output_path="$OUTPUT_DIR/$binary_name" if (cd "$SCRIPT_DIR" && cargo build --release --target "$target" -p elvm 2>&1 | tail -5); then src="$SCRIPT_DIR/target/$target/release/elvm${binary_suffix}" if [[ -f "$src" ]]; then cp "$src" "$output_path" size=$(du -h "$output_path" | cut -f1) ok "Built $binary_name ($size)" ((BUILT++)) else fail "Binary not found at $src" ((FAILED++)) fi else fail "Build failed for $target (cross-linker may be missing — see --list)" ((FAILED++)) fi echo "" done # ── Summary ─────────────────────────────────────────────────────────────────── echo "────────────────────────────────" echo "Built: $BUILT" echo "Skipped: $SKIPPED" echo "Failed: $FAILED" if [[ $BUILT -gt 0 ]]; then echo "" echo "Artifacts:" ls -lh "$OUTPUT_DIR/" fi echo "" if [[ $FAILED -gt 0 ]]; then echo -e "${YELLOW}Some targets failed. Run './build-targets.sh --list' for prerequisites.${NC}" exit 1 fi