#!/bin/sh # Build all user-mode applications as flat binaries. # Usage: build_apps.sh # Each app directory in / gets compiled and its flat binary # is placed in /. set -e APPS_DIR="$1" OUTPUT_DIR="$2" LINKER_SCRIPT="$APPS_DIR/user.ld" CC="${CC:-clang}" OBJCOPY="${OBJCOPY:-objcopy}" CFLAGS="-ffreestanding -m32 -fno-pie -fno-pic -fno-builtin -fno-stack-protector -mno-sse -mno-mmx -O2 -Wall -I$APPS_DIR/libc" LDFLAGS="-m32 -nostdlib -no-pie -Wl,--no-dynamic-linker" mkdir -p "$OUTPUT_DIR" # Build crt0 if it exists CRT0_OBJ="" if [ -f "$APPS_DIR/libc/crt0.S" ]; then CRT0_OBJ="$OUTPUT_DIR/_crt0.o" $CC $CFLAGS -c "$APPS_DIR/libc/crt0.S" -o "$CRT0_OBJ" fi for app_dir in "$APPS_DIR"/*/; do [ -d "$app_dir" ] || continue app_name=$(basename "$app_dir") # Skip the libc directory (shared library, not an app) [ "$app_name" = "libc" ] && continue echo "Building app: $app_name" # Collect source files OBJ_FILES="" for src in "$app_dir"*.S "$app_dir"*.c; do [ -f "$src" ] || continue obj="$OUTPUT_DIR/${app_name}_$(basename "${src%.*}").o" $CC $CFLAGS -c "$src" -o "$obj" OBJ_FILES="$OBJ_FILES $obj" done if [ -z "$OBJ_FILES" ]; then echo " No sources found, skipping" continue fi # Link into ELF (include crt0 if app has .c files and doesn't have its own _start) elf="$OUTPUT_DIR/$app_name.elf" HAS_C_FILES="" for src in "$app_dir"*.c; do [ -f "$src" ] && HAS_C_FILES="yes" done if [ -n "$HAS_C_FILES" ] && [ -n "$CRT0_OBJ" ]; then $CC $LDFLAGS -T "$LINKER_SCRIPT" "$CRT0_OBJ" $OBJ_FILES -o "$elf" else $CC $LDFLAGS -T "$LINKER_SCRIPT" $OBJ_FILES -o "$elf" fi # Convert to flat binary (include .bss for zero-initialized data) bin="$OUTPUT_DIR/$app_name" $OBJCOPY -O binary --only-section=.text --only-section=.rodata --only-section=.data --only-section=.bss "$elf" "$bin" size=$(wc -c < "$bin") echo " Built: $bin ($size bytes)" done