cmake_minimum_required(VERSION 4.0)
project(WindowGlfwGlLib CXX C)

include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
include(CheckIPOSupported)
check_ipo_supported(RESULT IS_IPO_SUPPORTED OUTPUT IPO_OUTPUT_VERBOSE)

find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
find_package(glfw3 CONFIG REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(Jemalloc REQUIRED IMPORTED_TARGET GLOBAL jemalloc)

set(COMPILE_FLAGS
        -pipe
        -march=native
        -mtune=native
        -Wall
        -Wextra
        -Winline
        -pedantic
        -pedantic-errors
        -Wnrvo
)

set(COMPILE_OPTIMIZED_FLAGS
        -fno-plt
        -fuse-ld=mold
        -funroll-loops
        -ffunction-sections
        -fdata-sections
        -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free
)

set(LINKER_OPTIONS
        -Wl,--sort-common,--as-needed
)

set(LINKER_OPTIMIZED_OPTIONS
        -Wl,--gc-sections
        -fuse-ld=mold
)
if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
    set(COMPILE_FLAGS -stdlib=libc++ ${COMPILE_FLAGS})
    set(LINKER_FLAGS ${LINKER_FLAGS} c++)

    set(COMPILE_OPTIMIZED_FLAGS ${COMPILE_OPTIMIZED_FLAGS} -fwhole-program-vtables)
    set(LINKER_OPTIMIZED_OPTIONS ${LINKER_OPTIMIZED_OPTIONS} -fwhole-program-vtables)
elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
    set(LINKER_FLAGS ${LINKER_FLAGS} stdc++)

    set(COMPILE_OPTIMIZED_FLAGS ${COMPILE_OPTIMIZED_FLAGS} -fdevirtualize-at-ltrans)
    set(LINKER_OPTIMIZED_OPTIONS ${LINKER_OPTIMIZED_OPTIONS} -fdevirtualize-at-ltrans)
endif ()

add_library(${PROJECT_NAME} STATIC)
target_sources(${PROJECT_NAME}
        PRIVATE
        src/window.cpp
        src/opengl_context.cpp
        src/context_window.cpp

        PUBLIC
        FILE_SET public_headers
        TYPE HEADERS
        BASE_DIRS include/
        FILES
        include/opengl_context.hpp
        include/window.hpp
        include/context_window.hpp
        include/basic_data.hpp
)
target_precompile_headers(${PROJECT_NAME} PUBLIC include/window.hpp include/basic_data.hpp include/context_window.hpp)
target_compile_definitions(${PROJECT_NAME} PUBLIC GLFW_INCLUDE_NONE)
target_compile_options(${PROJECT_NAME} PUBLIC ${COMPILE_FLAGS} $<$<CONFIG:Release>:${COMPILE_OPTIMIZED_FLAGS}>)
target_link_options(${PROJECT_NAME} PUBLIC ${LINKER_OPTIONS} $<$<CONFIG:Release>:${LINKER_OPTIMIZED_OPTIONS}>)
target_link_libraries(${PROJECT_NAME} PUBLIC $<$<CONFIG:Release>:PkgConfig::Jemalloc> OpenGL::GL GLEW::GLEW glfw)

set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 23 CXX_EXTENSIONS OFF UNITY_BUILD ON)
if (IS_IPO_SUPPORTED)
    set_property(TARGET ${PROJECT_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE)
else ()
    message(WARNING "IPO is not supported: ${IPO_OUTPUT_VERBOSE}")
endif ()

install(TARGETS ${PROJECT_NAME}
        EXPORT windowGlfwGlLibTargets
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
        INCLUDES DESTINATION include
        FILE_SET public_headers DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/windowGlfwGlLib"
)

install(EXPORT windowGlfwGlLibTargets
        FILE windowGlfwGlLibTargets.cmake
        NAMESPACE windowGlfwGlLibTargets::
        DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/windowGlfwGlLibTargets
)

configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
        "${CMAKE_CURRENT_BINARY_DIR}/windowGlfwGlLibTargetsConfig.cmake"
        INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/windowGlfwGlLibTargets
)

install(FILES
        "${CMAKE_CURRENT_BINARY_DIR}/windowGlfwGlLibTargetsConfig.cmake"
        DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/windowGlfwGlLibTargets
)
