# 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
ISO_DIR     := $(BUILD_DIR)/iso_root

# Common Freestanding Flags
COMMON_FLAGS := -Wall -Wextra -O2 -ffreestanding -fno-stack-protector \
                -fno-pie -no-pie -mno-red-zone -m64 \
                -I$(INCLUDE_DIR) -I$(LIB_DIR)/libc/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
PROCMGR      := $(BUILD_DIR)/procmgr.elf

.PHONY: all kernel libc hal servers iso run clean help

all: kernel libc hal servers
	@mkdir -p $(BUILD_DIR)
	@cp $(KERNEL_BIN) $(KERNEL_ELF)
	@echo "======================================================="
	@echo " [SUCCESS] opencoreC Skeleton Build Complete!"
	@echo " Kernel:   $(KERNEL_ELF)"
	@echo " Servers:  $(INIT_SERVER), $(UART_DRIVER), $(PROCMGR)"
	@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

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

servers: libc hal
	@mkdir -p $(BUILD_DIR)
	@echo "[CXX/CC] Linking Ring 3 User-space Servers..."
	@# 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)/syscalls.o $(BUILD_DIR)/string.o
	@# 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 $(BUILD_DIR)/syscalls.o $(BUILD_DIR)/string.o
	@# 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)/syscalls.o $(BUILD_DIR)/string.o

# Staging Limine Boot ISO directory
iso: all
	@mkdir -p $(ISO_DIR)/boot $(ISO_DIR)/EFI/BOOT
	@cp $(KERNEL_ELF) $(ISO_DIR)/boot/
	@cp $(INIT_SERVER) $(ISO_DIR)/boot/
	@cp $(UART_DRIVER) $(ISO_DIR)/boot/
	@cp limine.conf $(ISO_DIR)/boot/limine.conf
	@cp limine.cfg $(ISO_DIR)/boot/limine.cfg
	@echo "[ISO] Staged boot files in $(ISO_DIR)/"

run: all
	@echo "[QEMU] Launching opencoreC in QEMU (Serial Output to Terminal)..."
	@$(QEMU) -M q35 -m 512M \
		-serial stdio \
		-display none \
		-no-reboot \
		-no-shutdown \
		-kernel $(KERNEL_ELF)

clean:
	@echo "[CLEAN] Removing build directory and cargo target..."
	@rm -rf $(BUILD_DIR) target

help:
	@echo "opencoreC Microkernel Build System"
	@echo "Targets:"
	@echo "  make all      - Build kernel, HAL, libc, and user servers"
	@echo "  make kernel   - Build Rust microkernel only"
	@echo "  make hal      - Build freestanding HAL drivers"
	@echo "  make servers  - Build Ring 3 C++ servers"
	@echo "  make iso      - Stage ISO root boot directory"
	@echo "  make run      - Launch QEMU with serial stdio"
	@echo "  make clean    - Clean build artifacts"
