KERNEL_EXEC := socks_kernel

SOCKS_ARCH ?= x86_64

MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
ROOT_DIR := $(patsubst %/,%,$(dir $(MAKEFILE_PATH)))

include tools/make/gcc-cross-compile.mk

BUILD_DIR := build
CONFIG_DIR := .config

####################################
# If the user has selected some kernel extensions to include
# in the kernel image, include the file that describes the
# extension source files to build
####################################

-include $(CONFIG_DIR)/extensions.mk

####################################
# Architecture-specific source files
####################################

include arch/$(SOCKS_ARCH)/config.mk

####################################
# Platform-independent kernel source files
####################################

KERNEL_SRC_DIRS := init kernel vm ds util obj sched dev test kxld
KERNEL_C_FILES := $(foreach dir,$(KERNEL_SRC_DIRS),$(wildcard $(dir)/*.c))
KERNEL_CXX_FILES := $(foreach dir,$(KERNEL_SRC_DIRS),$(wildcard $(dir)/*.cpp))
KERNEL_OBJ := $(addprefix $(BUILD_DIR)/,$(KERNEL_C_FILES:.c=.o) $(KERNEL_CXX_FILES:.cpp=.o))

####################################
# Kernel libc source files
####################################

LIBC_SRC_DIRS := stdio string ctype
LIBC_C_FILES := $(foreach dir,$(LIBC_SRC_DIRS),$(wildcard libc/$(dir)/*.c))
LIBC_OBJ := $(addprefix $(BUILD_DIR)/,$(LIBC_C_FILES:.c=.o))

BUILD_ID := $(shell tools/socks.buildid --arch $(SOCKS_ARCH))

CWARNINGS := -Wall -Werror -pedantic -Wno-language-extension-token -Wno-unused-function  -Wno-gnu-statement-expression

OPTIMISATION_LEVEL := -O2

CFLAGS := $(CFLAGS) -DBUILD_ID=\"$(BUILD_ID)\" $(OPTIMISATION_LEVEL) -g -fPIC -std=gnu17 \
	-Iinclude -Iarch/$(SOCKS_ARCH)/include -Ilibc/include $(CWARNINGS)

KERNEL_DEFINES := -DSOCKS_INTERNAL=1

CXXFLAGS := $(CXXFLAGS) -DBUILD_ID=\"$(BUILD_ID)\" $(OPTIMISATION_LEVEL) -g -fPIC -std=gnu++17 \
	-Iinclude -Iarch/$(SOCKS_ARCH)/include -Ilibc/include -Wno-language-extension-token $(CWARNINGS)

ASMFLAGS := $(ASMFLAGS) -DBUILD_ID=\"$(BUILD_ID)\"
LDFLAGS := $(LDFLAGS) -g -lgcc $(OPTIMISATION_LEVEL)

ALL_KERNEL_OBJECT_FILES := $(KERNEL_OBJ) $(ARCH_OBJ) $(LIBC_OBJ) $(INTERNAL_KEXT_OBJ)
ALL_KERNEL_DEPS := $(ALL_KERNEL_OBJECT_FILES:.o=.d)

all: $(BUILD_DIR)/$(KERNEL_EXEC) tools

-include $(ALL_KERNEL_DEPS)

$(BUILD_DIR)/$(KERNEL_EXEC): $(ALL_KERNEL_OBJECT_FILES)
	@printf "    \033[1;36mLD\033[0m     \033[1mbuild/\033[35m$(KERNEL_EXEC)\033[0m\n"
	@mkdir -p $(@D)
	@$(LD) $^ -o $@ $(LDFLAGS) $(ARCH_LDFLAGS)
	@cp $@ $@.dbg
	@$(STRIP) $@

$(BUILD_DIR)/%.o: %.S
	@printf "    \033[1;32mAS\033[0m     \033[35m$(KERNEL_EXEC)\033[0m/$<\n"
	@mkdir -p $(@D)
	@$(ASM) $< -o $@ -c $(ASMFLAGS) $(ARCH_ASMFLAGS) -MMD

$(BUILD_DIR)/%.o: %.c
	@printf "    \033[1;32mCC\033[0m     \033[35m$(KERNEL_EXEC)\033[0m/$<\n"
	@mkdir -p $(@D)
	@$(CC) $< -o $@ -c $(CFLAGS) $(ARCH_CFLAGS) -MMD $(KERNEL_DEFINES)

$(BUILD_DIR)/%.o: %.cpp
	@printf "    \033[1;32mCXX\033[0m    \033[35m$(KERNEL_EXEC)\033[0m/$<\n"
	@mkdir -p $(@D)
	@$(CXX) $< -o $@ -c $(CXXFLAGS) $(ARCH_CFLAGS) -MMD $(KERNEL_DEFINES)

clean:
	@printf "    \033[1;93mRM\033[0m     Deleting build files.\n"
	@rm -rf $(BUILD_DIR)

$(BUILD_DIR)/compile_commands.json:
	@printf "    \033[1;93mGEN\033[0m    Generating compiler database.\n"

	@./tools/socks.compiledb

cd: $(BUILD_DIR)/socks-kernel.iso

install-cd: $(BUILD_DIR)/socks-kernel.iso
	@./tools/socks.install-cd

compile-db: $(BUILD_DIR)/compile_commands.json

tools:
	@$(MAKE) --no-print-directory -C tools

include arch/$(SOCKS_ARCH)/extra.mk

.PHONY: all tools compile-db $(BUILD_DIR)/compile_commands.json

.INTERMEDIATE: $(ARCH_TEMP_FILES)
