From 788ca8b1c0a6adf323fba8d1489c4f6c6aedc589 Mon Sep 17 00:00:00 2001 From: Hannes Date: Sun, 26 Oct 2025 15:20:37 +0100 Subject: [PATCH] Makefile --- Makefile | 314 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 314 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b45ba1f --- /dev/null +++ b/Makefile @@ -0,0 +1,314 @@ +# +# Kurzanleitung +# ============= +# +# +++ General Targets +++ +# +# make -- siehe -> make all +# +# make all -- Baut kernel.elf und generiert einen dump +# +# make install -- Baut kernel.img und transferiert ihn auf den Server. +# Das Board holt sich diesen Kernel beim nächsten Reset. +# +# make qemu -- Baut den Kernel und führt ihn unter QEMU aus +# +# make qemu_debug -- Baut den Kernel und führt ihn unter QEMU mit debug +# Optionen aus. Zum debuggen in einem zweiten Terminal +# folgendes ausführen: +# $ arm-none-eabi-gdb build/kernel.elf +# $ target remote localhost:1234 +# make qemu_trace -- Wie qemu, gibt aber zusätzlich bei bestimmten MMIO-Zugriffen +# Meldungen aus +# make qemu_trace_mmu -- Wie qemu_trace, gibt aber nur Meldungen zur MMU aus +# +# make gdb -- Startet gdb und verbindet sich mit qemu +# +# make gdb_window -- Führt `make gdb` in einem neuen terminal aus +# +# make debug -- Führt qemu_debug gdb_window aus +# +# make clean -- Löscht alle erzeugten Dateien. +# +# make format -- Formatiert alle .c und .h Dateien im Stil von kernel.org +# +# make submission -- Verpackt alle Dateien die von git getrackt sind +# Hierbei wird immer der Branch genutzt, der unter +# SUBMISSION_BRANCH eingetragen ist. +# +# make home -- kopiert das fertige image nach $TFTP_PATH, für die +# Arbeit zuhause einfach den Pfad eintragen +# +# +++ Single File Targets +++ +# +# make kernel -- Baut kernel.elf im build Ordner +# +# make kernel.bin -- Baut kernel.bin im build Ordner +# +# make kernel.img -- Baut kernel.img im build Ordner +# +# make kernel_only -- Baut den kernel aber nur mit den Dateien aus SRC +# Zum testen, ob der Kernel unabhängig kompiliert +# +# make user_only -- Baut nur die User Dateien aus USRC +# Zum testen, ob Userland unabhängig kompiliert +# +# +++ Sonstiges +++ +# +# MODE=strict make TARGET -- Baut TARGET mit allen Warnings, die GCC +# -- unterstütz, sowie undefined behaviour sanitzers. +# -- Baut nicht alles neu, d.h. im Zweifel zuerst +# -- make clean ausführen. +# +# make qemu_record -- Erstellt eine "Aufnahme" einer Ausführung des OS. +# Diese kann mit qemu_replay, qemu_debug_replay, +# und debug_replay zum debugging abgespielt werden. +# Dabei ist es dann in GDB möglich mit reverse-stepi +# und reverse-continue "rückwärts" zu debuggen. + +# Binäre Lsg (falls verwendet, ansonsten leer lassen) +BIN_LSG = + +# Hier eure source files hinzufügen +SRC = arch/cpu/entry.S kernel/start.c arch/bsp/yellow_led.c lib/ubsan.c lib/mem.c + +# Hier separate user source files hinzufügen +USRC = user/main.c + +# Hier können eigene GCC flags mit angegeben werden. +# Die vorgegebenen Flags können weiter unten gefunden werden unter +# CFLAGS_ALL und dürfen nicht verändert werden +# Bsp: CFLAGS = -Wpedantic -Werror -O2 +CFLAGS = -std=gnu23 + +# 'strict' Modus +ifeq ($(MODE), strict) + CFLAGS_AVAIL = $(shell $(CC) -Q --help=warning | sed -e 's/^\s*\(\-\S*\)\s*\[\w*\]/\1 /gp;d' | tr -d '\n') $(CFLAGS_LAX) + IGNORED_CFLAGS = -Wabi -Wc90-c99-compat -Wc99-c11-compat -Wc++-compat -Wtraditional \ + -Wtraditional-conversion -Wold-style-declaration -Wold-style-definition \ + -Wlong-long -Wdeclaration-after-statement -Wmain -Wswitch-default -Wstrict-flex-arrays \ + -Wsystem-headers + CFLAGS_STRICT = $(filter-out $(IGNORED_CFLAGS), $(CFLAGS_AVAIL)) + + CFLAGS += $(CFLAGS_STRICT) -Werror + CFLAGS += -fsanitize=undefined +endif + +# Gleiches gilt für Linkerflags, solltet ihr bspw. die libgcc mitlinken müssen +LDFLAGS = + +# Hier den git branch angeben, der für die Abgabe benutzt werden soll +SUBMISSION_BRANCH = main + +# Wenn ihr zuhause auf der Hardware arbeitet, hier das TFTP-Verzeichnis eintragen +TFTP_PATH = /srv/tftp + +# Standardinstallationspunkt der Toolchain +-include config.mk + +# Default if not defined in config.mk +PREFIX ?= $(HOME)/Nextcloud/UNI/25-26_TI/BSP/arm + +all: + echo $(PREFIX) + +# +-----------------------------------------------------+ +# | | +# | Ab hier nichts mehr anpassen! Änderungen unter- | +# | halb dieses Banners führen zu Punktabzug! | +# | | +# +-----------------------------------------------------+ + +# Source files, die fürs Testen einkompiliert werden. +TSRC = +SRC += $(TSRC) + +# build directory +BUILD_DIR = build + +# separate kernel files and add build prefix +KSRC_C = $(filter %.c, $(SRC)) +KSRC_S = $(filter %.S, $(SRC)) +KOBJ_C = $(addprefix $(BUILD_DIR)/,$(KSRC_C:%.c=%.o)) +KOBJ_S = $(addprefix $(BUILD_DIR)/,$(KSRC_S:%.S=%.o)) +KOBJ = $(KOBJ_C) $(KOBJ_S) + +# separate user files and add build prefix +USRC_C = $(filter %.c, $(USRC)) +USRC_S = $(filter %.S, $(USRC)) +UOBJ_C = $(addprefix $(BUILD_DIR)/,$(USRC_C:%.c=%.o)) +UOBJ_S = $(addprefix $(BUILD_DIR)/,$(USRC_S:%.S=%.o)) +UOBJ = $(UOBJ_C) $(UOBJ_S) + +# accumulate +OBJ_C = $(KOBJ_C) $(UOBJ_C) +OBJ_S = $(KOBJ_S) $(UOBJ_S) +OBJ = $(KOBJ) $(UOBJ) + +# all header files +HEADER_FILES = $$(find . -name '*.h') + +# auto generated dep files +DEP = $(OBJ:.o=.d) + +# linker script +LSCRIPT = kernel.lds + +# static lib location for binary solution +BIN_LSG_DIR = ./ + +# toolchain +CC = $(PREFIX)/bin/arm-none-eabi-gcc +LD = $(PREFIX)/bin/arm-none-eabi-ld +OBJCOPY = $(PREFIX)/bin/arm-none-eabi-objcopy +OBJDUMP = $(PREFIX)/bin/arm-none-eabi-objdump +IMG = $(PREFIX)/bin/mkimage +QEMU = $(PREFIX)/bin/qemu-system-arm +QEMU_IMG = $(PREFIX)/bin/qemu-img +GDB = $(PREFIX)/bin/arm-none-eabi-gdb +FORMAT = $(PREFIX)/bin/clang-format + +# configuration +CFLAGS_ALL = -Wall -Wextra -ggdb -ffreestanding -mcpu=cortex-a7 -mfloat-abi=soft -mno-unaligned-access $(CFLAGS) +CPPFLAGS = -Iinclude +LDFLAGS += -T$(LSCRIPT) -nostdlib --fatal-warnings +ifneq ($(BIN_LSG), ) + LDFLAGS += -L$(BIN_LSG_DIR) $(addprefix -l,$(BIN_LSG)) +endif +OBJCOPYFLAGS = -Obinary -S --set-section-flags .bss=contents,alloc,load,data +OBJDUMPFLAGS = -dfzh +IMGFLAGS = -A arm -T standalone -C none -a 0x8000 +QEMUFLAGS = -M raspi2b -nographic -icount shift=9 +QEMU_REPLAY_FLAGS = -icount rrfile=$(BUILD_DIR)/replay.bin + +FORMATFLAGS = --style="file:.clang-format" -i + +# Regeln +.PHONY: all + +# default target +all: kernel dump + +# include auto generated targets +-include $(DEP) + +# single file targets +$(OBJ_S):$(BUILD_DIR)/%.o: %.S + @mkdir -p $(dir $@) + $(CC) $(CPPFLAGS) $(CFLAGS_ALL) -MMD -MP -o $@ -c $< + +$(OBJ_C):$(BUILD_DIR)/%.o: %.c + @mkdir -p $(dir $@) + $(CC) $(CPPFLAGS) $(CFLAGS_ALL) -MMD -MP -o $@ -c $< + +$(BUILD_DIR)/kernel.elf: $(OBJ) $(LSCRIPT) +ifneq ($(words $(OBJ)), $(words $(SRC) $(USRC))) + @echo The number of objects files given to the linker does not match the\ + number of kernel and user files specified. Check your file extensions.; exit 1 +else + $(LD) -o $@ $(wordlist 2,$(words $^),x $^) $(LDFLAGS) +endif + +$(BUILD_DIR)/kernel.bin: $(BUILD_DIR)/kernel.elf + $(OBJCOPY) $(OBJCOPYFLAGS) $< $@ + +$(BUILD_DIR)/kernel.img: $(BUILD_DIR)/kernel.bin + $(IMG) $(IMGFLAGS) -d $< $@ + +$(BUILD_DIR)/kernel_only.elf: $(KOBJ) $(LSCRIPT) + $(LD) -o $@ $(wordlist 2,$(words $^),x $^) $(LDFLAGS) + +$(BUILD_DIR)/user_only.elf: $(UOBJ) $(LSCRIPT) + $(LD) -o $@ $(wordlist 2,$(words $^),x $^) $(LDFLAGS) --entry=0 + +$(BUILD_DIR)/kernel_dump.s: $(BUILD_DIR)/kernel.elf + $(OBJDUMP) $(OBJDUMPFLAGS) $< > $@ + +# aliases +.PHONY: dump kernel kernel.bin kernel.img kernel_only user_only +dump: $(BUILD_DIR)/kernel_dump.s +kernel: $(BUILD_DIR)/kernel.elf +kernel.bin: $(BUILD_DIR)/kernel.bin +kernel.img: $(BUILD_DIR)/kernel.img +kernel_only: $(BUILD_DIR)/kernel_only.elf +user_only: $(BUILD_DIR)/user_only.elf + +# general targets +.PHONY: install home qemu qemu_debug clean submission +install: $(BUILD_DIR)/kernel.img + arm-install-image $(BUILD_DIR)/kernel.img + +home: $(BUILD_DIR)/kernel.img + cp -v $(BUILD_DIR)/kernel.img $(TFTP_PATH) + +$(BUILD_DIR)/vmstate.qcow2: $(BUILD_DIR)/kernel.elf + mkdir -p $(BUILD_DIR) + $(QEMU_IMG) create -f qcow2 $@ 32M + +qemu: $(BUILD_DIR)/kernel.elf + $(QEMU) $(QEMUFLAGS) -kernel $(BUILD_DIR)/kernel.elf + +qemu_record: $(BUILD_DIR)/kernel.elf + $(QEMU) $(QEMUFLAGS) $(QEMU_REPLAY_FLAGS) -icount rr=record -kernel $(BUILD_DIR)/kernel.elf + +qemu_replay: $(BUILD_DIR)/kernel.elf $(BUILD_DIR)/replay.bin + $(QEMU) $(QEMUFLAGS) $(QEMU_REPLAY_FLAGS) -icount rr=replay -kernel $(BUILD_DIR)/kernel.elf + +qemu_debug: $(BUILD_DIR)/kernel.elf + $(QEMU) $(QEMUFLAGS) -s -S -kernel $(BUILD_DIR)/kernel.elf + +qemu_debug_replay: $(BUILD_DIR)/kernel.elf $(BUILD_DIR)/vmstate.qcow2 $(BUILD_DIR)/replay.bin + $(QEMU) $(QEMUFLAGS) $(QEMU_REPLAY_FLAGS) -drive file=$(BUILD_DIR)/vmstate.qcow2,if=none,snapshot=on,id=img-direct -icount rr=replay -s -S -kernel $(BUILD_DIR)/kernel.elf + +qemu_trace: $(BUILD_DIR)/kernel.elf + $(QEMU) $(QEMUFLAGS) -d "trace:bcm283*,trace:pl011*" -kernel $< + +qemu_trace_mmu: $(BUILD_DIR)/kernel.elf + $(QEMU) $(QEMUFLAGS) -d "mmu" -kernel $< + +gdb: $(BUILD_DIR)/kernel.elf + $(GDB) --ex="target remote localhost:1234" --ex "set scheduler-locking on" $< + +gdb_window: $(BUILD_DIR)/kernel.elf +ifeq (, $(shell which x-terminal-emulator 2>/dev/null)) + @which $(TERM) || { echo "TERM not set properly, please do so, e.g. with 'export TERM=xterm'"; exit 1; } + $(TERM) -e "bash -c 'make gdb; killall $(QEMU)'" & +else + x-terminal-emulator -e "make gdb; killall $(QEMU)" & +endif + +debug: gdb_window qemu_debug + +debug_replay: gdb_window qemu_debug_replay + +format: + @$(FORMAT) $(FORMATFLAGS) $$(find . -name '*.c' -o -name '*.h') + @echo "Finished reformatting code." + +clean: + rm -rf $(BUILD_DIR) + +CURR_BRANCH = $(shell git branch --show-current 2> /dev/null) +STATUS_BRANCH = "$(shell git status --porcelain 2> /dev/null)" + +submission: +ifneq ($(CURR_BRANCH), $(SUBMISSION_BRANCH)) + @echo "Refusing to create submission!" + @echo "Current branch does not match submission branch." + @echo " > Currently on branch: '$(CURR_BRANCH)'" + @echo " > But registered submission branch is: '$(SUBMISSION_BRANCH)'" + @echo "Please change branch or fix submission branch." + @exit 1 +endif +ifneq ($(STATUS_BRANCH), "") + @echo "Refusing to create submission!" + @echo "Submission branch is dirty or contains untracked files." + @echo "" + @echo "Please commit changes and add non essential files to '.gitignore'." + @echo "Use 'git status' for a detailed list." + @echo "" + @exit 1 +endif + git archive --format=tar.gz -o submission.tar.gz $(SUBMISSION_BRANCH) + @echo Successfully created submission.tar.gz + @echo We recommend testing archive before submitting it.