project(yak-kernel)

# Configure global options
set(CMAKE_SYSROOT "/does-not-exist")
set(CMAKE_SYSTEM_NAME yak)
set(CMAKE_SYSTEM_PROCESSOR x86_64)
set(CMAKE_CROSSCOMPILING 1)

if (NOT ${CMAKE_C_COMPILER_ID} STREQUAL "Clang")
    message(WARNING "Only clang is supported, not ${CMAKE_C_COMPILER_ID}")
endif ()

# Define global options
option(USE_DEBUG "Enable debug code" ON)
option(USE_LIMINE "Enable support for the limine boot protocol" ON)

# Find builtins
list(APPEND BUILTINS_SEARCH /usr/lib/clang/${CLANG_VERSION_MAJOR}/lib/linux /usr/lib/clang/${CMAKE_C_COMPILER_VERSION}/lib/linux)
find_library(BUILTINS_LIB
        libclang_rt.builtins-x86_64.a
        PATHS ${BUILTINS_SEARCH})

# Set compiler options
add_compile_options(
        -ffreestanding
        -fno-lto
        -fno-pie
        -fno-pic
        -m64
        --target=x86_64-pc-none-eabi
        -mno-80387
        -mno-mmx
        -mno-sse
        -mno-sse2
        -mno-red-zone
        -mcmodel=kernel
)
add_link_options(
        -nostdlib
        -static
        -z max-page-size=0x1000
        -T ${CMAKE_CURRENT_SOURCE_DIR}/linker.lds
)

# add printf library for complete printf functionality
FetchContent_Declare(printf_library
        GIT_REPOSITORY https://github.com/eyalroz/printf.git
        GIT_TAG v6.1.0)
FetchContent_GetProperties(printf_library)
if (NOT printf_library_POPULATED)
    FetchContent_Populate(printf_library)
endif ()


# Validate options
if (NOT ${USE_LIMINE})
    message(FATAL_ERROR "At least one boot protocol is required")
endif ()

# Find sources
file(GLOB KERNEL_SOURCES
        src/rt/*.c
        src/ulibc/*.c)
file(GLOB_RECURSE KERNEL_CORE_SOURCES
        src/rt/core/**.c)
file(GLOB PLATFORM_GENERIC_SOURCES src/platform/generic/*.c)

if (${USE_DEBUG})
    add_definitions(-DUSE_DEBUG)
    file(GLOB DEBUG_KERNEL_SOURCES src/rt/debug/*.c)
endif ()
if (${USE_LIMINE})
    add_definitions(-DUSE_LIMINE)
    file(GLOB LIMINE_KERNEL_SOURCES src/rt/boot/limine/*.c)
endif ()
if (NOT IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/${CMAKE_SYSTEM_PROCESSOR})
    message(FATAL_ERROR "Unknown architecture ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/${CMAKE_SYSTEM_PROCESSOR}")
endif ()

file(GLOB_RECURSE PLATFORM_SPECIFIC_SOURCES src/platform/${CMAKE_SYSTEM_PROCESSOR}/*.c)
file(GLOB_RECURSE PLATFORM_SPECIFIC_ASM_SOURCES src/platform/${CMAKE_SYSTEM_PROCESSOR}/*.asm)

file(GLOB CRTI src/platform/generic/crt/crti.c)
file(GLOB CRTN src/platform/generic/crt/crtn.c)

file(GLOB_RECURSE PYTHON_GENERATORS src/**/*.generator.py)


foreach (GENERATOR IN LISTS PYTHON_GENERATORS)
    get_filename_component(GENERATED_BARE ${GENERATOR} NAME_WE)
    add_custom_command(
            COMMAND python3 ${GENERATOR}
            OUTPUT ${GENERATED_BARE}.c
            COMMENT "Generates ${GENERATED_BARE}.c"
    )
    list(APPEND GENERATED_SOURCES ${GENERATED_BARE}.c)
endforeach ()


# Define aggregate sources
set(KERNEL_SOURCE_FILES
        ${KERNEL_SOURCES}
        ${KERNEL_CORE_SOURCES}
        ${LIMINE_KERNEL_SOURCES}
        ${DEBUG_KERNEL_SOURCES}
        ${PLATFORM_GENERIC_SOURCES}
        ${PLATFORM_SPECIFIC_SOURCES}
        ${PLATFORM_SPECIFIC_ASM_SOURCES}
        ${GENERATED_SOURCES}
)

# Define executable
add_executable(yak.elf ${CRTI} ${KERNEL_SOURCE_FILES} ${CRTN})
target_link_libraries(yak.elf PRIVATE ${BUILTINS_LIB})
target_include_directories(yak.elf PRIVATE include ../limine/include ${printf_library_SOURCE_DIR}/src)
