# opencoreC - Root Unified Makefile # Target Architecture: x86_64 Long Mode (Microkernel OS) SHELL := /usr/bin/env bash # Toolchain definitions CC := gcc CXX := g++ LD := ld CARGO := cargo QEMU := qemu-system-x86_64 # Directory layout BUILD_DIR := build CONFIG_DIR := config INCLUDE_DIR := include LIB_DIR := lib HAL_DIR := hal SERVERS_DIR := servers KERNEL_DIR := kernel LIMINE_DIR := boot/limine # Common Freestanding Flags COMMON_FLAGS := -Wall -Wextra -O2 -ffreestanding -fno-stack-protector \ -fno-pie -no-pie -mno-red-zone -m64 \ -mno-sse -mno-sse2 -mno-avx \ -I$(INCLUDE_DIR) -I$(LIB_DIR)/libc/include -I$(HAL_DIR)/include CFLAGS := $(COMMON_FLAGS) -std=c11 CXXFLAGS := $(COMMON_FLAGS) -std=c++20 -fno-exceptions -fno-rtti -I$(LIB_DIR)/libipc_cpp/include # Outputs KERNEL_BIN := target/x86_64-unknown-none/release/opencore_kernel KERNEL_ELF := $(BUILD_DIR)/opencore_kernel.elf INIT_SERVER := $(BUILD_DIR)/init_server.elf UART_DRIVER := $(BUILD_DIR)/uart_driver.elf VFS_SERVER := $(BUILD_DIR)/vfs_server.elf NET_SERVER := $(BUILD_DIR)/net_server.elf SH_SERVER := $(BUILD_DIR)/sh.elf PROCMGR := $(BUILD_DIR)/procmgr.elf HELLO_APP := $(BUILD_DIR)/hello.opc OGIT_APP := $(BUILD_DIR)/ogit.opc DISK_IMG := $(BUILD_DIR)/opencoreC.img LIBC_OBJS := $(BUILD_DIR)/string.o $(BUILD_DIR)/syscalls.o $(BUILD_DIR)/stdlib.o NET_OBJS := $(BUILD_DIR)/net.o $(BUILD_DIR)/rtl8139.o $(BUILD_DIR)/e1000.o $(BUILD_DIR)/r8169.o $(BUILD_DIR)/pci.o STORAGE_OBJS := $(BUILD_DIR)/ahci.o $(BUILD_DIR)/fat32.o $(BUILD_DIR)/pci.o .PHONY: all kernel libc hal servers image run qemu clean help limine-setup all: kernel libc hal servers @mkdir -p $(BUILD_DIR) @cp $(KERNEL_BIN) $(KERNEL_ELF) @echo "=======================================================" @echo " [SUCCESS] opencoreC Build Complete!" @echo " Kernel: $(KERNEL_ELF)" @echo " Servers: $(INIT_SERVER), $(UART_DRIVER), $(VFS_SERVER), $(NET_SERVER), $(PROCMGR), $(SH_SERVER)" @echo " Run: make run (Interactive Shell Terminal)" @echo "=======================================================" kernel: @echo "[CARGO] Compiling Rust Microkernel (x86_64-unknown-none)..." @RUSTFLAGS="-C link-arg=-T$(CONFIG_DIR)/linker.ld -C code-model=kernel -C relocation-model=static" \ $(CARGO) build --package opencore_kernel --target x86_64-unknown-none --release libc: @mkdir -p $(BUILD_DIR) @echo "[CC] Compiling bare-metal freestanding libc..." @$(CC) $(CFLAGS) -c $(LIB_DIR)/libc/src/string.c -o $(BUILD_DIR)/string.o @$(CC) $(CFLAGS) -c $(LIB_DIR)/libc/src/syscalls.c -o $(BUILD_DIR)/syscalls.o @$(CC) $(CFLAGS) -c $(LIB_DIR)/libc/src/stdlib.c -o $(BUILD_DIR)/stdlib.o @$(CC) $(CFLAGS) -I$(HAL_DIR)/include -c $(LIB_DIR)/libc/src/net.c -o $(BUILD_DIR)/net.o hal: libc @mkdir -p $(BUILD_DIR) @echo "[CC] Compiling HAL and Hardware Drivers..." @$(CC) $(CFLAGS) -I$(HAL_DIR)/include -c $(HAL_DIR)/src/uart.c -o $(BUILD_DIR)/uart.o @$(CC) $(CFLAGS) -I$(HAL_DIR)/include -c $(HAL_DIR)/src/pci.c -o $(BUILD_DIR)/pci.o @$(CC) $(CFLAGS) -I$(HAL_DIR)/include -c $(HAL_DIR)/src/apic.c -o $(BUILD_DIR)/apic.o @$(CC) $(CFLAGS) -I$(HAL_DIR)/include -c $(HAL_DIR)/src/fb.c -o $(BUILD_DIR)/fb.o @$(CC) $(CFLAGS) -I$(HAL_DIR)/include -c $(HAL_DIR)/src/rtl8139.c -o $(BUILD_DIR)/rtl8139.o @$(CC) $(CFLAGS) -I$(HAL_DIR)/include -c $(HAL_DIR)/src/e1000.c -o $(BUILD_DIR)/e1000.o @$(CC) $(CFLAGS) -I$(HAL_DIR)/include -c $(HAL_DIR)/src/r8169.c -o $(BUILD_DIR)/r8169.o @$(CC) $(CFLAGS) -I$(HAL_DIR)/include -c $(HAL_DIR)/src/ahci.c -o $(BUILD_DIR)/ahci.o @$(CC) $(CFLAGS) -I$(HAL_DIR)/include -c $(HAL_DIR)/src/fat32.c -o $(BUILD_DIR)/fat32.o servers: libc hal @mkdir -p $(BUILD_DIR) @echo "[CXX/CC] Linking Ring 3 User-space Servers..." @# C++ LibIPC @$(CXX) $(CXXFLAGS) -c $(LIB_DIR)/libipc_cpp/src/ipc.cpp -o $(BUILD_DIR)/ipc.o @# Init Root Server @$(CXX) $(CXXFLAGS) -c $(SERVERS_DIR)/init/main.cpp -o $(BUILD_DIR)/init_main.o @$(LD) -T $(CONFIG_DIR)/user.ld -nostdlib -static -o $(INIT_SERVER) \ $(BUILD_DIR)/init_main.o $(BUILD_DIR)/ipc.o $(LIBC_OBJS) @# Standalone UART Driver Server @$(CC) $(CFLAGS) -I$(HAL_DIR)/include -c $(SERVERS_DIR)/uart_driver/main.c -o $(BUILD_DIR)/uart_driver_main.o @$(LD) -T $(CONFIG_DIR)/user.ld -nostdlib -static -o $(UART_DRIVER) \ $(BUILD_DIR)/uart_driver_main.o $(BUILD_DIR)/uart.o $(LIBC_OBJS) @# Standalone Virtual File System Server (with AHCI SATA & FAT32) @$(CXX) $(CXXFLAGS) -I$(HAL_DIR)/include -c $(SERVERS_DIR)/vfs_server/main.cpp -o $(BUILD_DIR)/vfs_server_main.o @$(LD) -T $(CONFIG_DIR)/user.ld -nostdlib -static -o $(VFS_SERVER) \ $(BUILD_DIR)/vfs_server_main.o $(BUILD_DIR)/ipc.o $(STORAGE_OBJS) $(LIBC_OBJS) @# Standalone Network Stack Server (with Gigabit e1000 & r8169) @$(CXX) $(CXXFLAGS) -I$(HAL_DIR)/include -c $(SERVERS_DIR)/net_server/main.cpp -o $(BUILD_DIR)/net_server_main.o @$(LD) -T $(CONFIG_DIR)/user.ld -nostdlib -static -o $(NET_SERVER) \ $(BUILD_DIR)/net_server_main.o $(BUILD_DIR)/ipc.o $(NET_OBJS) $(LIBC_OBJS) @# Interactive Shell with Networking & Framebuffer @$(CXX) $(CXXFLAGS) -I$(HAL_DIR)/include -c $(SERVERS_DIR)/sh/main.cpp -o $(BUILD_DIR)/sh_main.o @$(LD) -T $(CONFIG_DIR)/user.ld -nostdlib -static -o $(SH_SERVER) \ $(BUILD_DIR)/sh_main.o $(BUILD_DIR)/ipc.o $(BUILD_DIR)/fb.o $(NET_OBJS) $(LIBC_OBJS) @# Process Manager Daemon @$(CXX) $(CXXFLAGS) -c $(SERVERS_DIR)/procmgr/main.cpp -o $(BUILD_DIR)/procmgr_main.o @$(LD) -T $(CONFIG_DIR)/user.ld -nostdlib -static -o $(PROCMGR) \ $(BUILD_DIR)/procmgr_main.o $(BUILD_DIR)/ipc.o $(LIBC_OBJS) @# Native .opc Executable Application (hello.opc) @$(CC) $(CFLAGS) -c apps/hello.c -o $(BUILD_DIR)/hello.o @$(LD) -T $(CONFIG_DIR)/user.ld -nostdlib -static -o $(BUILD_DIR)/hello.elf \ $(BUILD_DIR)/hello.o $(LIBC_OBJS) @python3 tools/elf2opc.py $(BUILD_DIR)/hello.elf $(HELLO_APP) @# Native .opc OpenCore Git Application (ogit.opc) @$(CC) $(CFLAGS) -c apps/ogit.c -o $(BUILD_DIR)/ogit.o @$(LD) -T $(CONFIG_DIR)/user.ld -nostdlib -static -o $(BUILD_DIR)/ogit.elf \ $(BUILD_DIR)/ogit.o $(LIBC_OBJS) @python3 tools/elf2opc.py $(BUILD_DIR)/ogit.elf $(OGIT_APP) # Download and build the Limine bootloader host tool limine-setup: @if [ ! -d "$(LIMINE_DIR)" ]; then \ echo "[LIMINE] Cloning Limine v8 binary branch..."; \ git clone https://github.com/limine-bootloader/limine.git --branch=v8.x-binary --depth=1 $(LIMINE_DIR); \ fi @echo "[LIMINE] Building host installer tool..." @$(MAKE) -C $(LIMINE_DIR) limine # Build a 64 MiB bootable FAT32 disk image with Limine BIOS/UEFI image: all limine-setup @echo "[IMAGE] Creating bootable disk image (64 MiB FAT32)..." @dd if=/dev/zero of=$(DISK_IMG) bs=1M count=64 2>/dev/null @parted -s $(DISK_IMG) mklabel msdos mkpart primary fat32 2048s 100% set 1 boot on 2>/dev/null @mformat -F -i $(DISK_IMG)@@1M :: @mmd -i $(DISK_IMG)@@1M ::/boot ::/EFI ::/EFI/BOOT @# Kernel and userspace servers @mcopy -i $(DISK_IMG)@@1M $(KERNEL_ELF) ::/boot/ @mcopy -i $(DISK_IMG)@@1M $(INIT_SERVER) ::/boot/ @mcopy -i $(DISK_IMG)@@1M $(UART_DRIVER) ::/boot/ @mcopy -i $(DISK_IMG)@@1M $(VFS_SERVER) ::/boot/ @mcopy -i $(DISK_IMG)@@1M $(NET_SERVER) ::/boot/ @mcopy -i $(DISK_IMG)@@1M $(PROCMGR) ::/boot/ @mcopy -i $(DISK_IMG)@@1M $(SH_SERVER) ::/boot/ @mcopy -i $(DISK_IMG)@@1M $(HELLO_APP) ::/boot/ @mcopy -i $(DISK_IMG)@@1M $(OGIT_APP) ::/boot/ @# Bootloader config @mcopy -i $(DISK_IMG)@@1M limine.conf ::/ @mcopy -i $(DISK_IMG)@@1M limine.cfg ::/ @mcopy -i $(DISK_IMG)@@1M limine.conf ::/boot/ @mcopy -i $(DISK_IMG)@@1M limine.cfg ::/boot/ @# Limine bootloader files @mcopy -i $(DISK_IMG)@@1M $(LIMINE_DIR)/limine-bios.sys ::/ @mcopy -i $(DISK_IMG)@@1M $(LIMINE_DIR)/limine-bios.sys ::/boot/ @mcopy -i $(DISK_IMG)@@1M $(LIMINE_DIR)/BOOTX64.EFI ::/EFI/BOOT/ @# Install Limine Stage 1 into MBR @$(LIMINE_DIR)/limine bios-install $(DISK_IMG) 2>&1 | grep -v "^Physical\|^Installing\|^Stage\|^Reminder" @echo "[IMAGE] Done: $(DISK_IMG) (BIOS + UEFI bootable)" # Launch QEMU with serial terminal (Interactive CLI mode) run: image @echo "[QEMU] Launching opencoreC (SMP 4 cores, Serial terminal, Framebuffer, RTL8139 Net)..." @echo "[QEMU] Type 'help' for commands. Ctrl+A X to exit QEMU." @echo "-------------------------------------------------------" @$(QEMU) \ -M q35 \ -smp 4 \ -m 512M \ -vga std \ -netdev user,id=net0 \ -device rtl8139,netdev=net0 \ -serial mon:stdio \ -no-reboot \ -display none \ -drive file=$(DISK_IMG),format=raw # Launch QEMU with Native Host CPU via KVM Hardware Acceleration run-kvm: image @echo "[QEMU] Launching with Native Host CPU & KVM Hardware Acceleration..." @echo "[QEMU] Type 'help' for commands. Ctrl+A X to exit QEMU." @echo "-------------------------------------------------------" @$(QEMU) \ -enable-kvm \ -cpu host \ -M q35 \ -smp 4 \ -m 512M \ -vga std \ -netdev user,id=net0 \ -device e1000,netdev=net0 \ -serial mon:stdio \ -no-reboot \ -display none \ -drive file=$(DISK_IMG),format=raw # Run without rebuilding image (faster iteration) qemu: $(DISK_IMG) @echo "[QEMU] Quick launch from existing image..." @echo "[QEMU] Type 'help'. Ctrl+A X to exit." @$(QEMU) -M q35 -smp 4 -m 512M -vga std -netdev user,id=net0 -device rtl8139,netdev=net0 \ -serial mon:stdio -no-reboot -display none \ -drive file=$(DISK_IMG),format=raw clean: @echo "[CLEAN] Removing build directory and cargo target..." @rm -rf $(BUILD_DIR) target help: @echo "opencoreC Microkernel Build System" @echo "" @echo "Targets:" @echo " make all - Build kernel, HAL, libc, and all user servers" @echo " make image - Create bootable disk image (build/opencoreC.img)" @echo " make gui - Launch QEMU with Desktop GUI Window (LVGL, Framebuffer, Mouse)" @echo " make run - Build image and launch in QEMU (interactive serial CLI)" @echo " make qemu - Quick relaunch without rebuild (CLI)" @echo " make limine-setup - Download/build Limine bootloader" @echo " make clean - Remove all build artifacts" @echo "" @echo "QEMU Controls:" @echo " Type commands in the terminal (serial I/O)" @echo " Ctrl+A then X -> exit QEMU" @echo " Ctrl+A then C -> QEMU monitor"