## CMake
cmake_minimum_required(VERSION 3.14)


## Project
set(PROJECT_NAME glfbo3d)
if ("${CMAKE_PROJECT_NAME}" STREQUAL "${PROJECT_NAME}")
    return()
endif()
project(${PROJECT_NAME}
    VERSION 1.0.0
    LANGUAGES CXX
)
set(CXX_STANDARD          11)
set(CXX_STANDARD_REQUIRED ON)
set(CXX_EXTENSIONS        OFF)


## Packages
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
find_package(glm REQUIRED)


## External projects
include(FetchContent)
FetchContent_Declare(glshader
    GIT_REPOSITORY https://git.rcrnstn.net/rcrnstn/glshader
)
FetchContent_Declare(gltest
    GIT_REPOSITORY https://git.rcrnstn.net/rcrnstn/gltest
)
FetchContent_MakeAvailable(
    glshader
    gltest
)


## Main target
add_library(${PROJECT_NAME}
    src/${PROJECT_NAME}.cpp
    include/${PROJECT_NAME}.hpp
)
set_property(TARGET ${PROJECT_NAME} PROPERTY PUBLIC_HEADER
    include/${PROJECT_NAME}.hpp
)
target_include_directories(${PROJECT_NAME}
    PUBLIC
        $<INSTALL_INTERFACE:include>
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    PRIVATE
        src
)
target_link_libraries(${PROJECT_NAME}
    PUBLIC
        OpenGL::GL
        GLEW::GLEW
)


if ("${CMAKE_PROJECT_NAME}" STREQUAL "${PROJECT_NAME}")


    ## Test target
    add_executable(${PROJECT_NAME}-test
        tests/${PROJECT_NAME}.cpp
    )
    target_include_directories(${PROJECT_NAME}-test
        PRIVATE
            tests
    )
    target_link_libraries(${PROJECT_NAME}-test
        PRIVATE
            ${PROJECT_NAME}
            OpenGL::GL
            GLEW::GLEW
            glm
            glshader
            gltest
    )
    add_test(
        NAME    ${PROJECT_NAME}-test
        COMMAND ${PROJECT_NAME}-test
        WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
    )


    ## Default build type for single-configuration generators
    if (NOT CMAKE_BUILD_TYPE)
        set(CMAKE_BUILD_TYPE Debug)
    endif()


    ## Language tools and options
    set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
    find_program(CPPCHECK             cppcheck)
    find_program(CLANG_TIDY           clang-tidy)
    find_program(INCLUDE_WHAT_YOU_USE include-what-you-use)
    if(CPPCHECK)
        set(CXX_CPPCHECK ${CPPCHECK} --enable=warning,style --error-exitcode=1)
    endif()
    if(CLANG_TIDY)
        set(CXX_CLANG_TIDY ${CLANG_TIDY})
    endif()
    if(INCLUDE_WHAT_YOU_USE)
        set(CXX_INCLUDE_WHAT_YOU_USE ${INCLUDE_WHAT_YOU_USE})
    endif()
    if (MSVC)
        set(COMPILE_OPTIONS
            /permissive-
            /WX
            /W4
        )
    elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|.*Clang")
        set(COMPILE_OPTIONS
            -pedantic
            -Werror -Wfatal-errors
            -Wall -Wextra
            -Wconversion -Wsign-conversion
            -Wdouble-promotion
            -Wimplicit-fallthrough
            -Wvla
            -Wzero-as-null-pointer-constant
            -Weffc++
        )
        set(SANITIZE_OPTIONS
            $<$<CONFIG:Debug>:-fsanitize=address,leak,undefined>
        )
        list(APPEND COMPILE_OPTIONS ${SANITIZE_OPTIONS})
        list(APPEND LINK_OPTIONS    ${SANITIZE_OPTIONS})
    endif()
    include(CheckIPOSupported)
    check_ipo_supported(RESULT INTERPROCEDURAL_OPTIMIZATION)
    get_directory_property(BUILDSYSTEM_TARGETS BUILDSYSTEM_TARGETS)
    set_target_properties(
        ${BUILDSYSTEM_TARGETS}
        PROPERTIES
            CXX_STANDARD             "${CXX_STANDARD}"
            CXX_STANDARD_REQUIRED    "${CXX_STANDARD_REQUIRED}"
            CXX_EXTENSIONS           "${CXX_EXTENSIONS}"
            CXX_CPPCHECK             "${CXX_CPPCHECK}"
            CXX_CLANG_TIDY           "${CXX_CLANG_TIDY}"
            CXX_INCLUDE_WHAT_YOU_USE "${CXX_INCLUDE_WHAT_YOU_USE}"
            COMPILE_OPTIONS          "${COMPILE_OPTIONS}"
            LINK_OPTIONS             "${LINK_OPTIONS}"
            INTERPROCEDURAL_OPTIMIZATION
                "${INTERPROCEDURAL_OPTIMIZATION}"
    )


    ## Testing
    include(CTest)


    ## Packaging and installing
    include(CPack)
    install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME})
    include(GNUInstallDirs)
    set(CMAKE_INSTALL_CMAKEDIR ${CMAKE_INSTALL_LIBDIR}/cmake
        CACHE PATH "System CMake package config files"
    )
    install(EXPORT ${PROJECT_NAME}
        FILE ${PROJECT_NAME}Config.cmake
        DESTINATION ${CMAKE_INSTALL_CMAKEDIR}/${PROJECT_NAME}
    )
    include(CMakePackageConfigHelpers)
    write_basic_package_version_file(${PROJECT_NAME}ConfigVersion.cmake
        COMPATIBILITY SameMajorVersion
    )
    install(
        FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
        DESTINATION ${CMAKE_INSTALL_CMAKEDIR}/${PROJECT_NAME}
    )


endif()