mirror of
https://github.com/subhobhai943/SUB-OS.git
synced 2026-10-25 16:52:29 +00:00
A new desktop app whose whole point is to say sorry, and to look like
saying it took effort. Nothing in it is a static bitmap.
The heart is the classic parametric heart curve, x = 16sin^3(t) and
y = 13cos(t) - 5cos(2t) - 2cos(3t) - cos(4t), precomputed as a 96-point
integer polygon normalised to a half-width of 1000 and scanline-filled at
whatever size the beat currently has it at. Even-odd crossing counting is
what keeps the notch between the lobes open. The beat is a two-thump
cardiac envelope -- a strong systolic beat and a softer echo -- and the
fill carries a vertical gradient, a soft specular highlight on the upper
lobe, and a six-layer glow. The kernel is built -mno-sse with no floating
point, so every curve, gradient, easing and physics step is integer-only
and needs no trigonometry at runtime.
Around it: three apology letters that type themselves out a character at
a time, and a slow drift of small hearts using the same fill routine.
Answering "I forgive you" brightens the heart and bursts the drift
outward; answering "Not yet" dims it, slows the beat, and starts an
honest count of how long it has been waiting. Neither answer is an exit.
Supporting changes, all of them general rather than app-specific:
- gui_desktop_request_animation_frame(), so an app can opt into
full-rate recompositing instead of the ~10 Hz live-content
heartbeat. It is renewed per paint, so it lapses by itself when the
app stops animating or its window closes.
- gui_button_styled() and gui_hitzone() in SUB-WT, letting an app with
its own palette keep the toolkit's click handling. gui_button_colored
is now a thin wrapper over the former.
- A heart glyph in the icon set.
The glow layers skip whatever the heart body is about to cover, which
cuts their blended-pixel cost by roughly 3.5x and pays for the extra
layers that turn contour rings into a smooth halo.
Verified in QEMU on x86_64: all three states driven by real clicks --
hover, forgiveness (brighter heart, burst, live typewriter) and waiting
(dimmed heart, slower beat, running counter). Builds clean on x86_64,
aarch64 and armv8i.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Fh5z6V7nGPbHvqVG5p4CXX
542 lines
21 KiB
Makefile
542 lines
21 KiB
Makefile
# =============================================================================
|
|
# SUB-OS Master Multi-Architecture Linux-Style Makefile
|
|
# Supports: x86_64, aarch64, armv8i
|
|
# Features: Linux Kconfig TUI (make configure / make menuconfig), dynamic Kbuild
|
|
# =============================================================================
|
|
|
|
-include .config
|
|
|
|
# Architecture Selection (Default: x86_64)
|
|
ifdef CONFIG_ARCH
|
|
ARCH ?= $(CONFIG_ARCH)
|
|
else
|
|
ARCH ?= x86_64
|
|
endif
|
|
|
|
BUILD_DIR = build
|
|
BOOT_DIR = boot
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Toolchain & Architecture Flags
|
|
# -----------------------------------------------------------------------------
|
|
ifeq ($(ARCH), x86_64)
|
|
CROSS_COMPILE ?= x86_64-elf-
|
|
CC = $(CROSS_COMPILE)gcc
|
|
LD = $(CROSS_COMPILE)ld
|
|
OBJCOPY = $(CROSS_COMPILE)objcopy
|
|
ASM = nasm
|
|
|
|
CFLAGS = -ffreestanding \
|
|
-fno-pie \
|
|
-fno-pic \
|
|
-mno-red-zone \
|
|
-mno-mmx \
|
|
-mno-sse \
|
|
-mno-sse2 \
|
|
-mcmodel=kernel \
|
|
-Wall \
|
|
-Wextra \
|
|
-Wno-unused-function \
|
|
-Wno-unused-parameter \
|
|
$(if $(CONFIG_OPTIMIZATION),$(CONFIG_OPTIMIZATION),-O2) \
|
|
-Iinclude \
|
|
-D__x86_64__
|
|
|
|
ASMFLAGS_ELF = -f elf64
|
|
ASMFLAGS_BOOT = -f bin -I$(BOOT_DIR)/
|
|
LDFLAGS = -nostdlib -no-pie -T linker.ld
|
|
|
|
ARCH_C_SRCS = $(shell find arch/x86_64 -name '*.c' 2>/dev/null)
|
|
ARCH_ASM_SRCS = $(shell find arch/x86_64 -name '*.asm' 2>/dev/null)
|
|
ENTRY_OBJ = $(BUILD_DIR)/arch/x86_64/boot/entry.o
|
|
IMAGE = SUB-OS.img
|
|
TARGET = $(IMAGE)
|
|
QEMU_CMD = qemu-system-x86_64 -drive format=raw,file=$(IMAGE) \
|
|
-netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \
|
|
-device e1000,netdev=net0 -serial stdio -display none
|
|
|
|
else ifneq ($(filter $(ARCH), aarch64 arm64),)
|
|
CROSS_COMPILE ?= aarch64-linux-gnu-
|
|
CC = $(CROSS_COMPILE)gcc
|
|
LD = $(CROSS_COMPILE)ld
|
|
OBJCOPY = $(CROSS_COMPILE)objcopy
|
|
AS = $(CROSS_COMPILE)as
|
|
|
|
CFLAGS = -ffreestanding \
|
|
-fno-pie \
|
|
-fno-pic \
|
|
-Wall \
|
|
-Wextra \
|
|
-Wno-unused-function \
|
|
-Wno-unused-parameter \
|
|
-mno-outline-atomics \
|
|
$(if $(CONFIG_OPTIMIZATION),$(CONFIG_OPTIMIZATION),-O2) \
|
|
-Iinclude \
|
|
-D__aarch64__ \
|
|
-march=armv8-a
|
|
|
|
LDFLAGS = -nostdlib -no-pie -T arch/aarch64/linker.ld
|
|
|
|
ARCH_C_SRCS = $(shell find arch/aarch64 -name '*.c' 2>/dev/null)
|
|
ARCH_S_SRCS = $(shell find arch/aarch64 -name '*.S' 2>/dev/null)
|
|
ENTRY_OBJ = $(BUILD_DIR)/arch/aarch64/boot/entry.o
|
|
TARGET = $(BUILD_DIR)/kernel.elf
|
|
QEMU_CMD = qemu-system-aarch64 -M virt -cpu cortex-a57 -m 128M -nographic -kernel $(BUILD_DIR)/kernel.elf
|
|
|
|
else ifneq ($(filter $(ARCH), armv8i armv81 arm32 arm armv7 armv7-a armv7a aarch32),)
|
|
CROSS_COMPILE ?= arm-linux-gnueabihf-
|
|
CC = $(CROSS_COMPILE)gcc
|
|
LD = $(CROSS_COMPILE)ld
|
|
OBJCOPY = $(CROSS_COMPILE)objcopy
|
|
AS = $(CROSS_COMPILE)as
|
|
|
|
CFLAGS = -ffreestanding \
|
|
-fno-pie \
|
|
-fno-pic \
|
|
-Wall \
|
|
-Wextra \
|
|
-Wno-unused-function \
|
|
-Wno-unused-parameter \
|
|
$(if $(CONFIG_OPTIMIZATION),$(CONFIG_OPTIMIZATION),-O2) \
|
|
-Iinclude \
|
|
-D__arm__ \
|
|
-D__armv8i__ \
|
|
-mcpu=cortex-a15 \
|
|
-mfpu=neon-vfpv4 \
|
|
-mfloat-abi=hard \
|
|
-marm
|
|
|
|
LDFLAGS = -nostdlib -no-pie -T arch/armv8i/linker.ld
|
|
|
|
ARCH_C_SRCS = $(shell find arch/armv8i -name '*.c' 2>/dev/null)
|
|
ARCH_S_SRCS = $(shell find arch/armv8i -name '*.S' 2>/dev/null)
|
|
ENTRY_OBJ = $(BUILD_DIR)/arch/armv8i/boot/entry.o
|
|
TARGET = $(BUILD_DIR)/kernel.elf
|
|
QEMU_CMD = qemu-system-arm -M virt -cpu cortex-a15 -m 128M -nographic -kernel $(BUILD_DIR)/kernel.elf
|
|
|
|
else
|
|
$(error Unsupported Architecture '$(ARCH)'. Supported: x86_64, aarch64, armv8i)
|
|
endif
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Linux-Style Configurable Kernel Subsystems (Kbuild-Style)
|
|
# -----------------------------------------------------------------------------
|
|
CORE_SRCS = kernel/main.c kernel/task.c kernel/sync.c kernel/timer.c kernel/printk.c \
|
|
kernel/panic.c kernel/trace.c kernel/sched.c kernel/cron.c kernel/syscall.c \
|
|
kernel/syslog.c kernel/module.c kernel/kobject.c kernel/metrics.c kernel/namespace.c \
|
|
kernel/signal.c kernel/workqueue.c kernel/tsc.c kernel/vt_art.c \
|
|
kernel/sub/sub_runtime.c kernel/sub/sub_vm.c kernel/nt/ob.c kernel/nt/reg.c kernel/nt/io.c \
|
|
kernel/wait.c kernel/futex.c kernel/rcu.c kernel/ktest.c kernel/time/ktime.c \
|
|
kernel/elf.c kernel/exec.c \
|
|
lib/string.c lib/vsprintf.c lib/bitmap.c lib/rbtree.c lib/kfifo.c lib/hashtable.c lib/font8x8.c \
|
|
init/cmdline.c init/service.c init/bootlogo.c init/logo_data.c usr/initramfs.c block/block.c block/elevator.c \
|
|
ipc/sem.c ipc/shm.c ipc/shm_posix.c ipc/pipe.c ipc/ipc.c ipc/msg.c \
|
|
crypto/sha256.c crypto/md5.c crypto/crc32.c crypto/prng.c sound/beep.c
|
|
|
|
# If no .config exists, default all core options to y
|
|
ifeq ($(wildcard .config),)
|
|
CONFIG_MM_PMM = y
|
|
CONFIG_MM_SLAB = y
|
|
CONFIG_MM_VMA = y
|
|
CONFIG_FS_VFS = y
|
|
CONFIG_FS_FAT32 = y
|
|
CONFIG_FS_EXT2 = y
|
|
CONFIG_FS_SYSFS = y
|
|
CONFIG_DRV_RAMDISK = y
|
|
CONFIG_DRV_AHCI = y
|
|
CONFIG_DRV_NVME = y
|
|
CONFIG_DRV_ATA = y
|
|
CONFIG_DRV_VIRTIO_BLK = y
|
|
CONFIG_NET_STACK = y
|
|
CONFIG_NET_FILTER = y
|
|
CONFIG_NET_HTTPD = y
|
|
CONFIG_NET_SSHD = y
|
|
CONFIG_DRV_E1000 = y
|
|
CONFIG_DRV_RTL8139 = y
|
|
CONFIG_DRV_VIRTIO_NET = y
|
|
CONFIG_DRV_PTY = y
|
|
CONFIG_DRV_VIRTIO_RNG = y
|
|
CONFIG_DRV_CANVAS_2D = y
|
|
CONFIG_DRV_BOCHS_VBE = y
|
|
CONFIG_DRV_SOUND_HDA = y
|
|
CONFIG_DRV_SOUND_AC97 = y
|
|
CONFIG_DRV_USB_XHCI = y
|
|
CONFIG_DRV_HWMON = y
|
|
CONFIG_SECURITY_LSM = y
|
|
CONFIG_SECURITY_KEYRING = y
|
|
CONFIG_BPF_VM = y
|
|
CONFIG_IO_URING = y
|
|
CONFIG_USERLAND_LAZYBOX = y
|
|
endif
|
|
|
|
CONFIG_SRCS-y := $(CORE_SRCS)
|
|
|
|
ifeq ($(CONFIG_MM_PMM), y)
|
|
CONFIG_SRCS-y += mm/pmm.c mm/kmalloc.c mm/page_cache.c
|
|
endif
|
|
ifeq ($(CONFIG_MM_SLAB), y)
|
|
CONFIG_SRCS-y += mm/slab.c
|
|
endif
|
|
ifeq ($(CONFIG_MM_VMA), y)
|
|
CONFIG_SRCS-y += mm/vma.c
|
|
endif
|
|
|
|
ifeq ($(CONFIG_BPF_VM), y)
|
|
CONFIG_SRCS-y += kernel/bpf.c
|
|
endif
|
|
ifeq ($(CONFIG_IO_URING), y)
|
|
CONFIG_SRCS-y += io_uring/io_uring.c
|
|
endif
|
|
ifeq ($(CONFIG_SECURITY_LSM), y)
|
|
CONFIG_SRCS-y += security/lsm.c security/auth.c
|
|
endif
|
|
ifeq ($(CONFIG_SECURITY_KEYRING), y)
|
|
CONFIG_SRCS-y += certs/x509.c
|
|
endif
|
|
|
|
# Filesystems
|
|
ifeq ($(CONFIG_FS_VFS), y)
|
|
CONFIG_SRCS-y += fs/vfs.c fs/ramfs.c fs/devfs.c fs/procfs.c
|
|
endif
|
|
ifeq ($(CONFIG_FS_FAT32), y)
|
|
CONFIG_SRCS-y += fs/fat32.c
|
|
endif
|
|
ifeq ($(CONFIG_FS_EXT2), y)
|
|
CONFIG_SRCS-y += fs/ext2.c
|
|
endif
|
|
ifeq ($(CONFIG_FS_SYSFS), y)
|
|
CONFIG_SRCS-y += fs/sysfs.c
|
|
endif
|
|
|
|
# Storage Drivers
|
|
ifeq ($(CONFIG_DRV_RAMDISK), y)
|
|
CONFIG_SRCS-y += drivers/block/ramdisk.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_AHCI), y)
|
|
CONFIG_SRCS-y += drivers/block/ahci.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_NVME), y)
|
|
CONFIG_SRCS-y += drivers/block/nvme.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_ATA), y)
|
|
CONFIG_SRCS-y += drivers/block/ata.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_VIRTIO_BLK), y)
|
|
CONFIG_SRCS-y += drivers/virtio/virtio_blk.c virt/virtio.c virt/hypervisor.c
|
|
endif
|
|
|
|
# Network Subsystem
|
|
ifeq ($(CONFIG_NET_STACK), y)
|
|
CONFIG_SRCS-y += net/core/net.c net/core/socket.c net/ipv4/tcp.c net/ipv4/udp.c net/ipv4/dhcp.c net/ipv4/dns.c net/ipv4/dns_cache.c
|
|
endif
|
|
ifeq ($(CONFIG_NET_FILTER), y)
|
|
CONFIG_SRCS-y += net/filter.c
|
|
endif
|
|
ifeq ($(CONFIG_NET_HTTPD), y)
|
|
CONFIG_SRCS-y += net/httpd.c
|
|
endif
|
|
ifeq ($(CONFIG_NET_SSHD), y)
|
|
CONFIG_SRCS-y += net/ssh.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_E1000), y)
|
|
CONFIG_SRCS-y += drivers/net/e1000.c drivers/pci/pci.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_RTL8139), y)
|
|
CONFIG_SRCS-y += drivers/net/rtl8139.c drivers/pci/pci.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_VIRTIO_NET), y)
|
|
CONFIG_SRCS-y += drivers/virtio/virtio_net.c virt/virtio.c
|
|
endif
|
|
|
|
# Character, Audio, Video Drivers
|
|
ifeq ($(CONFIG_DRV_PTY), y)
|
|
CONFIG_SRCS-y += drivers/char/pty.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_VIRTIO_RNG), y)
|
|
CONFIG_SRCS-y += drivers/char/virtio_rng.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_USB_XHCI), y)
|
|
CONFIG_SRCS-y += drivers/usb/xhci.c drivers/usb/usb.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_HWMON), y)
|
|
CONFIG_SRCS-y += drivers/hwmon/coretemp.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_CANVAS_2D), y)
|
|
CONFIG_SRCS-y += drivers/video/canvas.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_BOCHS_VBE), y)
|
|
CONFIG_SRCS-y += drivers/video/bochs.c drivers/video/fb.c drivers/video/fbcon.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_SOUND_HDA), y)
|
|
CONFIG_SRCS-y += sound/hda.c sound/sound.c sound/pcm.c sound/tts.c sound/melody.c
|
|
endif
|
|
ifeq ($(CONFIG_DRV_SOUND_AC97), y)
|
|
CONFIG_SRCS-y += sound/ac97.c sound/sound.c sound/pcm.c
|
|
endif
|
|
|
|
# Common Input/Display/Power/GPU/Networking Drivers
|
|
CONFIG_SRCS-y += drivers/char/tty.c drivers/char/keyboard.c drivers/char/serial.c drivers/char/vga.c \
|
|
drivers/input/mouse.c drivers/power/acpi.c drivers/power/cpufreq.c drivers/rtc/rtc.c drivers/sound/speaker.c \
|
|
drivers/net/e1000e.c drivers/virtio/virtio_gpu.c drivers/virtio/virtio_input.c \
|
|
drivers/timer/hpet.c drivers/char/lpt.c drivers/char/nvram.c
|
|
|
|
# Userland & GUI Desktop Subsystem
|
|
ifeq ($(CONFIG_USERLAND_LAZYBOX), y)
|
|
CONFIG_SRCS-y += userland/lazybox/lazybox.c userland/lazybox/shell.c userland/lazybox/sh.c userland/lazybox/nano.c userland/lazybox/snake.c userland/lazybox/tree.c userland/lazybox/coreutils.c
|
|
endif
|
|
|
|
CONFIG_SRCS-y += gui/gui.c gui/gui_gfx.c gui/gui_cursor.c gui/gui_wm.c gui/gui_desktop.c gui/gui_apps.c \
|
|
gui/gui_widgets.c gui/gui_icons.c gui/gui_dialog.c gui/gui_apps_ext.c gui/gui_terminal.c \
|
|
gui/gui_app_sorry.c
|
|
|
|
# Deduplicate
|
|
CONFIG_SRCS-y := $(sort $(CONFIG_SRCS-y))
|
|
|
|
# Rust & C++ Layer Configuration
|
|
ifeq ($(ARCH), x86_64)
|
|
RUSTC ?= rustc
|
|
RUST_SRCS = $(shell find rust/src -name '*.rs' 2>/dev/null)
|
|
RUST_LIB = $(BUILD_DIR)/rust/librust_kernel.a
|
|
CXX ?= g++
|
|
CXXFLAGS = -ffreestanding -fno-pie -fno-pic -mno-red-zone -mno-mmx -mno-sse -mno-sse2 \
|
|
-mcmodel=kernel -Wall -Wextra -Wno-unused-function -Wno-unused-parameter \
|
|
$(if $(CONFIG_OPTIMIZATION),$(CONFIG_OPTIMIZATION),-O2) -Iinclude -D__x86_64__ \
|
|
-std=c++17 -fno-exceptions -fno-rtti -fno-threadsafe-statics -fno-use-cxa-atexit
|
|
CPP_SRCS = $(shell find kernel/cpp -name '*.cpp' 2>/dev/null)
|
|
CPP_OBJS = $(patsubst %.cpp, $(BUILD_DIR)/%.o, $(CPP_SRCS))
|
|
ALL_C_SRCS = $(ARCH_C_SRCS) $(CONFIG_SRCS-y)
|
|
C_OBJS = $(patsubst %.c, $(BUILD_DIR)/%.o, $(ALL_C_SRCS))
|
|
ASM_OBJS = $(patsubst %.asm, $(BUILD_DIR)/%.o, $(ARCH_ASM_SRCS))
|
|
|
|
# Userland /sbin/init, linked separately and carried inside the kernel image.
|
|
INIT_SRC = userland/init/init.c
|
|
INIT_LD = userland/init/user.ld
|
|
INIT_OBJ = $(BUILD_DIR)/userland/init/init.o
|
|
INIT_ELF = $(BUILD_DIR)/userland/init/init.elf
|
|
INIT_BLOB_SRC = $(BUILD_DIR)/usr/init_blob.c
|
|
INIT_BLOB_OBJ = $(BUILD_DIR)/usr/init_blob.o
|
|
|
|
OTHER_OBJS = $(filter-out $(ENTRY_OBJ), $(ASM_OBJS) $(C_OBJS)) $(CPP_OBJS) $(INIT_BLOB_OBJ) $(RUST_LIB)
|
|
else
|
|
CONFIG_SRCS-y += rust/rust_fallback.c kernel/cpp/cpp_fallback.c
|
|
ALL_C_SRCS = $(ARCH_C_SRCS) $(CONFIG_SRCS-y)
|
|
C_OBJS = $(patsubst %.c, $(BUILD_DIR)/%.o, $(ALL_C_SRCS))
|
|
S_OBJS = $(patsubst %.S, $(BUILD_DIR)/%.o, $(ARCH_S_SRCS))
|
|
OTHER_OBJS = $(filter-out $(ENTRY_OBJ), $(S_OBJS) $(C_OBJS))
|
|
endif
|
|
|
|
# Generated dependency files, one per object. The include lives at the very
|
|
# end of this file: a .d file's first rule would otherwise become make's
|
|
# default goal and turn a bare `make` into a no-op.
|
|
DEPS = $(C_OBJS:.o=.d) $(CPP_OBJS:.o=.d) $(S_OBJS:.o=.d)
|
|
|
|
.DEFAULT_GOAL := all
|
|
|
|
.PHONY: all clean run run-headless run-fullscreen run-vnc run-server debug info configure menuconfig config tui nconfig defconfig x86_64_defconfig aarch64_defconfig armv8_defconfig armv8i_defconfig armv81_defconfig arm32_defconfig qemu help
|
|
|
|
all: $(TARGET)
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Configuration Targets (Linux Kconfig TUI Configurator)
|
|
# -----------------------------------------------------------------------------
|
|
configure menuconfig config tui nconfig:
|
|
@python3 scripts/kconfig/menuconfig.py
|
|
|
|
defconfig:
|
|
@python3 scripts/kconfig/menuconfig.py --defconfig $(ARCH)
|
|
|
|
x86_64_defconfig:
|
|
@python3 scripts/kconfig/menuconfig.py --x86_64
|
|
|
|
aarch64_defconfig:
|
|
@python3 scripts/kconfig/menuconfig.py --aarch64
|
|
|
|
armv8_defconfig armv8i_defconfig armv81_defconfig arm32_defconfig:
|
|
@python3 scripts/kconfig/menuconfig.py --armv8i
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Compilation Rules
|
|
# -----------------------------------------------------------------------------
|
|
# Header dependency tracking: without this a header change leaves stale objects
|
|
# behind, and a struct layout edit silently corrupts every unrebuilt caller.
|
|
DEPFLAGS = -MMD -MP
|
|
|
|
# C Source Files
|
|
$(BUILD_DIR)/%.o: %.c include/config/autoconf.h
|
|
@mkdir -p $(dir $@)
|
|
$(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@
|
|
|
|
# C++ Source Files
|
|
$(BUILD_DIR)/%.o: %.cpp include/config/autoconf.h
|
|
@mkdir -p $(dir $@)
|
|
$(CXX) $(CXXFLAGS) $(DEPFLAGS) -c $< -o $@
|
|
|
|
# x86_64 NASM Assembly Files
|
|
$(BUILD_DIR)/%.o: %.asm
|
|
@mkdir -p $(dir $@)
|
|
$(ASM) $(ASMFLAGS_ELF) $< -o $@
|
|
|
|
# ARM/AArch64 GNU Assembly Files (.S)
|
|
$(BUILD_DIR)/%.o: %.S
|
|
@mkdir -p $(dir $@)
|
|
$(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@
|
|
|
|
# Userland Program Compilation
|
|
#
|
|
# /sbin/init is a separate freestanding executable, not kernel code: it is
|
|
# linked at the user base from userland/user.ld and must never see the kernel's
|
|
# -mcmodel=kernel, which cannot reach the user half of the address space.
|
|
USER_CFLAGS = -ffreestanding -nostdlib -fno-pie -fno-pic -mno-red-zone \
|
|
-mcmodel=large -mno-sse -mno-mmx -mno-sse2 \
|
|
-Wall -Wextra -Wno-unused-function \
|
|
$(if $(CONFIG_OPTIMIZATION),$(CONFIG_OPTIMIZATION),-O2)
|
|
|
|
$(INIT_OBJ): $(INIT_SRC)
|
|
@mkdir -p $(dir $@)
|
|
$(CC) $(USER_CFLAGS) -c $< -o $@
|
|
|
|
$(INIT_ELF): $(INIT_OBJ) $(INIT_LD)
|
|
@mkdir -p $(dir $@)
|
|
$(LD) -nostdlib -no-pie -T $(INIT_LD) -o $@ $(INIT_OBJ)
|
|
@echo "=== [Userland init linked: $@] ==="
|
|
|
|
$(INIT_BLOB_SRC): $(INIT_ELF) scripts/mkblob.py
|
|
@mkdir -p $(dir $@)
|
|
@python3 scripts/mkblob.py $(INIT_ELF) $@ subos_init_elf
|
|
|
|
$(INIT_BLOB_OBJ): $(INIT_BLOB_SRC) include/config/autoconf.h
|
|
@mkdir -p $(dir $@)
|
|
$(CC) $(CFLAGS) -c $< -o $@
|
|
|
|
# Rust Source Compilation
|
|
$(RUST_LIB): rust/src/lib.rs $(RUST_SRCS)
|
|
@mkdir -p $(dir $@)
|
|
$(RUSTC) --crate-type staticlib -C panic=abort -C relocation-model=static -C opt-level=2 -C no-redzone=y -o $@ rust/src/lib.rs
|
|
|
|
|
|
# Header Generation Fallback
|
|
include/config/autoconf.h:
|
|
@mkdir -p include/config
|
|
@if [ ! -f .config ]; then python3 scripts/kconfig/menuconfig.py --defconfig $(ARCH); fi
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Link & Image Assembly
|
|
# -----------------------------------------------------------------------------
|
|
$(BUILD_DIR)/boot/boot.bin: $(BOOT_DIR)/boot.asm | $(BUILD_DIR)/boot
|
|
$(ASM) $(ASMFLAGS_BOOT) $< -o $@
|
|
|
|
$(BUILD_DIR)/boot/stage2.bin: $(BOOT_DIR)/stage2.asm $(BOOT_DIR)/gdt.asm | $(BUILD_DIR)/boot
|
|
$(ASM) $(ASMFLAGS_BOOT) $< -o $@
|
|
|
|
$(BUILD_DIR)/boot:
|
|
mkdir -p $(BUILD_DIR)/boot
|
|
|
|
LIBGCC ?= $(shell $(CC) $(CFLAGS) -print-libgcc-file-name 2>/dev/null)
|
|
|
|
$(BUILD_DIR)/kernel.elf: $(ENTRY_OBJ) $(OTHER_OBJS)
|
|
$(LD) $(LDFLAGS) -o $@ $(ENTRY_OBJ) $(OTHER_OBJS) $(LIBGCC)
|
|
@echo "=== [Kernel ELF Linked: $@ (Architecture: $(ARCH))] ==="
|
|
|
|
$(BUILD_DIR)/kernel.bin: $(BUILD_DIR)/kernel.elf
|
|
$(OBJCOPY) -O binary $< $@
|
|
|
|
$(IMAGE): $(BUILD_DIR)/boot/boot.bin $(BUILD_DIR)/boot/stage2.bin $(BUILD_DIR)/kernel.bin
|
|
dd if=/dev/zero of=$@ bs=512 count=2880 status=none
|
|
dd if=$(BUILD_DIR)/boot/boot.bin of=$@ bs=512 conv=notrunc status=none
|
|
dd if=$(BUILD_DIR)/boot/stage2.bin of=$@ bs=512 seek=1 conv=notrunc status=none
|
|
dd if=$(BUILD_DIR)/kernel.bin of=$@ bs=512 seek=16 conv=notrunc status=none
|
|
@echo "=== [SUB-OS x86_64 Disk Image Built: $@ (Size: $$(du -h $@ | cut -f1))] ==="
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Execution & Emulation Targets
|
|
# -----------------------------------------------------------------------------
|
|
# -vga std gives the Bochs VBE adapter the kernel drives. vgamem_mb is raised
|
|
# because a 1280x720 32-bit framebuffer needs more than the 8 MB default.
|
|
QEMU_VGA = -device VGA,vgamem_mb=64
|
|
|
|
# `make run` boots straight into the SUB-OS Graphical Desktop Environment. The
|
|
# guest window scales with zoom-to-fit; pass `nogui`/`text` on the kernel
|
|
# command line for the emergency TTY. Use `make run-headless` for serial only.
|
|
run qemu: $(TARGET)
|
|
ifeq ($(ARCH), x86_64)
|
|
qemu-system-x86_64 -drive format=raw,file=$(IMAGE) -m 512M \
|
|
-netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \
|
|
-device e1000,netdev=net0 $(QEMU_VGA) -display gtk,zoom-to-fit=on -serial stdio
|
|
else ifneq ($(filter $(ARCH), aarch64 arm64),)
|
|
qemu-system-aarch64 -M virt -cpu cortex-a57 -m 256M -kernel $(BUILD_DIR)/kernel.elf -device virtio-gpu-pci -serial stdio
|
|
else
|
|
qemu-system-arm -M virt -cpu cortex-a15 -m 256M -kernel $(BUILD_DIR)/kernel.elf -device virtio-gpu-pci -serial stdio
|
|
endif
|
|
|
|
# Headless: no graphical window, kernel console on the serial line only. Boot
|
|
# with `nogui` on the kernel command line to reach the TTY in this mode.
|
|
run-headless: $(TARGET)
|
|
$(QEMU_CMD)
|
|
|
|
# Fullscreen without distortion: zoom-to-fit scales the guest while preserving
|
|
# its aspect ratio, letterboxing rather than stretching on a wider panel.
|
|
run-fullscreen: $(TARGET)
|
|
ifeq ($(ARCH), x86_64)
|
|
qemu-system-x86_64 -drive format=raw,file=$(IMAGE) \
|
|
-netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \
|
|
-device e1000,netdev=net0 $(QEMU_VGA) \
|
|
-display gtk,zoom-to-fit=on,show-cursor=on -full-screen -serial stdio
|
|
else
|
|
@echo "run-fullscreen targets x86_64 only"
|
|
endif
|
|
|
|
run-vnc: $(TARGET)
|
|
ifeq ($(ARCH), x86_64)
|
|
@echo "=== [QEMU VNC Server running at localhost:5900 (VNC Display :0)] ==="
|
|
qemu-system-x86_64 -drive format=raw,file=$(IMAGE) \
|
|
-netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \
|
|
-device e1000,netdev=net0 $(QEMU_VGA) -vnc :0 -serial stdio
|
|
else
|
|
@echo "=== [QEMU VNC Server running at localhost:5900 (VNC Display :0)] ==="
|
|
qemu-system-aarch64 -M virt -cpu cortex-a57 -m 128M -kernel $(BUILD_DIR)/kernel.elf -device virtio-gpu-pci -vnc :0 -serial stdio
|
|
endif
|
|
|
|
run-server: $(IMAGE)
|
|
qemu-system-x86_64 -drive format=raw,file=$(IMAGE) \
|
|
-netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \
|
|
-device e1000,netdev=net0 -serial stdio -display none
|
|
|
|
debug: $(TARGET)
|
|
ifeq ($(ARCH), x86_64)
|
|
qemu-system-x86_64 -drive format=raw,file=$(IMAGE) \
|
|
-netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::8080-:80 \
|
|
-device e1000,netdev=net0 -serial stdio -s -S
|
|
else ifneq ($(filter $(ARCH), aarch64 arm64),)
|
|
qemu-system-aarch64 -M virt -cpu cortex-a57 -m 128M -nographic -kernel $(BUILD_DIR)/kernel.elf -s -S
|
|
else
|
|
qemu-system-arm -M virt -cpu cortex-a15 -m 128M -nographic -kernel $(BUILD_DIR)/kernel.elf -s -S
|
|
endif
|
|
|
|
info:
|
|
@echo "Target Architecture: $(ARCH)"
|
|
@echo "Cross Compiler: $(CROSS_COMPILE)"
|
|
@echo "Compiled Sources: $(words $(ALL_C_SRCS)) C files"
|
|
@echo "Target Binary: $(TARGET)"
|
|
|
|
help:
|
|
@echo "SUB-OS Kernel Build System (Linux-Style Kconfig)"
|
|
@echo "=================================================="
|
|
@echo " make configure - Launch interactive Linux-style TUI Configurator"
|
|
@echo " make menuconfig - Alias for make configure"
|
|
@echo " make defconfig - Reset to default configuration for active ARCH"
|
|
@echo " make x86_64_defconfig - Load x86_64 default configuration"
|
|
@echo " make aarch64_defconfig- Load AArch64 default configuration"
|
|
@echo " make armv8i_defconfig - Load ARMv8i (32-bit ARM) default configuration"
|
|
@echo " make all [ARCH=...] - Compile kernel image for selected architecture"
|
|
@echo " make run [ARCH=...] - Boot into the SUB-OS Graphical Desktop in QEMU"
|
|
@echo " make run-headless - Boot in QEMU with serial console only (no window)"
|
|
@echo " make run-fullscreen - Boot the desktop in a full-screen QEMU window"
|
|
@echo " make run-vnc - Boot the desktop and expose it over VNC :0"
|
|
@echo " make clean - Remove all compiled objects and disk images"
|
|
@echo " make info - Display build configuration and source metrics"
|
|
|
|
clean:
|
|
rm -rf $(BUILD_DIR) $(IMAGE)
|
|
|
|
-include $(DEPS)
|