cmake_minimum_required(VERSION 3.20)
project(dewar LANGUAGES C ASM_NASM)

set(CMAKE_C_STANDARD 23)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)

if (NOT DEFINED ARCH)
    set(ARCH "x86_64")
endif()

message(STATUS "Dewar kernel: Building for architecture '${ARCH}'")

set(TERMOS_OBJCOPY objcopy)
if(APPLE)
    find_program(TERMOS_LD_LLD NAMES ld.lld HINTS /usr/local/bin /opt/homebrew/bin REQUIRED)
    find_program(TERMOS_OBJCOPY NAMES llvm-objcopy objcopy HINTS /usr/local/opt/llvm/bin /opt/homebrew/opt/llvm/bin REQUIRED)
    set(CMAKE_C_LINK_FLAGS "")
    set(CMAKE_ASM_NASM_COMPILE_OBJECT
        "<CMAKE_ASM_NASM_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -MD <DEP_FILE> -MT <DEP_TARGET> -f elf64 -o <OBJECT> <SOURCE>")
    set(CMAKE_C_LINK_EXECUTABLE
        "${TERMOS_LD_LLD} <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
endif()


file(GLOB_RECURSE KERNEL_SOURCES CMAKE_CONFIGURE_DEPENDS
    "src/kmain.c"
    
    "src/arch/${ARCH}/*.c"
    "src/arch/${ARCH}/*.asm"

    "src/OS/*.c"
    "src/OS/Exec/*.c"
    "src/OS/Services/*.c"
    "src/lib/*.c"
    "src/IO/*.c"
    "src/VM/*.c"
    "src/FS/*.c"
    
    "Data/*.c"
)

add_executable(kernel ${KERNEL_SOURCES})
set_target_properties(kernel PROPERTIES NASM_OBJ_FORMAT elf64)

target_include_directories(kernel PRIVATE
    "${CMAKE_CURRENT_SOURCE_DIR}/../common"
    "${CMAKE_CURRENT_SOURCE_DIR}/inc"
    "${CMAKE_CURRENT_SOURCE_DIR}/inc/arch/${ARCH}"
    "${CMAKE_CURRENT_SOURCE_DIR}/Data"
)

target_compile_options(kernel PRIVATE
    $<$<COMPILE_LANGUAGE:C>:
        $<$<BOOL:${APPLE}>:--target=x86_64-none-elf>
        -ffreestanding
        -mno-red-zone
        -fno-stack-protector
        -fno-builtin
        -Wall -Wextra
        -mcmodel=kernel
        -g
        -mno-sse -mno-sse2 -msoft-float
    >
    $<$<AND:$<BOOL:${APPLE}>,$<COMPILE_LANGUAGE:ASM>>:--target=x86_64-none-elf>
)

target_link_options(kernel PRIVATE
    -nostdlib
    -static
    -no-pie
    -T "${CMAKE_CURRENT_SOURCE_DIR}/linker.ld"
    -z max-page-size=0x1000 
)

set_target_properties(kernel PROPERTIES 
    OUTPUT_NAME "kernel.elf"
    RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
)

add_custom_command(TARGET kernel POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E env
        "PATH=/usr/local/opt/llvm/bin:/opt/homebrew/opt/llvm/bin:$ENV{PATH}"
        llvm-objcopy -O binary $<TARGET_FILE:kernel> $<TARGET_FILE_DIR:kernel>/kernel.bin
    COMMENT "Generating raw binary kernel.bin..."
)