mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-21 10:40:00 +00:00
226 lines
9.1 KiB
Makefile
226 lines
9.1 KiB
Makefile
.RECIPEPREFIX := >
|
|
|
|
NO_COLOR ?= 0
|
|
|
|
BUILD_ROOT := build/x86_64
|
|
OBJ_ROOT := $(BUILD_ROOT)/obj
|
|
ISO_ROOT := $(BUILD_ROOT)/iso_root
|
|
KERNEL_ELF := $(BUILD_ROOT)/clks_kernel.elf
|
|
RAMDISK_IMAGE := $(BUILD_ROOT)/cleonos_ramdisk.tar
|
|
ISO_IMAGE := build/CLeonOS-x86_64.iso
|
|
|
|
LIMINE_DIR ?= limine
|
|
LIMINE_REPO ?= https://gh-proxy.com/https://github.com/limine-bootloader/limine.git
|
|
LIMINE_REF ?=
|
|
LIMINE_BIN_DIR ?= $(LIMINE_DIR)/bin
|
|
LIMINE_SETUP_STAMP := $(LIMINE_DIR)/.cleonos-limine-setup.stamp
|
|
LIMINE_BUILD_STAMP := $(LIMINE_DIR)/.cleonos-limine-build.stamp
|
|
LIMINE_CONFIGURE_FLAGS ?= --enable-bios-cd --enable-uefi-cd --enable-uefi-x86-64
|
|
LIMINE_SKIP_CONFIGURE ?= 0
|
|
OBJCOPY_FOR_TARGET ?= llvm-objcopy
|
|
OBJDUMP_FOR_TARGET ?= llvm-objdump
|
|
READELF_FOR_TARGET ?= llvm-readelf
|
|
|
|
XORRISO ?= xorriso
|
|
TAR ?= tar
|
|
|
|
QEMU_X86_64 ?= qemu-system-x86_64
|
|
|
|
CC ?= x86_64-elf-gcc
|
|
LD ?= x86_64-elf-ld
|
|
ARCH_CFLAGS := -DCLKS_ARCH_X86_64=1 -m64 -mno-red-zone -mcmodel=kernel -fno-pic -fno-pie
|
|
LINKER_SCRIPT := clks/arch/x86_64/linker.ld
|
|
RUN_COMMAND := $(QEMU_X86_64) -M q35 -m 1024M -cdrom $(ISO_IMAGE) -serial stdio
|
|
DEBUG_COMMAND := $(QEMU_X86_64) -M q35 -m 1024M -cdrom $(ISO_IMAGE) -serial stdio -s -S
|
|
|
|
ifeq ($(NO_COLOR),1)
|
|
COLOR_RESET :=
|
|
COLOR_INFO :=
|
|
COLOR_WARN :=
|
|
COLOR_ERROR :=
|
|
COLOR_STEP :=
|
|
else
|
|
COLOR_RESET := \033[0m
|
|
COLOR_INFO := \033[1;36m
|
|
COLOR_WARN := \033[1;33m
|
|
COLOR_ERROR := \033[1;31m
|
|
COLOR_STEP := \033[1;35m
|
|
endif
|
|
|
|
define log_info
|
|
@printf '%b\n' "$(COLOR_INFO)[INFO]$(COLOR_RESET) $(1)"
|
|
endef
|
|
|
|
define log_warn
|
|
@printf '%b\n' "$(COLOR_WARN)[WARN]$(COLOR_RESET) $(1)"
|
|
endef
|
|
|
|
define log_error
|
|
@printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) $(1)"
|
|
endef
|
|
|
|
define log_step
|
|
@printf '%b\n' "$(COLOR_STEP)[STEP]$(COLOR_RESET) $(1)"
|
|
endef
|
|
|
|
SOURCES := \
|
|
clks/kernel/kmain.c \
|
|
clks/kernel/log.c \
|
|
clks/kernel/limine_requests.c \
|
|
clks/kernel/tty.c \
|
|
clks/lib/string.c \
|
|
clks/drivers/serial/serial.c \
|
|
clks/drivers/video/framebuffer.c \
|
|
clks/drivers/video/font8x8.c \
|
|
clks/arch/x86_64/boot.c
|
|
|
|
OBJECTS := $(patsubst %.c,$(OBJ_ROOT)/%.o,$(SOURCES))
|
|
|
|
CFLAGS_COMMON := -std=c11 -ffreestanding -fno-stack-protector -fno-builtin -Wall -Wextra -Werror -Iclks/include
|
|
LDFLAGS_COMMON := -nostdlib -z max-page-size=0x1000
|
|
|
|
.PHONY: all setup setup-tools setup-limine kernel ramdisk iso run debug clean clean-all help
|
|
|
|
all: iso
|
|
|
|
setup: setup-tools setup-limine
|
|
> $(call log_info,environment ready)
|
|
|
|
setup-tools:
|
|
> $(call log_step,checking host tools)
|
|
> @command -v git >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: git" && exit 1)
|
|
> @command -v $(TAR) >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: $(TAR)" && exit 1)
|
|
> @command -v $(XORRISO) >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: $(XORRISO)" && exit 1)
|
|
> @command -v clang >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: clang" && exit 1)
|
|
> @command -v ld.lld >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: ld.lld" && exit 1)
|
|
> @command -v $(OBJCOPY_FOR_TARGET) >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: $(OBJCOPY_FOR_TARGET)" && exit 1)
|
|
> @command -v $(OBJDUMP_FOR_TARGET) >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: $(OBJDUMP_FOR_TARGET)" && exit 1)
|
|
> @command -v $(READELF_FOR_TARGET) >/dev/null 2>&1 || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) missing tool: $(READELF_FOR_TARGET)" && exit 1)
|
|
> $(call log_info,required tools are available)
|
|
|
|
setup-limine:
|
|
> $(call log_step,preparing limine)
|
|
> @if [ ! -d "$(LIMINE_DIR)" ]; then \
|
|
> if [ -n "$(LIMINE_REF)" ]; then \
|
|
> printf '%b\n' "$(COLOR_INFO)[INFO]$(COLOR_RESET) cloning limine ($(LIMINE_REF)) into $(LIMINE_DIR)"; \
|
|
> git clone --branch "$(LIMINE_REF)" --depth 1 "$(LIMINE_REPO)" "$(LIMINE_DIR)"; \
|
|
> else \
|
|
> printf '%b\n' "$(COLOR_INFO)[INFO]$(COLOR_RESET) cloning limine (default branch) into $(LIMINE_DIR)"; \
|
|
> git clone --depth 1 "$(LIMINE_REPO)" "$(LIMINE_DIR)"; \
|
|
> fi; \
|
|
> fi
|
|
> @if [ "$(LIMINE_SKIP_CONFIGURE)" = "1" ]; then \
|
|
> test -f "$(LIMINE_DIR)/Makefile" || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) LIMINE_SKIP_CONFIGURE=1 but $(LIMINE_DIR)/Makefile is missing" && exit 1); \
|
|
> printf '%b\n' "$(COLOR_WARN)[WARN]$(COLOR_RESET) skipping limine Makefile generation (LIMINE_SKIP_CONFIGURE=1)"; \
|
|
> else \
|
|
> cfg_fingerprint="FLAGS=$(LIMINE_CONFIGURE_FLAGS);OBJCOPY=$(OBJCOPY_FOR_TARGET);OBJDUMP=$(OBJDUMP_FOR_TARGET);READELF=$(READELF_FOR_TARGET)"; \
|
|
> need_configure=0; \
|
|
> if [ ! -f "$(LIMINE_DIR)/Makefile" ]; then need_configure=1; fi; \
|
|
> if [ ! -f "$(LIMINE_SETUP_STAMP)" ]; then need_configure=1; fi; \
|
|
> if [ -f "$(LIMINE_SETUP_STAMP)" ] && ! grep -qx "$$cfg_fingerprint" "$(LIMINE_SETUP_STAMP)"; then need_configure=1; fi; \
|
|
> if [ "$$need_configure" -eq 1 ]; then \
|
|
> printf '%b\n' "$(COLOR_STEP)[STEP]$(COLOR_RESET) generating/reconfiguring limine Makefile"; \
|
|
> if [ -x "$(LIMINE_DIR)/bootstrap" ]; then \
|
|
> (cd "$(LIMINE_DIR)" && ./bootstrap); \
|
|
> fi; \
|
|
> test -x "$(LIMINE_DIR)/configure" || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) limine configure script missing" && exit 1); \
|
|
> (cd "$(LIMINE_DIR)" && OBJCOPY_FOR_TARGET="$(OBJCOPY_FOR_TARGET)" OBJDUMP_FOR_TARGET="$(OBJDUMP_FOR_TARGET)" READELF_FOR_TARGET="$(READELF_FOR_TARGET)" ./configure $(LIMINE_CONFIGURE_FLAGS)); \
|
|
> printf '%s\n' "$$cfg_fingerprint" > "$(LIMINE_SETUP_STAMP)"; \
|
|
> rm -f "$(LIMINE_BUILD_STAMP)"; \
|
|
> else \
|
|
> printf '%b\n' "$(COLOR_INFO)[INFO]$(COLOR_RESET) limine configure state unchanged"; \
|
|
> fi; \
|
|
> fi
|
|
> @need_build=0; \
|
|
> if [ ! -f "$(LIMINE_BUILD_STAMP)" ]; then need_build=1; fi; \
|
|
> for f in limine limine-bios.sys limine-bios-cd.bin limine-uefi-cd.bin; do \
|
|
> if [ ! -f "$(LIMINE_BIN_DIR)/$$f" ]; then need_build=1; fi; \
|
|
> done; \
|
|
> if [ "$$need_build" -eq 1 ]; then \
|
|
> printf '%b\n' "$(COLOR_INFO)[INFO]$(COLOR_RESET) building limine"; \
|
|
> $(MAKE) -C "$(LIMINE_DIR)"; \
|
|
> touch "$(LIMINE_BUILD_STAMP)"; \
|
|
> else \
|
|
> printf '%b\n' "$(COLOR_INFO)[INFO]$(COLOR_RESET) limine already built, skipping compile"; \
|
|
> fi
|
|
> @test -f "$(LIMINE_BIN_DIR)/limine" || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) limine build failed" && exit 1)
|
|
> @test -f "$(LIMINE_BIN_DIR)/limine-bios.sys" || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) limine-bios.sys missing" && exit 1)
|
|
> @test -f "$(LIMINE_BIN_DIR)/limine-bios-cd.bin" || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) limine-bios-cd.bin missing" && exit 1)
|
|
> @test -f "$(LIMINE_BIN_DIR)/limine-uefi-cd.bin" || (printf '%b\n' "$(COLOR_ERROR)[ERROR]$(COLOR_RESET) limine-uefi-cd.bin missing" && exit 1)
|
|
> $(call log_info,limine artifacts ready)
|
|
|
|
kernel: $(KERNEL_ELF)
|
|
|
|
ramdisk: $(RAMDISK_IMAGE)
|
|
|
|
$(KERNEL_ELF): $(OBJECTS) $(LINKER_SCRIPT) Makefile
|
|
> $(call log_step,linking kernel -> $(KERNEL_ELF))
|
|
> @mkdir -p $(dir $@)
|
|
> @$(LD) $(LDFLAGS_COMMON) -T $(LINKER_SCRIPT) -o $@ $(OBJECTS)
|
|
|
|
$(OBJ_ROOT)/%.o: %.c Makefile
|
|
> $(call log_step,compiling $<)
|
|
> @mkdir -p $(dir $@)
|
|
> @$(CC) $(CFLAGS_COMMON) $(ARCH_CFLAGS) -c $< -o $@
|
|
|
|
$(RAMDISK_IMAGE):
|
|
> $(call log_step,packing ramdisk -> $(RAMDISK_IMAGE))
|
|
> @mkdir -p $(dir $@)
|
|
> @$(TAR) -C ramdisk -cf $@ .
|
|
|
|
iso: setup-tools setup-limine $(KERNEL_ELF) $(RAMDISK_IMAGE) configs/limine.conf
|
|
> $(call log_step,assembling iso root)
|
|
> @rm -rf $(ISO_ROOT)
|
|
> @mkdir -p $(ISO_ROOT)/boot/limine
|
|
> @cp $(KERNEL_ELF) $(ISO_ROOT)/boot/clks_kernel.elf
|
|
> @cp $(RAMDISK_IMAGE) $(ISO_ROOT)/boot/cleonos_ramdisk.tar
|
|
> @cp configs/limine.conf $(ISO_ROOT)/boot/limine/limine.conf
|
|
> @cp $(LIMINE_BIN_DIR)/limine-bios.sys $(ISO_ROOT)/boot/limine/
|
|
> @cp $(LIMINE_BIN_DIR)/limine-bios-cd.bin $(ISO_ROOT)/boot/limine/
|
|
> @cp $(LIMINE_BIN_DIR)/limine-uefi-cd.bin $(ISO_ROOT)/boot/limine/
|
|
> @mkdir -p $(dir $(ISO_IMAGE))
|
|
> $(call log_step,building iso -> $(ISO_IMAGE))
|
|
> @$(XORRISO) -as mkisofs \
|
|
> -b boot/limine/limine-bios-cd.bin \
|
|
> -no-emul-boot \
|
|
> -boot-load-size 4 \
|
|
> -boot-info-table \
|
|
> --efi-boot boot/limine/limine-uefi-cd.bin \
|
|
> -efi-boot-part \
|
|
> --efi-boot-image \
|
|
> --protective-msdos-label \
|
|
> $(ISO_ROOT) \
|
|
> -o $(ISO_IMAGE)
|
|
> $(call log_step,installing limine boot sectors)
|
|
> @$(LIMINE_BIN_DIR)/limine bios-install $(ISO_IMAGE)
|
|
> $(call log_info,iso ready: $(ISO_IMAGE))
|
|
|
|
run: iso
|
|
> $(call log_step,launching qemu run)
|
|
> @$(RUN_COMMAND)
|
|
|
|
debug: iso
|
|
> $(call log_step,launching qemu debug (-s -S))
|
|
> @$(DEBUG_COMMAND)
|
|
|
|
clean:
|
|
> $(call log_step,cleaning $(BUILD_ROOT))
|
|
> @rm -rf $(BUILD_ROOT)
|
|
> $(call log_info,clean done)
|
|
|
|
clean-all:
|
|
> $(call log_step,cleaning build)
|
|
> @rm -rf build
|
|
> $(call log_info,clean-all done)
|
|
|
|
help:
|
|
> @echo "CLeonOS build system (x86_64 only)"
|
|
> @echo " make setup"
|
|
> @echo " make setup LIMINE_REF=<branch-or-tag>"
|
|
> @echo " make setup LIMINE_SKIP_CONFIGURE=1"
|
|
> @echo " make setup LIMINE_CONFIGURE_FLAGS='--enable-bios-cd --enable-uefi-cd --enable-uefi-x86-64'"
|
|
> @echo " make setup OBJCOPY_FOR_TARGET=llvm-objcopy OBJDUMP_FOR_TARGET=llvm-objdump READELF_FOR_TARGET=llvm-readelf"
|
|
> @echo " make iso"
|
|
> @echo " make run"
|
|
> @echo " make debug"
|
|
> @echo " make NO_COLOR=1 <target>" |