149 lines
5.5 KiB
Bash
Executable File
149 lines
5.5 KiB
Bash
Executable File
#!/bin/bash
|
||
# Build Archipelago backend binary for Debian Linux
|
||
#
|
||
# Target architecture:
|
||
# (unset) native host build — unchanged default behavior
|
||
# ARCH=aarch64 build for ARM64 (Pi 5 test installs — see
|
||
# docs/raspberry-pi-test-install.md). On the M2 — our
|
||
# dedicated ARM64 build machine — this runs at native speed
|
||
# (Apple Silicon runs arm64 Linux containers natively).
|
||
# On x86_64 it prefers cargo-zigbuild (fast host cross
|
||
# build) or falls back to an emulated rust:trixie Docker
|
||
# build (needs qemu binfmt, slow).
|
||
#
|
||
# The backend is rustls-only (no OpenSSL dependency), so cross-building needs
|
||
# just a rustup target + the zig linker — no sysroot libraries.
|
||
|
||
set -e
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||
BACKEND_DIR="$PROJECT_ROOT/core/archipelago"
|
||
OUTPUT_DIR="$SCRIPT_DIR/../build/backend"
|
||
|
||
# Resolve target architecture / cross-compile triple.
|
||
ARCH="${ARCH:-native}"
|
||
# Normalize uname -m into our arch vocabulary (macOS reports arm64; the M2
|
||
# builder is an arm64 host even though it produces Linux binaries via Docker).
|
||
case "$(uname -m)" in
|
||
x86_64|amd64) HOST_ARCH="x86_64" ;;
|
||
aarch64|arm64) HOST_ARCH="aarch64" ;;
|
||
*) HOST_ARCH="$(uname -m)" ;;
|
||
esac
|
||
CROSS_TARGET=""
|
||
case "$ARCH" in
|
||
native) ;;
|
||
aarch64|x86_64)
|
||
if [[ "$ARCH" == "$HOST_ARCH" && "$OSTYPE" != "darwin"* ]]; then
|
||
# Linux host building for itself — plain native build
|
||
echo "ℹ️ ARCH=$ARCH matches host — building natively"
|
||
else
|
||
# Explicit target triple — on Apple Silicon (M2) the arm64
|
||
# container runs natively; only x86_64 hosts emulate.
|
||
CROSS_TARGET="${ARCH}-unknown-linux-gnu"
|
||
echo "🎯 Building for $ARCH ($CROSS_TARGET)"
|
||
fi
|
||
;;
|
||
*) echo "❌ ARCH must be 'native', 'aarch64' or 'x86_64' (got: $ARCH)" >&2; exit 1 ;;
|
||
esac
|
||
OUT_NAME="archipelago"
|
||
if [ -n "$CROSS_TARGET" ]; then
|
||
OUT_NAME="archipelago-${ARCH}"
|
||
fi
|
||
|
||
echo "🔨 Building Archipelago backend..."
|
||
echo " Source: $BACKEND_DIR"
|
||
echo " Output: $OUTPUT_DIR/$OUT_NAME"
|
||
echo ""
|
||
|
||
# Create output directory
|
||
mkdir -p "$OUTPUT_DIR"
|
||
|
||
# Check if we should use Docker
|
||
USE_DOCKER=false
|
||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||
USE_DOCKER=true
|
||
echo "🍎 macOS detected - using Docker for Linux build"
|
||
elif ! command -v rustc >/dev/null 2>&1; then
|
||
USE_DOCKER=true
|
||
echo "⚠️ Rust not found - using Docker"
|
||
fi
|
||
|
||
# Cross-build without cargo-zigbuild (e.g. system rust without rustup targets)
|
||
# falls back to the emulated Docker path instead of hard-failing.
|
||
if [ "$USE_DOCKER" != true ] && [ -n "$CROSS_TARGET" ] \
|
||
&& ! command -v cargo-zigbuild >/dev/null 2>&1; then
|
||
echo "⚠️ cargo-zigbuild not found — using the emulated Docker build (slow)"
|
||
USE_DOCKER=true
|
||
fi
|
||
|
||
if [ "$USE_DOCKER" = true ]; then
|
||
echo "🐳 Building in Docker container..."
|
||
# Cross builds in Docker use --platform for an emulated target-arch rust
|
||
# toolchain (needs qemu binfmt; slow but zero host setup). An explicit
|
||
# --target keeps the shared target/ dir from colliding with host-arch
|
||
# builds.
|
||
PLATFORM_ARGS=""
|
||
INNER_BUILD="cargo build --release"
|
||
INNER_COPY="cp ../target/release/archipelago /output/${OUT_NAME}"
|
||
if [ -n "$CROSS_TARGET" ]; then
|
||
PLATFORM_ARGS="--platform linux/$([[ "$ARCH" == "aarch64" ]] && echo arm64 || echo amd64)"
|
||
INNER_BUILD="rustup target add ${CROSS_TARGET} && cargo build --release --target ${CROSS_TARGET}"
|
||
INNER_COPY="cp ../target/${CROSS_TARGET}/release/archipelago /output/${OUT_NAME}"
|
||
if [[ "$(uname -m)" == "arm64" && "$ARCH" == "aarch64" ]]; then
|
||
echo " (Apple Silicon — arm64 containers run natively here)"
|
||
else
|
||
echo " (emulated ${ARCH} build — expect it to be slow)"
|
||
fi
|
||
fi
|
||
# shellcheck disable=SC2086
|
||
docker run --rm \
|
||
-v "$PROJECT_ROOT:/workspace" \
|
||
-v "$OUTPUT_DIR:/output" \
|
||
-w /workspace/core/archipelago \
|
||
$PLATFORM_ARGS \
|
||
rust:trixie \
|
||
sh -c "
|
||
echo '📦 Installing build dependencies...'
|
||
apt-get update && apt-get install -y pkg-config libssl-dev
|
||
|
||
echo '🔨 Building Archipelago backend...'
|
||
${INNER_BUILD}
|
||
|
||
echo '📋 Copying binary to output...'
|
||
${INNER_COPY}
|
||
|
||
echo '✅ Build complete!'
|
||
ls -lh /output/
|
||
"
|
||
elif [ -n "$CROSS_TARGET" ]; then
|
||
# Host-side cross build: cargo-zigbuild (zig as linker) — much faster than
|
||
# the emulated Docker path. On Arch: pacman -S cargo-zigbuild (pulls zig).
|
||
echo "🐧 Cross-compiling on host with cargo-zigbuild..."
|
||
rustup target add "$CROSS_TARGET"
|
||
cd "$BACKEND_DIR"
|
||
cargo zigbuild --release --target "$CROSS_TARGET"
|
||
|
||
cp "../target/${CROSS_TARGET}/release/archipelago" "$OUTPUT_DIR/$OUT_NAME"
|
||
else
|
||
# Native Linux build
|
||
echo "🐧 Building natively..."
|
||
cd "$BACKEND_DIR"
|
||
cargo build --release
|
||
|
||
cp "../target/release/archipelago" "$OUTPUT_DIR/archipelago"
|
||
fi
|
||
|
||
# Strip binary for smaller size (GNU strip handles foreign-arch ELF too).
|
||
if [ -f "$OUTPUT_DIR/$OUT_NAME" ]; then
|
||
if command -v strip >/dev/null 2>&1 && [[ "$OSTYPE" != "darwin"* ]]; then
|
||
strip "$OUTPUT_DIR/$OUT_NAME"
|
||
fi
|
||
echo ""
|
||
echo "✅ Backend built: $OUTPUT_DIR/$OUT_NAME"
|
||
ls -lh "$OUTPUT_DIR/$OUT_NAME"
|
||
else
|
||
echo "❌ Build failed - binary not found"
|
||
exit 1
|
||
fi
|