# CubeCactusOS Makefile
# Build system for custom MINIX3-based operating system
# Compiler and tools
# Detect OS and set appropriate tools
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
# macOS - check for cross-compiler (try multiple variants)
ifeq ($(shell which i386-elf-gcc 2>/dev/null),)
ifeq ($(shell which x86_64-elf-gcc 2>/dev/null),)
# No cross-compiler found
$(error Cross-compiler not found. Install with: brew tap nativeos/i386-elf-toolchain && brew install i386-elf-binutils i386-elf-gcc)
else
# Use x86_64-elf cross-compiler in 32-bit mode
CC = x86_64-elf-gcc
LD = x86_64-elf-ld
CFLAGS_ARCH = -m32
LDFLAGS_ARCH = -m elf_i386 -T $(BOOT_DIR)/linker.ld -nostdlib
USE_NATIVE = 0
endif
else
# Use i386-elf cross-compiler
CC = i386-elf-gcc
LD = i386-elf-ld
CFLAGS_ARCH = -m32
LDFLAGS_ARCH = -T $(BOOT_DIR)/linker.ld -nostdlib
USE_NATIVE = 0
endif
AS = nasm
ASFLAGS = -f elf32
else
# Linux
CC = gcc
AS = nasm
LD = ld
ASFLAGS = -f elf32
CFLAGS_ARCH = -m32
LDFLAGS_ARCH = -m elf_i386 -T $(BOOT_DIR)/linker.ld -nostdlib
USE_NATIVE = 0
endif
QEMU = qemu-system-i386
# Try different GRUB variants
ifeq ($(shell which grub-mkrescue 2>/dev/null),)
ifeq ($(shell which grub2-mkrescue 2>/dev/null),)
ifeq ($(shell which i686-elf-grub-mkrescue 2>/dev/null),)
GRUB_MKRESCUE =
else
GRUB_MKRESCUE = i686-elf-grub-mkrescue
endif
else
GRUB_MKRESCUE = grub2-mkrescue
endif
else
GRUB_MKRESCUE = grub-mkrescue
endif
# Compiler flags
CFLAGS = $(CFLAGS_ARCH) -ffreestanding -fno-builtin -fno-stack-protector -O2 -Wall -Wextra -I$(KERNEL_DIR)
ifeq ($(USE_NATIVE),1)
LDFLAGS = $(LDFLAGS_ARCH)
else
LDFLAGS = $(LDFLAGS_ARCH)
endif
# Directories
KERNEL_DIR = os/kernel
SERVER_DIR = os/servers
DRIVER_DIR = os/drivers
USERLAND_DIR = os/userland
LIB_DIR = os/lib
BOOT_DIR = os/boot
BUILD_DIR = os/build
ISO_DIR = $(BUILD_DIR)/isodir
# Source files
KERNEL_SRCS = $(wildcard $(KERNEL_DIR)/*.c)
SERVER_SRCS = $(wildcard $(SERVER_DIR)/*.c)
DRIVER_SRCS = $(wildcard $(DRIVER_DIR)/*.c)
LIB_SRCS = $(wildcard $(LIB_DIR)/*.c)
USERLAND_SRCS = $(wildcard $(USERLAND_DIR)/*.c)
BOOT_ASM = $(BOOT_DIR)/boot.S
# Object files
BOOT_OBJ = $(BUILD_DIR)/boot/boot.o
KERNEL_OBJS = $(patsubst $(KERNEL_DIR)/%.c,$(BUILD_DIR)/kernel/%.o,$(KERNEL_SRCS))
SERVER_OBJS = $(patsubst $(SERVER_DIR)/%.c,$(BUILD_DIR)/servers/%.o,$(SERVER_SRCS))
DRIVER_OBJS = $(patsubst $(DRIVER_DIR)/%.c,$(BUILD_DIR)/drivers/%.o,$(DRIVER_SRCS))
LIB_OBJS = $(patsubst $(LIB_DIR)/%.c,$(BUILD_DIR)/lib/%.o,$(LIB_SRCS))
USERLAND_OBJS = $(patsubst $(USERLAND_DIR)/%.c,$(BUILD_DIR)/userland/%.o,$(USERLAND_SRCS))
ALL_OBJS = $(BOOT_OBJ) $(LIB_OBJS) $(KERNEL_OBJS) $(SERVER_OBJS) $(DRIVER_OBJS) $(USERLAND_OBJS)
# Targets
KERNEL_BIN = $(BUILD_DIR)/cubecactusos.bin
ISO_FILE = $(BUILD_DIR)/cubecactusos.iso
.PHONY: all clean os-build os-image os-run help
all: help
# Help target
help:
@echo "CubeCactusOS Build System"
@echo ""
@echo "Targets:"
@echo " os-build - Build the OS kernel and components"
@echo " os-image - Create bootable ISO image"
@echo " os-run - Run OS in QEMU emulator"
@echo " os-clean - Clean build artifacts"
@echo " help - Show this help message"
@echo ""
@echo "Quick start:"
@echo " make os-build && make os-run"
# Build OS
os-build: $(BUILD_DIR) $(KERNEL_BIN)
@echo "✓ Build complete: $(KERNEL_BIN)"
# Create directories
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)/kernel
mkdir -p $(BUILD_DIR)/servers
mkdir -p $(BUILD_DIR)/drivers
mkdir -p $(BUILD_DIR)/lib
mkdir -p $(BUILD_DIR)/userland
mkdir -p $(BUILD_DIR)/boot
mkdir -p $(ISO_DIR)/boot/grub
# Assemble boot code
$(BOOT_OBJ): $(BOOT_ASM) | $(BUILD_DIR)
@echo "Assembling $<"
@if ! command -v $(AS) >/dev/null 2>&1; then \
echo "✗ NASM assembler not found."; \
echo ""; \
echo "Install NASM:"; \
echo " brew install nasm"; \
exit 1; \
fi
$(AS) $(ASFLAGS) $< -o $@
# Compile kernel
$(BUILD_DIR)/kernel/%.o: $(KERNEL_DIR)/%.c | $(BUILD_DIR)
@echo "Compiling $<"
$(CC) $(CFLAGS) -c $< -o $@
# Compile servers
$(BUILD_DIR)/servers/%.o: $(SERVER_DIR)/%.c | $(BUILD_DIR)
@echo "Compiling $<"
$(CC) $(CFLAGS) -c $< -o $@
# Compile drivers
$(BUILD_DIR)/drivers/%.o: $(DRIVER_DIR)/%.c | $(BUILD_DIR)
@echo "Compiling $<"
$(CC) $(CFLAGS) -c $< -o $@
# Compile library
$(BUILD_DIR)/lib/%.o: $(LIB_DIR)/%.c | $(BUILD_DIR)
@echo "Compiling $<"
$(CC) $(CFLAGS) -c $< -o $@
# Compile userland
$(BUILD_DIR)/userland/%.o: $(USERLAND_DIR)/%.c | $(BUILD_DIR)
@echo "Compiling $<"
$(CC) $(CFLAGS) -c $< -o $@
# Link kernel
$(KERNEL_BIN): $(ALL_OBJS)
@echo "Linking kernel..."
ifeq ($(USE_NATIVE),1)
@echo "⚠ Using native macOS linker (limited functionality)"
@echo "⚠ For full OS functionality, install cross-compiler:"
@echo " brew tap nativeos/i386-elf-toolchain"
@echo " brew install i386-elf-binutils i386-elf-gcc"
@echo ""
endif
$(LD) $(LDFLAGS) -o $@ $^
@echo "✓ Kernel linked successfully"
# Create ISO image
os-image: $(KERNEL_BIN)
@echo "Creating bootable ISO image..."
@mkdir -p $(ISO_DIR)/boot/grub
@cp $(KERNEL_BIN) $(ISO_DIR)/boot/cubecactusos.bin
@cp $(BOOT_DIR)/grub.cfg $(ISO_DIR)/boot/grub/grub.cfg
@if [ -z "$(GRUB_MKRESCUE)" ]; then \
echo "✗ GRUB not found. Install with:"; \
echo " brew install i686-elf-grub xorriso"; \
exit 1; \
fi
@echo "Using $(GRUB_MKRESCUE) to create ISO..."
@$(GRUB_MKRESCUE) -o $(ISO_FILE) $(ISO_DIR) 2>&1 | grep -v "warning:" || true
@if [ -f $(ISO_FILE) ]; then \
echo "✓ ISO created: $(ISO_FILE)"; \
ls -lh $(ISO_FILE); \
else \
echo "✗ ISO creation failed"; \
exit 1; \
fi
# Run in QEMU
os-run: os-image
@if [ ! -f $(ISO_FILE) ]; then \
echo "✗ ISO file not found. Run 'make os-image' first."; \
exit 1; \
fi
@if ! command -v $(QEMU) >/dev/null 2>&1; then \
echo "✗ QEMU not found. Install it:"; \
echo " macOS: brew install qemu"; \
echo " Linux: sudo apt-get install qemu-system-x86"; \
exit 1; \
fi
@echo "Starting CubeCactusOS in QEMU..."
$(QEMU) -cdrom $(ISO_FILE) -m 512M -serial stdio
# Clean build artifacts
os-clean:
rm -rf $(BUILD_DIR)
@echo "Build directory cleaned"
# Clean everything including OS build
clean: os-clean
rm -rf build/
@echo "All build artifacts cleaned"