﻿# CMakeList.txt : Top-level CMake project file, do global configuration
# and include sub-projects here.
#
cmake_minimum_required (VERSION 3.10)

list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/tools/cmake)
include(SubDirList)

get_filename_component(PROJECT_DIR ${CMAKE_CURRENT_SOURCE_DIR} NAME)
string(REPLACE " " "_" PROJECT_DIR ${PROJECT_DIR})
project(${PROJECT_DIR})

set(PROJECT_VERSION_MAJOR 0)
set(PROJECT_VERSION_MINOR 1)
set(PROJECT_VERSION_PATCH 0)
set(PROJECT_VERSION_BRANCH "N/A")
set(PROJECT_VERSION_COMMIT "N/A")

# Get the current working branch
execute_process(
    COMMAND git rev-parse --abbrev-ref HEAD
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    OUTPUT_VARIABLE PROJECT_VERSION_BRANCH
    OUTPUT_STRIP_TRAILING_WHITESPACE)
    
# Get the latest commit hash
execute_process(
        COMMAND git rev-parse --short HEAD
        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
        OUTPUT_VARIABLE PROJECT_VERSION_COMMIT
        OUTPUT_STRIP_TRAILING_WHITESPACE)

set(PROJECT_VERSION_FULL ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}-${PROJECT_VERSION_BRANCH}-${PROJECT_VERSION_COMMIT})

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE}/bin)

set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/install)

set(CMAKE_CACHEFILE_DIR ${CMAKE_SOURCE_DIR}/build)

include(CTest)
enable_testing()

set(CMAKE_CXX_STANDARD 20)
set(CPACK_PROJECT_NAME ${${PROJECT_NAME}_NAME})
set(CPACK_PROJECT_VERSION ${${PROJECT_NAME}_VERSION})
include(CPack)

option(${PROJECT_NAME}_BUILD_ENGINE "Build engine library" ON)
option(${PROJECT_NAME}_BUILD_APPS "Build supplimentary applications" ON)
option(${PROJECT_NAME}_BUILD_DEPS "Build dependencies" ON)

option(ONLY_COVERAGE "Build only tests necessary for coverage" OFF)
option(LIBCPP "Build with libc++" OFF)
option(ENABLE_COVERAGE "Enable coverage reporting for gcc/clang" OFF)
option(ENABLE_ASAN "Enable address sanitizer" OFF)
option(BUILD_SHARED_LIBS "Enable compilation of shared libraries" OFF)
option(ENABLE_TESTING "Enable the building of the test" OFF)
option(ENABLE_CLANG_TIDY "Enable testing with clang-tidy" OFF)
option(ENABLE_CPPCHECK "Enable testing with cppcheck" OFF)
option(SIMPLE_BUILD "Build the project as minimally as possible" OFF)
option(BUILD_DOC "Build the project's documentation" OFF)
option(FORCE_COLORED_OUTPUT "Always produce ANSI-colored output (GNU/Clang only)." OFF)
option(DEBUG_LOGGING "Enabling debug logging" OFF)

add_library(project_warnings INTERFACE)
add_library(project_options INTERFACE)

if(ONLY_COVERAGE OR ENABLE_COVERAGE)
    target_compile_options(project_options INTERFACE --coverage -O0 -g)
    target_link_libraries(project_options INTERFACE --coverage)
endif()

if(ENABLE_ASAN)
    target_compile_options(project_options INTERFACE -fsanitize=address)
    target_link_libraries(project_options INTERFACE -fsanitize=address)
endif()

if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
    target_compile_options(project_warnings
        INTERFACE
        -Wall
        -Wextra
        -Wshadow
        -Wnon-virtual-dtor
        -Wold-style-cast
        -Wcast-align
        -Wunused
        -Woverloaded-virtual
        -Wpedantic
        -Wconversion
        -Wsign-conversion
        -Wnull-dereference
        -Wdouble-promotion
        -Wformat=2)
endif()

# some GCC specific warnings. These flags are added only if the used compiler is GCC.
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
    target_compile_options(project_warnings
        INTERFACE
        -Wmisleading-indentation
        -Wduplicated-cond
        -Wlogical-op
        -Wuseless-cast
        )
    target_link_libraries(project_options INTERFACE stdc++fs)
endif()

if (${FORCE_COLORED_OUTPUT})
    if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
        target_compile_options(project_options INTERFACE -fdiagnostics-color=always)
    elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
        target_compile_options(project_options INTERFACE -fcolor-diagnostics)
    endif ()
endif ()

find_program(CCACHE ccache)
if(CCACHE)
    set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE})
endif()

if(ENABLE_CPPCHECK)
    find_program(CPPCHECK cppcheck)
    if(CPPCHECK)
    set(CMAKE_CXX_CPPCHECK
        ${CPPCHECK}
        --suppress=syntaxError
        --enable=all
        --inconclusive)
    else()
    message(SEND_ERROR "cppcheck requested but executable not found")
    endif()
endif()

if(ENABLE_CLANG_TIDY)
    find_program(CLANGTIDY clang-tidy)
    if(CLANGTIDY)
    set(CMAKE_CXX_CLANG_TIDY ${CLANGTIDY})
    else()
    message(SEND_ERROR "clang-tidy requested but executable not found")
    endif()
endif()

if(BUILD_DOC)
    find_package(Doxygen)
    if (DOXYGEN_FOUND)
                SET(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile.in)
                SET(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)

                configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)

                add_custom_target(doc ALL
                        COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
                        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
                        COMMENT "Buidling Doxygen documentation"
                        VERBATIM )
    else (DOXYGEN_FOUND)
                message("No doxygen binary found on the system.")
                SET(${BUILD_DOC} OFF)
    endif ()
endif()

message(STATUS "")
message(STATUS "Summary")
#message(STATUS "")
#message(STATUS "Build libs:       \t ${${PROJECT_NAME}_BUILD_DEPS}")
#message(STATUS "Build src:     \t ${${PROJECT_NAME}_BUILD_ENGINE}")
message(STATUS "")
message(STATUS "Build type:       \t ${CMAKE_BUILD_TYPE}")
message(STATUS "Install prefix:   \t ${CMAKE_INSTALL_PREFIX}")
message(STATUS "Testing enabled:  \t ${ENABLE_TESTING}")
message(STATUS "Clang-tidy:       \t ${ENABLE_CLANG_TIDY}")
message(STATUS "Cppcheck:         \t ${ENABLE_CPPCHECK}")
message(STATUS "Compiler:         \t ${CMAKE_CXX_COMPILER_ID}")
message(STATUS "Sanizizers:       \t ${ENABLE_ASAN}")
message(STATUS "Shared libs:      \t ${BUILD_SHARED_LIBS}")
message(STATUS "Build libcpp:     \t ${LIBCPP}")
message(STATUS "CCache executable:\t ${CCACHE}")
message(STATUS "Building doc:     \t ${BUILD_DOC}")
message(STATUS "Force color output:\t ${FORCE_COLORED_OUTPUT}")
message(STATUS "")
message(STATUS "Version:          \t ${${PROJECT_NAME}_VERSION}")
message(STATUS "")

add_subdirectory("libs")
add_subdirectory("srcs")
