188 lines
5.1 KiB
Bash
Executable File
188 lines
5.1 KiB
Bash
Executable File
#!/bin/bash
|
||
# NIP ARM64 Static Build Script using Zig
|
||
# Builds a fully static ARM64 binary using Zig as C compiler with musl
|
||
set -e
|
||
|
||
echo "🚀 Building NIP for ARM64 (aarch64-linux-musl) using Zig"
|
||
echo "========================================================="
|
||
echo ""
|
||
|
||
# Check dependencies
|
||
if ! command -v nim &> /dev/null; then
|
||
echo "❌ Error: Nim compiler not found"
|
||
exit 1
|
||
fi
|
||
|
||
if ! command -v zig &> /dev/null; then
|
||
echo "❌ Error: Zig compiler not found"
|
||
exit 1
|
||
fi
|
||
|
||
echo "📋 Nim version: $(nim --version | head -1)"
|
||
echo "📋 Zig version: $(zig version)"
|
||
echo ""
|
||
|
||
# Create Zig wrapper that shadows aarch64-linux-gnu-gcc
|
||
ZIG_WRAPPER_DIR="/tmp/nip-zig-wrappers-arm64"
|
||
rm -rf "$ZIG_WRAPPER_DIR"
|
||
mkdir -p "$ZIG_WRAPPER_DIR"
|
||
|
||
# Create a wrapper named exactly "aarch64-linux-gnu-gcc" that calls zig cc
|
||
# This shadows the system's aarch64-linux-gnu-gcc when prepended to PATH
|
||
# Filters out x86-specific compile flags AND problematic linker flags
|
||
cat > "$ZIG_WRAPPER_DIR/aarch64-linux-gnu-gcc" << 'WRAPPER'
|
||
#!/bin/bash
|
||
# Zig CC wrapper for ARM64 cross-compilation
|
||
# Shadows system's aarch64-linux-gnu-gcc and filters incompatible flags
|
||
|
||
FILTERED_ARGS=()
|
||
echo "Wrapper called with:" >> /tmp/wrapper.log
|
||
printf "'%s' " "$@" >> /tmp/wrapper.log
|
||
echo "" >> /tmp/wrapper.log
|
||
|
||
for arg in "$@"; do
|
||
case "$arg" in
|
||
# Skip x86-specific compile flags
|
||
-mpclmul|-maes|-msse*|-mavx*|-mno-80387|-fcf-protection|-fstack-clash-protection)
|
||
;;
|
||
-march=x86*|-march=native)
|
||
;;
|
||
-mtune=haswell|-mtune=skylake|-mtune=generic)
|
||
;;
|
||
-Wp,-D_FORTIFY_SOURCE=*)
|
||
;;
|
||
-flto)
|
||
# LTO can cause issues with zig cross-compile
|
||
;;
|
||
# Skip dynamic library flags that don't work with musl static
|
||
-ldl)
|
||
# musl's libc.a includes dl* functions, no separate libdl needed
|
||
;;
|
||
# Filter all march/mtune flags to avoid zig cc conflicts
|
||
-m64|-m32|-march=*|-mtune=*|-mcpu=*|-Xclang*|-target-feature*)
|
||
# skip host-specific flags
|
||
;;
|
||
*)
|
||
FILTERED_ARGS+=("$arg")
|
||
;;
|
||
esac
|
||
done
|
||
|
||
exec zig cc -target aarch64-linux-musl "${FILTERED_ARGS[@]}"
|
||
WRAPPER
|
||
chmod +x "$ZIG_WRAPPER_DIR/aarch64-linux-gnu-gcc"
|
||
|
||
echo "✅ Created Zig wrapper at $ZIG_WRAPPER_DIR/aarch64-linux-gnu-gcc"
|
||
echo ""
|
||
|
||
# Clean previous builds and cache
|
||
echo "🧹 Cleaning previous ARM64 builds and Nim cache..."
|
||
rm -f nip-arm64 nip_arm64 nip-arm64-musl
|
||
rm -rf ~/.cache/nim/nip_*
|
||
rm -rf /tmp/nip-arm64-cache
|
||
echo ""
|
||
|
||
# Prepend our wrapper to PATH
|
||
export PATH="$ZIG_WRAPPER_DIR:$PATH"
|
||
|
||
# Verify our wrapper is first in PATH
|
||
FOUND_GCC=$(which aarch64-linux-gnu-gcc)
|
||
echo "🔍 Using gcc wrapper: $FOUND_GCC"
|
||
echo ""
|
||
|
||
# Compile statically
|
||
echo "🔨 Building optimized ARM64 static binary..."
|
||
echo " Target: aarch64-linux-musl (static via Zig)"
|
||
echo " This may take a few minutes..."
|
||
|
||
nim c \
|
||
--cpu:arm64 \
|
||
--os:linux \
|
||
--cc:gcc \
|
||
--gcc.exe:"$ZIG_WRAPPER_DIR/aarch64-linux-gnu-gcc" \
|
||
--gcc.linkerexe:"$ZIG_WRAPPER_DIR/aarch64-linux-gnu-gcc" \
|
||
--passC:"-O2" \
|
||
--passC:"-w" \
|
||
--passL:-static \
|
||
--passL:-s \
|
||
-d:release \
|
||
-d:danger \
|
||
-d:nimcrypto_disable_neon \
|
||
-d:nimcrypto_no_asm \
|
||
-d:nimcrypto_sysrand \
|
||
--opt:size \
|
||
--mm:orc \
|
||
--threads:on \
|
||
--nimcache:/tmp/nip-arm64-cache \
|
||
--skipProjCfg \
|
||
--out:nip-arm64 \
|
||
src/nip.nim 2>&1 | tee /tmp/nip-arm64-build.log
|
||
|
||
if [ ! -f "nip-arm64" ]; then
|
||
echo ""
|
||
echo "❌ Build failed! Check /tmp/nip-arm64-build.log for details"
|
||
echo "Last 20 lines of error:"
|
||
tail -20 /tmp/nip-arm64-build.log
|
||
exit 1
|
||
fi
|
||
|
||
echo ""
|
||
echo "✅ Build successful!"
|
||
echo ""
|
||
|
||
# Show binary info
|
||
echo "📊 Binary Information:"
|
||
ls -lh nip-arm64
|
||
echo ""
|
||
|
||
echo "🔍 File details:"
|
||
file nip-arm64
|
||
echo ""
|
||
|
||
# Verify it's ARM64
|
||
if file nip-arm64 | grep -q "ARM aarch64"; then
|
||
echo "✅ Verified: Binary is ARM64 aarch64"
|
||
else
|
||
echo "⚠️ Binary may not be ARM64 - check file output above"
|
||
fi
|
||
echo ""
|
||
|
||
# Verify static linking with readelf
|
||
echo "🔍 Verifying static linking..."
|
||
if readelf -d nip-arm64 2>/dev/null | grep -q "NEEDED"; then
|
||
echo "⚠️ Binary has dynamic dependencies:"
|
||
readelf -d nip-arm64 2>/dev/null | grep NEEDED
|
||
else
|
||
echo "✅ No dynamic dependencies found (fully static)"
|
||
fi
|
||
echo ""
|
||
|
||
# Test with QEMU if available
|
||
echo "🧪 Testing binary with QEMU user-mode emulation..."
|
||
if command -v qemu-aarch64 &> /dev/null; then
|
||
if timeout 10 qemu-aarch64 ./nip-arm64 --version 2>&1; then
|
||
echo "✅ Binary works under QEMU aarch64 emulation"
|
||
else
|
||
echo "⚠️ Binary may need additional setup"
|
||
fi
|
||
else
|
||
echo "ℹ️ QEMU aarch64 user-mode not available"
|
||
fi
|
||
echo ""
|
||
|
||
# Create output directory
|
||
OUTPUT_DIR="build/arm64"
|
||
mkdir -p "$OUTPUT_DIR"
|
||
cp nip-arm64 "$OUTPUT_DIR/nip"
|
||
chmod +x "$OUTPUT_DIR/nip"
|
||
|
||
echo "🎉 ARM64 build complete!"
|
||
echo ""
|
||
echo "📋 Build Summary:"
|
||
echo " Binary: nip-arm64"
|
||
echo " Target: aarch64-linux-musl (static)"
|
||
echo " Size: $(ls -lh nip-arm64 | awk '{print $5}')"
|
||
echo " Output: $OUTPUT_DIR/nip"
|
||
echo ""
|
||
echo "📦 Ready for NexBox integration!"
|