Skip to content

Commit

Permalink
build: moved to single top-level makefile
Browse files Browse the repository at this point in the history
  • Loading branch information
DeanoBurrito committed Jan 20, 2025
1 parent 99ffc95 commit a0442a4
Show file tree
Hide file tree
Showing 24 changed files with 312 additions and 598 deletions.
9 changes: 2 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
.devel-cache
.upstream
build/
kbuild/
iso/
initdisk/drivers/
initdisk/LICENSE
.cache
.build/
initdisk/pci.ids
BakedConstants.cpp
compile_flags.txt
223 changes: 81 additions & 142 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,164 +1,103 @@
# User-facing config file.
include Config.mk
# Translate Config.mk variables into build flags.
include misc/BuildPrep.mk
# Things to make the output nicer on the eyes
include misc/Formatting.mk
# Help text, provides `make help` target which runs by default
include misc/HelpText.mk

# Toolchain selection
ifeq ($(TOOLCHAIN), gcc)
export X_CXX_BIN = $(TOOLCHAIN_PREFIX)$(ARCH_TARGET)-g++
export X_AS_BIN = $(TOOLCHAIN_PREFIX)$(ARCH_TARGET)-as
export X_LD_BIN = $(TOOLCHAIN_PREFIX)$(ARCH_TARGET)-ld
export X_AR_BIN = $(TOOLCHAIN_PREFIX)$(ARCH_TARGET)-ar
export KERNEL_AS_FLAGS =
else ifeq ($(TOOLCHAIN), clang)
export X_CXX_BIN = clang++ --target=$(ARCH_TARGET)
export X_AS_BIN = clang --target=$(ARCH_TARGET)
export X_LD_BIN = ld.lld
export X_AR_BIN = llvm-ar
export KERNEL_AS_FLAGS = -c
else
$(error "Unknown toolchain: $(TOOLCHAIN), build aborted.")
endif
KERNEL_CXX_FLAGS += -Wall -Wextra -fstack-protector-strong -fPIE -ffreestanding \
-fno-omit-frame-pointer -fvisibility=hidden -fno-asynchronous-unwind-tables \
-std=c++17 -fno-rtti -fno-exceptions -fsized-deallocation -fno-unwind-tables \
-Ikernel/include -DNPK_HAS_KERNEL -Ilibs/np-syslib/include -ffunction-sections -fdata-sections
KERNEL_LD_FLAGS += -zmax-page-size=0x1000 -static -pie -nostdlib --gc-sections

# Setting up paths for development files
ifeq ($(USE_DEVEL_CACHE), yes)
include misc/DevelCache.mk
else
export LIMINE_DIR
export OVMF_FILE
endif
BUILD_DIR = .build
VENDOR_CACHE_DIR = .cache
ARCH_DIR = arch/$(CPU_ARCH)
KERNEL_TARGET = $(BUILD_DIR)/npk-$(CPU_ARCH)
BUILD_TARGETS = $(KERNEL_TARGET) $(INITDISK_TARGET)
ISO_BUILD_DIR = $(BUILD_DIR)/iso
ISO_TARGET = $(BUILD_DIR)/northport-live-$(CPU_ARCH).iso

# Arch-specific flags + targets.
include misc/cross/$(CPU_ARCH)/CrossConfig.mk
ARCH_TARGET = $(CPU_ARCH)-elf
KERNEL_VER_MAJOR = 0
KERNEL_VER_MINOR = 5
KERNEL_VER_REVISION = 0
KERNEL_CXX_FLAGS_HASH = $(strip $(shell echo $(KERNEL_CXX_FLAGS) | sha256sum | cut -d " " -f1))

# Platform-agnostic compiler and linker flags for the kernel and drivers
export KERNEL_CXX_FLAGS += -Wall -Wextra -fstack-protector-strong -fPIE \
-fno-omit-frame-pointer -ffreestanding -fvisibility=hidden \
-std=c++17 -fno-rtti -fno-exceptions -fsized-deallocation -fno-unwind-tables \
-fno-asynchronous-unwind-tables -Iinclude -DNP_KERNEL \
-I$(PROJ_ROOT_DIR)/libs/np-syslib/include
export KERNEL_LD_FLAGS += -L$(LIBS_OUTPUT_DIR) -lknp-syslib \
-nostdlib -zmax-page-size=0x1000 -static -pie
export SYSLIB_CXX_FLAGS += -fvisibility=default -fPIC
export DRIVER_C_FLAGS += -Wall -Wextra -std=c17 -fno-unwind-tables -fno-asynchronous-unwind-tables \
-ffreestanding -fPIC -fvisibility=hidden -fno-omit-frame-pointer \
-I$(PROJ_ROOT_DIR)/kernel/include -I$(PROJ_ROOT_DIR)/libs/np-syslib/include
export DRIVER_CXX_FLAGS += -Wall -Wextra -std=c++17 -fno-rtti -fno-exceptions -fno-unwind-tables \
-fno-asynchronous-unwind-tables -ffreestanding -fPIC -fvisibility=hidden -fno-omit-frame-pointer \
-fsized-deallocation \
-I$(PROJ_ROOT_DIR)/kernel/include -I$(PROJ_ROOT_DIR)/libs/np-syslib/include \
-I$(PROJ_ROOT_DIR)/libs/np-driverlib/include
export DRIVER_LD_FLAGS += -nostdlib -shared -znorelro \
-L$(LIBS_OUTPUT_DIR) --exclude-libs ALL -lknp-syslib -lnp-driverlib \
-T$(PROJ_ROOT_DIR)/misc/cross/$(CPU_ARCH)/Driver.lds

export BUILD_DIR = build
export CPU_ARCH
export TOOLCHAIN
export ARCH_TARGET = $(CPU_ARCH)-elf
export KERNEL_BOOT_PROTOCOL

PROJ_DIR_INITDISK = initdisk
PROJ_DIR_KERNEL = kernel
PROJ_DIR_LIBS = libs
PROJ_DIR_DRIVERS = drivers
PROJ_DIR_DOCS = docs/manual

export INITDISK_FULL_FILEPATH = $(abspath $(PROJ_DIR_INITDISK)/$(BUILD_DIR)/northport-initdisk.tar)
export KERNEL_FILENAME = northport-kernel-$(CPU_ARCH).elf
export KERNEL_FULL_FILEPATH = $(abspath $(PROJ_DIR_KERNEL)/$(BUILD_DIR)/$(KERNEL_FILENAME))
export LIBS_OUTPUT_DIR = $(abspath $(PROJ_DIR_LIBS)/$(BUILD_DIR))
export DRIVERS_OUTPUT_DIR = $(abspath $(PROJ_DIR_DRIVERS)/$(BUILD_DIR))
export SUBMAKE_FLAGS = --no-print-directory -j $(shell nproc)
export PROJ_ROOT_DIR = $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))

ISO_TEMP_DIR = iso/build
ISO_FILENAME = iso/northport-$(CPU_ARCH).iso
export ISO_FULL_FILEPATH = $(abspath $(ISO_FILENAME))
LIMINE_BINARIES = $(VENDOR_CACHE_DIR)/limine

include misc/cross/$(CPU_ARCH)/CrossConfig.mk
include kernel/arch/$(CPU_ARCH)/Arch.mk
include libs/np-syslib/Local.mk
include kernel/Local.mk
include initdisk/Local.mk

.PHONY: help
help: help-text

.PHONY: all
all: $(ARCH_DEFAULT_TARGET)

.PHONY: clean
clean:
$(LOUD)-rm $(BUILD_DIR) -r $(LOUD_REDIRECT)
@printf "$(C_CYAN)[Build]$(C_RST) Removing build artefacts in: $(BUILD_DIR)\n"

.PHONY: clean-cache
clean-cache:
$(LOUD)-rm $(VENDOR_CACHE_DIR) -rf $(LOUD_REDIRECT)
@printf "$(C_YELLOW)[Cache]$(C_RST) Removing vendor artefacts in: $(VENDOR_CACHE_DIR)\n"

.PHONY: options
options:
@printf "$(C_CYAN)Toolchain:$(C_RST) $(TOOLCHAIN), $(C_CYAN)Arch:$(C_RST)\
$(CPU_ARCH), $(C_CYAN)Boot Protocol:$(C_RST) $(KERNEL_BOOT_PROTOCOL), $(C_CYAN)Quiet:$(C_RST) $(QUIET_BUILD)\r\n"
@printf "$(C_CYAN)Kernel C++ flags:$(C_RST) $(KERNEL_CXX_FLAGS)\r\n"
@printf "$(C_CYAN)Kernel LD flags:$(C_RST) $(KERNEL_LD_FLAGS)\r\n"

.PHONY: binaries
binaries: options
$(LOUD)cd $(PROJ_DIR_LIBS)/np-syslib; $(MAKE) all-kernel $(SUBMAKE_FLAGS)
$(LOUD)cd $(PROJ_DIR_LIBS); $(MAKE) all $(SUBMAKE_FLAGS)
$(LOUD)cd $(PROJ_DIR_KERNEL); $(MAKE) all $(SUBMAKE_FLAGS)
$(LOUD)cd $(PROJ_DIR_DRIVERS); $(MAKE) all $(SUBMAKE_FLAGS)
$(LOUD)cd $(PROJ_DIR_INITDISK); $(MAKE) all $(SUBMAKE_FLAGS)
$(CPU_ARCH), $(C_CYAN)Boot Protocol:$(C_RST) $(KERNEL_BOOT_PROTOCOL), $(C_CYAN)Quiet:$(C_RST) $(QUIET_BUILD)\n"
@printf "$(C_CYAN)Kernel C++ flags:$(C_RST) $(KERNEL_CXX_FLAGS)\n"
@printf "$(C_CYAN)Kernel LD flags:$(C_RST) $(KERNEL_LD_FLAGS)\n"
ifeq ($(COUNT_TODOS), yes)
@printf "$(C_CYAN)[Build]$(C_RST) $(shell grep -o "TODO:" $$(find -name "*.cpp"\
-o -name "*.h" -o -name "*.S") | wc -l) TODOs found in code, $(shell grep -o \
"TODO:" $$(find -name "*.tex" -o -name "*.md") | wc -l) TODOs found in docs.\r\n"
@printf "$(C_CYAN)TODOs:$(C_RST) $(shell grep -o "TODO:" $$(find -name "*.cpp"\
-o -name "*.h" -o -name "*.S") | wc -l) in code, $(shell grep -o \
"TODO:" $$(find -name "*.tex" -o -name "*.md") | wc -l) in docs.\n"
endif

#Builds a bootable (via uefi) iso, suitable for any platforms that support UEFI.
.PHONY: iso
iso: binaries $(LIMINE_DIR)
$(LOUD)mkdir -p $(ISO_TEMP_DIR)
$(LOUD)cp misc/cross/$(CPU_ARCH)/limine.cfg $(ISO_TEMP_DIR)
$(LOUD)cp $(LIMINE_DIR)/limine-uefi-cd.bin $(ISO_TEMP_DIR)
$(LOUD)mkdir -p $(ISO_TEMP_DIR)/EFI/BOOT
$(LOUD)cp $(LIMINE_DIR)/$(UEFI_BOOT_NAME) $(ISO_TEMP_DIR)/EFI/BOOT/
$(LOUD)cp $(INITDISK_FULL_FILEPATH) $(ISO_TEMP_DIR)
$(LOUD)cp $(KERNEL_FULL_FILEPATH) $(ISO_TEMP_DIR)
.PHONY: run
run: $(ARCH_DEFAULT_TARGET) $(QEMU_FW_FILE)
$(LOUD)$(QEMU_BASE) $(QEMU_ACCEL)

.PHONY: run-noaccel
run-noaccel: $(ARCH_DEFAULT_TARGET) $(QEMU_FW_FILE)
$(LOUD)$(QEMU_BASE) $(QEMU_NO_ACCEL)

.PHONY: debug
debug: $(ARCH_DEFAULT_TARGET) $(QEMU_FW_FILE)
$(LOUD)$(QEMU_BASE) $(QEMU_NO_ACCEL) $(QEMU_DEBUG)

.PHONY: attach
attach:
$(LOUD)gdb $(KERNEL_FULL_FILEPATH) -ex "target remote :1234"

binaries: options $(BUILD_TARGETS)

limine-iso-prep: binaries $(LIMINE_BINARIES)
$(LOUD)mkdir -p $(BUILD_DIR)/iso
$(LOUD)cp misc/cross/$(CPU_ARCH)/limine.conf $(ISO_BUILD_DIR)
$(LOUD)cp $(LIMINE_BINARIES)/limine-uefi-cd.bin $(ISO_BUILD_DIR)
$(LOUD)mkdir -p $(ISO_BUILD_DIR)/EFI/BOOT
$(LOUD)cp $(LIMINE_BINARIES)/$(UEFI_BOOT_NAME) $(ISO_BUILD_DIR)/EFI/BOOT/
$(LOUD)cp $(INITDISK_TARGET) $(ISO_BUILD_DIR)
$(LOUD)cp $(KERNEL_TARGET) $(ISO_BUILD_DIR)

limine-iso: limine-iso-prep
$(LOUD)xorriso -as mkisofs --efi-boot limine-uefi-cd.bin -efi-boot-part \
--efi-boot-image --protective-msdos-label $(ISO_TEMP_DIR) -o \
$(ISO_FULL_FILEPATH) $(LOUD_REDIRECT)
$(LOUD)rm -r $(ISO_TEMP_DIR)
@printf "$(C_CYAN)[Build]$(C_RST) Bootable iso generated @ $(ISO_FULL_FILEPATH)\r\n"
@printf "$(C_CYAN)[Build]$(C_RST) If qemu is installed, try it out with 'make run'!\r\n"

#Builds an iso that can be booted via bios or uefi, for x86_64 only.
.PHONY: iso-hybrid
iso-hybrid: binaries $(LIMINE_DIR)
$(LOUD)mkdir -p $(ISO_TEMP_DIR)
$(LOUD)cp misc/cross/$(CPU_ARCH)/limine.cfg $(ISO_TEMP_DIR)
$(LOUD)cp $(LIMINE_DIR)/limine-uefi-cd.bin $(ISO_TEMP_DIR)
$(LOUD)cp $(LIMINE_DIR)/limine-bios-cd.bin $(ISO_TEMP_DIR)
$(LOUD)cp $(LIMINE_DIR)/limine-bios.sys $(ISO_TEMP_DIR)
$(LOUD)mkdir -p $(ISO_TEMP_DIR)/EFI/BOOT
$(LOUD)cp $(LIMINE_DIR)/$(UEFI_BOOT_NAME) $(ISO_TEMP_DIR)/EFI/BOOT/
$(LOUD)cp $(INITDISK_FULL_FILEPATH) $(ISO_TEMP_DIR)
$(LOUD)cp $(KERNEL_FULL_FILEPATH) $(ISO_TEMP_DIR)
$(LOUD)xorriso -as mkisofs -b limine-bios-cd.bin -no-emul-boot -boot-load-size 4 \
-boot-info-table --efi-boot limine-uefi-cd.bin -efi-boot-part \
--efi-boot-image --protective-msdos-label $(ISO_TEMP_DIR) -o \
$(ISO_FULL_FILEPATH) $(LOUD_REDIRECT)
$(LOUD)$(LIMINE_DIR)/limine bios-install $(ISO_FULL_FILEPATH) $(LOUD_REDIRECT)
$(LOUD)rm -r $(ISO_TEMP_DIR)
@printf "$(C_CYAN)[Build]$(C_RST) Bootable iso (hybrid uefi + bios) generated @ $(ISO_FULL_FILEPATH)\r\n"
@printf "$(C_CYAN)[Build]$(C_RST) If qemu is installed, try it out with 'make run'!\r\n"
--efi-boot-image --protective-msdos-label $(ISO_BUILD_DIR) -o \
$(ISO_TARGET) $(LOUD_REDIRECT)
$(LOUD)rm -r $(ISO_BUILD_DIR)
@printf "$(C_CYAN)[Build]$(C_RST) Bootable iso generated @ $(ISO_TARGET)\n"
@printf "$(C_CYAN)[Build]$(C_RST) If qemu is installed, try it out with 'make run'!\n"

$(LIMINE_BINARIES):
$(LOUD)-rm -rf $(VENDOR_CACHE_DIR)/limine
$(LOUD)git clone https://github.com/limine-bootloader/limine.git \
--branch=v8.x-binary --depth 1 $(LIMINE_BINARIES)
$(LOUD)cd $(LIMINE_BINARIES); make all
$(LOUD)touch $@
@printf "$(C_YELLOW)[Cache]$(C_RST) Limine repo cloned from latest v8 release.\r\n"

.PHONY: clean
clean:
$(LOUD)-cd $(PROJ_DIR_LIBS)/np-syslib; $(MAKE) clean-kernel $(SUBMAKE_FLAGS)
$(LOUD)-cd $(PROJ_DIR_LIBS); $(MAKE) clean $(SUBMAKE_FLAGS)
$(LOUD)-cd $(PROJ_DIR_KERNEL); $(MAKE) clean $(SUBMAKE_FLAGS)
$(LOUD)-cd $(PROJ_DIR_DRIVERS); $(MAKE) clean $(SUBMAKE_FLAGS)
$(LOUD)-cd $(PROJ_DIR_INITDISK); $(MAKE) clean $(SUBMAKE_FLAGS)

.PHONY: docs
docs:
$(LOUD)cd $(PROJ_DIR_DOCS); $(MAKE) all $(SUBMAKE_FLAGS)

.PHONY: docs-clean
docs-clean:
$(LOUD)cd $(PROJ_DIR_DOCS); $(MAKE) clean $(SUBMAKE_FLAGS)

# Optional, run/debug/attach targets and qemu interactions.
include misc/RunDebug.mk
38 changes: 0 additions & 38 deletions docs/Building.md

This file was deleted.

15 changes: 13 additions & 2 deletions docs/KernelConfig.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,21 @@
## Command Line Arguments

- `kernel.boot.print_tags`: whether or not to print the contents of the boot protocol responses. This wont disable logging whether the responses were populated or not.
- `kernel.boot.print_cpu_features`: whether or not to dump the supported feature set of the current cpu.
- `kernel.smp.inhibit`: prevents starting additional cores to the BSP. This is from the kernel's perspective, the firmware or bootloader may still bring up additional cores if they are present.
- `kernel.heap.check_bounds`: can enable checking for buffer overruns/underruns within kernel heap. This will use extra memory per-allocation, and has a performance penalty.
- `kernel.heap.trash_after_use`: kernel heap memory is filled with random data after being freed. This incurs a performance penalty to freeing memory but can catch use-after-free bugs.
- `kernel.heap.trash_before_use`: similar to trash_after_use, this helps catch initialization errors with objects allocated on the kernel heap by filling new allocations with random data before returning to the caller.
- `kernel.heap.log_expansion`: emits a log each time the heap expands. This introduces a lot of noise to the logs, but can be useful in some circumstances.
- `kernel.pmm.trash_before_use`: writes junk data to physical before returning it to the caller, similar usage to the heap feature.
- `kernel.pmm.trash_after_use`: writes junk data to physical memory after freeing it, similar usage to the heap feature.
- `kernel.timer.dump_calibration_data`: dumps raw timer calibration data, not useful on all platforms, but can be helpful for diagnosing time-related issues.
- `kernel.clock.uptime_freq`: overrides the default frequency of the global uptime counter. This only affects the timestamps of logs and not clock event expiry times.
- `kernel.enable_magic_panic_key`: allows using the magic key combo followed by the `p` key to panic the kernel, useful for testing.
- `kernel.enable_magic_shutdown_key`: similar to above, pressing the magic key combo followed by the `s` key will cause the kernel to exit, and attempt to shutdown the system.
- `kernel.enable_all_magic_keys`: enables all the above magic key actions, useful for debugging or in trusted environments.
- `kernel.scheduler.priorities`: allows overriding the number of scheduler priorities used.
- `kernel.log.no_fb_output`: prevent the logging subsystem from spawning terminal emulators on any detected framebuffers, bootloader or runtime.

## Pre-processor Defines

- `NPK_HAS_KERNEL`: defined if code is being compiled as part of the kernel.
- `NPK_HAS_KASAN`: defined (to any value) if the kernel is being compiled with kasan.
Loading

0 comments on commit a0442a4

Please sign in to comment.