#!/usr/bin/env bash set -e # Nexus Rumpk Build Script v0.4 # "Split Brain" Networking Edition RUMPK_DIR=$(pwd) BUILD_DIR="$RUMPK_DIR/build" mkdir -p "$BUILD_DIR" export ZIG_GLOBAL_CACHE_DIR="$BUILD_DIR/.zig-cache" export ZIG_LOCAL_CACHE_DIR="$BUILD_DIR/.zig-cache-local" ARCH=${1:-riscv64} case $ARCH in riscv64) ZIG_TARGET="riscv64-freestanding-none" ZIG_OBJ_FLAGS="-mcpu=sifive_u54 -mcmodel=medany" ARCH_FLAGS="-mcpu=sifive_u54 -mabi=lp64d -mcmodel=medany -ffunction-sections -fdata-sections" NIM_CPU="riscv64" NIM_DEFINE="riscv64" ENTRY_FILE="riscv" ;; x86_64) ZIG_TARGET="x86_64-freestanding-none" ARCH_FLAGS="-mno-red-zone" NIM_CPU="amd64" NIM_DEFINE="x86_64" ENTRY_FILE="x86_64" ;; aarch64) ZIG_TARGET="aarch64-freestanding-none" ARCH_FLAGS="" NIM_CPU="arm64" NIM_DEFINE="aarch64" ENTRY_FILE="aarch64" ;; *) echo "Unsupported architecture: $ARCH" exit 1 ;; esac echo "╔═══════════════════════════════════════╗" echo "║ RUMPK MULTI-ARCH BUILD v0.4 ║" echo "║ Architecture: $ARCH " echo "╚═══════════════════════════════════════╝" # ========================================================= # Step 1: Compile Zig L0 (HAL + libc stubs) # ========================================================= echo "[1/8] Compiling Zig L0 (HAL + libc stubs)..." zig build-obj \ -target $ZIG_TARGET \ $ZIG_OBJ_FLAGS \ -O ReleaseFast \ "$RUMPK_DIR/hal/entry_$ENTRY_FILE.zig" \ --name hal mv hal.o "$BUILD_DIR/hal.o" echo " → $BUILD_DIR/hal.o" zig build-obj \ -target $ZIG_TARGET \ $ZIG_OBJ_FLAGS \ -O ReleaseFast \ "$RUMPK_DIR/hal/stubs.zig" \ --name stubs mv stubs.o "$BUILD_DIR/stubs.o" echo " → $BUILD_DIR/stubs.o" zig build-obj \ -target $ZIG_TARGET \ $ZIG_OBJ_FLAGS \ -O ReleaseFast \ "$RUMPK_DIR/hal/channel.zig" \ --name channel mv channel.o "$BUILD_DIR/channel.o" echo " → $BUILD_DIR/channel.o" # Compile NexShell NPL (Immune System Voice) echo "[1.1/8] Compiling NexShell NPL..." zig build-obj \ -target $ZIG_TARGET \ $ZIG_OBJ_FLAGS \ -O ReleaseFast \ "$RUMPK_DIR/src/npl/system/nexshell.zig" \ --name nexshell mv nexshell.o "$BUILD_DIR/nexshell.o" echo " → $BUILD_DIR/nexshell.o" # ========================================================= # Step 2: Compile context switch assembly # ========================================================= echo "[2/8] Compiling context switch ($ARCH)..." zig cc \ -target $ZIG_TARGET \ $ARCH_FLAGS \ -ffreestanding \ -c "$RUMPK_DIR/hal/arch/$ARCH/switch.S" \ -o "$BUILD_DIR/switch.o" echo " → $BUILD_DIR/switch.o" # ========================================================= # Step 2.1: Compile Monocypher # ========================================================= echo "[2.1/8] Compiling Monocypher..." zig cc \ -target $ZIG_TARGET \ -ffreestanding \ -fno-stack-protector \ -fno-builtin \ -O3 \ -c "$RUMPK_DIR/hal/crypto/monocypher.c" \ -o "$BUILD_DIR/monocypher.o" echo " → $BUILD_DIR/monocypher.o" # ========================================================= # Step 2.2: Compile LwIP (Kernel Stack) # ========================================================= # echo "[2.2/8] Compiling LwIP (Kernel)..." # LWIP_CORE_FILES=( # "src/core/init.c" # "src/core/def.c" # "src/core/dns.c" # "src/core/inet_chksum.c" # "src/core/ip.c" # "src/core/mem.c" # "src/core/memp.c" # "src/core/netif.c" # "src/core/pbuf.c" # "src/core/raw.c" # "src/core/stats.c" # "src/core/sys.c" # "src/core/tcp.c" # "src/core/tcp_in.c" # "src/core/tcp_out.c" # "src/core/timeouts.c" # "src/core/udp.c" # "src/core/ipv4/autoip.c" # "src/core/ipv4/dhcp.c" # "src/core/ipv4/etharp.c" # "src/core/ipv4/icmp.c" # "src/core/ipv4/igmp.c" # "src/core/ipv4/ip4.c" # "src/core/ipv4/ip4_addr.c" # "src/core/ipv4/ip4_frag.c" # "src/netif/ethernet.c" # ) # # for cfile in "${LWIP_CORE_FILES[@]}"; do # cfile_path="$RUMPK_DIR/vendor/lwip/$cfile" # objname=$(basename "$cfile" .c) # zig cc \ # -target $ZIG_TARGET \ # $ARCH_FLAGS \ # -ffreestanding \ # -fno-stack-protector \ # -fno-builtin \ # -O2 \ # -I"$RUMPK_DIR/core/include" \ # -I"$RUMPK_DIR/core/net" \ # -I"$RUMPK_DIR/vendor/lwip/src/include" \ # -c "$cfile_path" \ # -o "$BUILD_DIR/lwip_kernel_$objname.o" # done # ========================================================= # Step 2.3: Compile LwIP (Membrane Stack) # ========================================================= echo "[2.3/8] Compiling LwIP (Membrane)..." for cfile in "${LWIP_CORE_FILES[@]}"; do cfile_path="$RUMPK_DIR/vendor/lwip/$cfile" objname=$(basename "$cfile" .c) zig cc \ -target $ZIG_TARGET \ $ARCH_FLAGS \ -ffreestanding \ -fno-stack-protector \ -fno-builtin \ -O2 \ -I"$RUMPK_DIR/core/include" \ -I"$RUMPK_DIR/core/net" \ -I"$RUMPK_DIR/libs/membrane/include" \ -I"$RUMPK_DIR/vendor/lwip/src/include" \ -c "$cfile_path" \ -o "$BUILD_DIR/lwip_membrane_$objname.o" done LWIP_MEMBRANE_OBJS=$(ls $BUILD_DIR/lwip_membrane_*.o) # Compile sys_arch.c (LwIP Platform Abstraction) echo "[2.4/8] Compiling LwIP Platform Layer (sys_arch.c)..." # zig cc \ # -target $ZIG_TARGET \ # $ARCH_FLAGS \ # -ffreestanding \ # -fno-stack-protector \ # -fno-builtin \ # -O2 \ # -I"$RUMPK_DIR/core/include" \ # -I"$RUMPK_DIR/core/net" \ # -I"$RUMPK_DIR/vendor/lwip/src/include" \ # -c "$RUMPK_DIR/core/net/sys_arch.c" \ # -o "$BUILD_DIR/sys_arch.o" # # echo " → LwIP objects compiled." # ========================================================= # Step 3: Compile Nim L1 (Kernel + Fibers) # ========================================================= echo "[3/8] Compiling Nim L1 (Kernel + Fibers)..." mkdir -p "$BUILD_DIR/nimcache" nim c \ --cpu:$NIM_CPU \ --os:any \ --mm:arc \ --noMain:on \ --cc:clang \ --passC:"-target ${ZIG_TARGET/-freestanding-none/-unknown-none} -ffreestanding -fno-stack-protector -fno-builtin $ARCH_FLAGS -I$RUMPK_DIR/core/include" \ --define:useMalloc \ --define:nimNoLibc \ --define:noSignalHandler \ --define:$NIM_DEFINE \ -d:release \ -d:danger \ --nimcache:"$BUILD_DIR/nimcache" \ --path:"$RUMPK_DIR/core" \ -c \ "$RUMPK_DIR/core/kernel.nim" # ========================================================= # Step 4: Compile Nim C files # ========================================================= echo "[4/8] Compiling Nim C files..." zig cc \ -target $ZIG_TARGET \ $ARCH_FLAGS \ -ffreestanding \ -fno-stack-protector \ -fno-builtin \ -O2 \ -I"$RUMPK_DIR/core/include" \ -c "$RUMPK_DIR/core/cstubs.c" \ -o "$BUILD_DIR/cstubs.o" echo " → $BUILD_DIR/cstubs.o" NIM_OBJS="" for cfile in "$BUILD_DIR/nimcache"/*.c; do ofile="${cfile%.c}.o" zig cc \ -target $ZIG_TARGET \ -ffreestanding \ -fno-stack-protector \ -fno-builtin \ -fno-sanitize=all \ $ARCH_FLAGS \ -I"$RUMPK_DIR/core/include" \ -I/usr/lib/nim \ -I"$RUMPK_DIR/core" \ -c "$cfile" \ -o "$ofile" NIM_OBJS="$NIM_OBJS $ofile" done echo " → $BUILD_DIR/nimcache/*.o" # ========================================================= # Step 4.1: Compile Overrides (Math/Atomics Stubs) # ========================================================= echo "[4.1/8] Compiling Sovereign Overrides..." zig cc \ -target $ZIG_TARGET \ $ARCH_FLAGS \ -ffreestanding \ -fno-stack-protector \ -fno-builtin \ -O2 \ -I"$RUMPK_DIR/core/include" \ -c "$RUMPK_DIR/core/overrides.c" \ -o "$BUILD_DIR/overrides.o" echo " → $BUILD_DIR/overrides.o" # ========================================================= # Step 5: Compile Membrane Library (libnexus.a) # ========================================================= echo "[5/8] Compiling Membrane Library (libnexus.a)..." mkdir -p "$BUILD_DIR/membrane_nimcache" # Compile clib.c (The Mini-Libc) zig cc \ -target $ZIG_TARGET \ $ARCH_FLAGS \ -ffreestanding \ -fno-stack-protector \ -fno-builtin \ -O2 \ -I"$RUMPK_DIR/core/include" \ -c "$RUMPK_DIR/libs/membrane/clib.c" \ -o "$BUILD_DIR/clib.o" # Compile sys_arch.c (Membrane LwIP Platform Layer) zig cc \ -target $ZIG_TARGET \ $ARCH_FLAGS \ -ffreestanding \ -fno-stack-protector \ -fno-builtin \ -O2 \ -I"$RUMPK_DIR/core/include" \ -I"$RUMPK_DIR/libs/membrane/include" \ -I"$RUMPK_DIR/vendor/lwip/src/include" \ -c "$RUMPK_DIR/libs/membrane/sys_arch.c" \ -o "$BUILD_DIR/membrane_sys_arch.o" nim c \ --cpu:$NIM_CPU \ --os:any \ -d:is_membrane \ -d:danger \ -d:useMalloc \ -d:nimNoLibc \ -d:noSignalHandler \ --gc:arc \ --panics:on \ --noMain \ --hint:Conf:off \ --hint:OSLib:off \ --nimcache:"$BUILD_DIR/membrane_nimcache" \ --path:"$RUMPK_DIR/libs/membrane" \ --path:"$RUMPK_DIR/core" \ -c \ "$RUMPK_DIR/libs/membrane/libc.nim" MEMBRANE_NIM_OBJS="" for cfile in "$BUILD_DIR/membrane_nimcache"/*.c; do ofile="${cfile%.c}.o" zig cc \ -target $ZIG_TARGET \ -ffreestanding \ -fno-stack-protector \ -fno-builtin \ -fno-sanitize=all \ $ARCH_FLAGS \ -I"$RUMPK_DIR/core/include" \ -I/usr/lib/nim \ -I"$RUMPK_DIR/core" \ -I"$RUMPK_DIR/libs/membrane" \ -I"$RUMPK_DIR/libs/membrane/include" \ -I"$RUMPK_DIR/vendor/lwip/src/include" \ -c "$cfile" \ -o "$ofile" MEMBRANE_NIM_OBJS="$MEMBRANE_NIM_OBJS $ofile" done # ========================================================= # Step 5.1: Compile Subject Zig Object (Diamond Glass) # ========================================================= echo "[5.1/8] Compiling Subject Zig Object..." SUBJECT_SRC=${SUBJECT_SRC:-"$RUMPK_DIR/apps/subject_zig/main.zig"} zig build-obj \ -target $ZIG_TARGET \ $ZIG_OBJ_FLAGS \ -O ReleaseSmall \ "$SUBJECT_SRC" \ --name subject_zig mv subject_zig.o "$BUILD_DIR/subject_zig.o" # ========================================================= # Step 5.5: Patch Atomic References & Nuke Cache (GLOBAL) # ========================================================= # We must do this BEFORE creating archives or linking anything. # This ensures broken libcompiler_rt refs are removed from ALL objects. echo "[5.5/8] Patching Atomic References & Nuking Cache..." find "$BUILD_DIR" -name "*.o" | while read obj; do zig objcopy --redefine-syms="$RUMPK_DIR/core/re-symbol.txt" "$obj" "$obj" 2>/dev/null || true # Remove auto-linking sections zig objcopy \ --remove-section .linker-options \ --remove-section .comment \ --remove-section .deplibs \ --remove-section .llvm_addrsig \ --remove-section .dependent-lib \ "$obj" "$obj" 2>/dev/null || true done echo " → SWAPPING libcompiler_rt.a with dummy archive (GLOB)..." echo "" > "$BUILD_DIR/dummy.c" zig cc -target $ZIG_TARGET -c "$BUILD_DIR/dummy.c" -o "$BUILD_DIR/dummy.o" $ARCH_FLAGS for lib in "$BUILD_DIR"/.zig-cache/o/*/libcompiler_rt.a; do if [ -f "$lib" ]; then echo " Replacing $lib" rm -f "$lib" zig ar rc "$lib" "$BUILD_DIR/dummy.o" fi done # ========================================================= # Step 5b: Create Membrane Archive # ========================================================= # Note: We manually include ion_switch.o from the KERNEL nimcache if needed, # but it should be in membrane_nimcache too because libc.nim imports it. # Let's verify if ion_switch.o exists in membrane_nimcache. ION_SWITCH_OBJ=$(ls "$BUILD_DIR/membrane_nimcache"/*ion_switch*o 2>/dev/null || echo "") zig ar rc "$BUILD_DIR/libnexus.a" \ $MEMBRANE_NIM_OBJS \ $LWIP_MEMBRANE_OBJS \ "$BUILD_DIR/clib.o" \ "$BUILD_DIR/membrane_sys_arch.o" \ "$BUILD_DIR/switch.o" echo " → $BUILD_DIR/libnexus.a" # ========================================================= # Step 6: Link Subject Zero # ========================================================= echo "[6/8] Linking Subject Zero (Canary)..." # Note: subject_zero.o and libnexus.a are already compiled and patched. # ========================================================= # Step 6: Link Subject Zig # ========================================================= echo "[6/8] Linking Subject Zig..." zig cc \ -target $ZIG_TARGET \ -nostdlib \ -T "$RUMPK_DIR/apps/linker_user.ld" \ "$BUILD_DIR/subject_zig.o" \ "$BUILD_DIR/libnexus.a" \ -o "$BUILD_DIR/subject.elf" \ -lgcc echo " → $BUILD_DIR/subject.elf" zig objcopy -O binary "$BUILD_DIR/subject.elf" "$BUILD_DIR/subject.bin" echo " → $BUILD_DIR/subject.bin" # ========================================================= # Step 7: Compile Loader (After Subject) # ========================================================= echo "[7/8] Compiling Loader (with Embedded Subject)..." # Copy subject.bin to core/ so loader.zig can embed it (package path restriction) cp "$BUILD_DIR/subject.bin" "$RUMPK_DIR/core/subject.bin" zig build-obj \ -target $ZIG_TARGET \ $ZIG_OBJ_FLAGS \ -O ReleaseFast \ "$RUMPK_DIR/core/loader.zig" \ --name loader mv loader.o "$BUILD_DIR/loader.o" echo " → $BUILD_DIR/loader.o" # Clean up temp file rm "$RUMPK_DIR/core/subject.bin" # Patch Loader Object specifically echo " → Patching Loader Object..." obj="$BUILD_DIR/loader.o" zig objcopy --redefine-syms="$RUMPK_DIR/core/re-symbol.txt" "$obj" "$obj" 2>/dev/null || true zig objcopy \ --remove-section .linker-options \ --remove-section .comment \ --remove-section .deplibs \ --remove-section .llvm_addrsig \ --remove-section .dependent-lib \ "$obj" "$obj" 2>/dev/null || true # ========================================================= # Step 8: Link Kernel (Direct LLD Bypass) # ========================================================= echo "[8/8] Linking Kernel ($ARCH) using LLD..." # Check if ld.lld is available, otherwise assume zig cc wrapper but we try direct first LINKER="ld.lld" EMULATION="" if [ "$ARCH" = "riscv64" ]; then EMULATION="-m elf64lriscv" elif [ "$ARCH" = "x86_64" ]; then EMULATION="-m elf_x86_64" elif [ "$ARCH" = "aarch64" ]; then EMULATION="-m aarch64elf" fi $LINKER \ -t \ $EMULATION \ --gc-sections \ -T "$RUMPK_DIR/hal/arch/$ARCH/linker.ld" \ "$BUILD_DIR/hal.o" \ "$BUILD_DIR/stubs.o" \ "$BUILD_DIR/channel.o" \ "$BUILD_DIR/switch.o" \ "$BUILD_DIR/monocypher.o" \ "$BUILD_DIR/cstubs.o" \ "$BUILD_DIR/overrides.o" \ "$BUILD_DIR/loader.o" \ "$BUILD_DIR/nexshell.o" \ $NIM_OBJS \ -o "$BUILD_DIR/rumpk-$ARCH.elf" echo " → $BUILD_DIR/rumpk-$ARCH.elf" echo "" echo "✅ Build complete for $ARCH!" echo "Run with:" echo " qemu-system-riscv64 -M virt -nographic -kernel $BUILD_DIR/rumpk-riscv64.elf -netdev user,id=n0 -device virtio-net-pci,netdev=n0,disable-modern=on" echo ""