cmake_minimum_required(VERSION 3.25.2 FATAL_ERROR)
cmake_policy(VERSION 3.25.2)

include(cmake/version.cmake)

project(opnic-sdk VERSION ${QM_OPNIC_CMAKE_VERSION} LANGUAGES C CXX)

set(QM_OPNIC_MASTER_PROJECT OFF)
if (${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_SOURCE_DIR})
    set(QM_OPNIC_MASTER_PROJECT ON)
else (if ${QM_OPNIC_ENABLE_INSTALL} STREQUAL "ON")
    set(QM_OPNIC_MASTER_PROJECT ON)
endif ()

option(QM_BUILD_TEST "Build the tests" OFF)
option(QM_BUILD_INSTALL "Generate the install script" ${QM_OPNIC_MASTER_PROJECT})
option(QM_NO_CUDA "Disable CUDA support" OFF)
option(QM_MOCK_DRIVER "Mocks the opnic driver for unit tests" OFF)

include(GNUInstallDirs)

set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

file(GLOB_RECURSE CORE_HEADER opnic/*.hpp)
file(GLOB_RECURSE STREAM_CONF_SOURCE opnic/stream/configurators/*.cpp)

file(GLOB_RECURSE CUDA_UTIL_SOURCE opnic/utils/*.cu)
file(GLOB_RECURSE UTIL_SOURCE opnic/utils/*.cpp)

configure_file(
        "${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.cpp.in"
        "${CMAKE_CURRENT_BINARY_DIR}/opnic/version.cpp"
        @ONLY
)

file(GLOB_RECURSE VERSION_SOURCE "${CMAKE_CURRENT_BINARY_DIR}/opnic/version.cpp")

set(MINIMUM_GCC_VERSION "13.0")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS MINIMUM_GCC_VERSION)
        message(FATAL_ERROR "GCC version must be at least ${MINIMUM_GCC_VERSION}, found: ${CMAKE_CXX_COMPILER_VERSION}")
    else ()
        message(STATUS "Found GCC version ${CMAKE_CXX_COMPILER_VERSION}")
    endif ()
endif ()

if (QM_MOCK_DRIVER)
    add_compile_definitions(QM_MOCK_DRIVER)
else ()
    include(cmake/check_opnic_driver.cmake)

    if (NOT OPNIC_DRIVER_INSTALLED)
        message(FATAL_ERROR "This project requires the opnic driver to be installed")
    endif ()
endif ()

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

include(cmake/targets/opnic.cmake)
if (NOT QM_NO_CUDA)
    include(cmake/targets/opnic-cuda.cmake)
endif ()

if (QM_BUILD_TEST)
    enable_testing()
    add_subdirectory(tests)
endif ()

if (QM_BUILD_INSTALL)
    if (QM_NO_CUDA)
        install(TARGETS opnic
                EXPORT opnic-targets
                LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
                ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
                RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
                FILE_SET HEADERS DESTINATION include
                FILE_SET headers_gen DESTINATION include
        )
    else ()
        install(TARGETS opnic opnic-cuda
                EXPORT opnic-targets
                LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
                ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
                RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
                FILE_SET HEADERS DESTINATION include
                FILE_SET headers_gen DESTINATION include
        )
    endif ()

    install(EXPORT opnic-targets
            FILE opnic-targets.cmake
            NAMESPACE qm::
            DESTINATION share/opnic
    )

    include(CMakePackageConfigHelpers)
    write_basic_package_version_file(
            "${CMAKE_CURRENT_BINARY_DIR}/opnic-config-version.cmake"
            VERSION ${QM_OPNIC_VERSION}
            COMPATIBILITY SameMajorVersion
    )

    configure_package_config_file(
            "cmake/opnic-config.cmake.in"
            "${CMAKE_CURRENT_BINARY_DIR}/opnic-config.cmake"
            INSTALL_DESTINATION share/opnic
    )

    install(
            FILES
            "${CMAKE_CURRENT_BINARY_DIR}/opnic-config.cmake"
            "${CMAKE_CURRENT_BINARY_DIR}/opnic-config-version.cmake"
            DESTINATION share/opnic
    )

    install(
            FILES
            "cmake/check_opnic_driver.cmake"
            DESTINATION share/opnic
    )
    configure_file(
            "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall_opnic.cmake.in"
            "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall_opnic.cmake"
            IMMEDIATE @ONLY
    )

    add_custom_target(
            uninstall
            "${CMAKE_COMMAND}" -P
            "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall_opnic.cmake"
    )
endif ()

