cmake_minimum_required(VERSION 3.22...3.31)

set(CMAKE_POLICY_DEFAULT_CMP0091 NEW)   # Respect CMAKE_MSVC_RUNTIME_LIBRARY

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

include(GitVersion)

gitversion_set_version(DUNE_VERSION v)

project(dunelegacy
	VERSION 0.96.4
	LANGUAGES CXX C
)
if(APPLE)
    enable_language(OBJC)
endif()

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_DEBUG OFF)

if(CMAKE_BUILD_TYPE)
    message(STATUS "CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}")
    set(build_list ${CMAKE_BUILD_TYPE})
elseif(CMAKE_CONFIGURATION_TYPES)
    message(STATUS "CMAKE_CONFIGURATION_TYPES ${CMAKE_CONFIGURATION_TYPES}")
    set(build_list ${CMAKE_CONFIGURATION_TYPES})
endif()

add_compile_definitions($<$<CONFIG:Debug>:DEBUG>)

option(DUNE_PRECOMPILED_HEADERS "Use precompiled headers" ON)
if(DUNE_PRECOMPILED_HEADERS)
    message(STATUS "Enabling precompiled headers")
endif()

option(DUNE_ASAN "Enable ASAN")
if(DUNE_ASAN)
    include(setup/asan-setup)
endif()

option(DUNE_ASAN "Enable UBSAN")
if(DUNE_UBSAN)
    include(setup/ubsan-setup)
endif()

if(WIN32)
    include(setup/win32-setup)
endif()

if(MSVC)
    include(setup/msvc-setup)
endif()

if(APPLE)
    include(setup/macos-setup)
endif()

if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    include(setup/clang-gcc-setup)
endif()

include(create-harden-interface)

include(CheckFeatures)

if(DUNE_TARGET_ARCHITECTURE)
    if (DUNE_TARGET_ARCHITECTURE STREQUAL "x64" OR DUNE_TARGET_ARCHITECTURE STREQUAL "x86_64")
        check_cxx_source_compiles(
            "#if !defined(__x86_64__) && !defined(_M_X64)
            #error \"Invalid architecture\"
            #endif
            int main(int argc, const char* argv[]) { }
            "
            DUNE_TARGET_MATCHES)
    elseif(DUNE_TARGET_ARCHITECTURE STREQUAL "x86")
        check_cxx_source_compiles(
            "#if !defined(__i386__) && !defined(_M_IX86)
            #error \"Invalid architecture\"
            #endif
            int main(int argc, const char* argv[]) { }
            "
            DUNE_TARGET_MATCHES)
    elseif(DUNE_TARGET_ARCHITECTURE STREQUAL "arm64")
        check_cxx_source_compiles(
            "#if !defined(__aarch64__) && !defined(_M_ARM64)
            #error \"Invalid architecture\"
            #endif
            int main(int argc, const char* argv[]) { }
            "
            DUNE_TARGET_MATCHES)
    endif()
    if(DUNE_TARGET_MATCHES)
    else()
        message(WARNING "Target architecture \"${DUNE_TARGET_ARCHITECTURE}\" doesn't match the compiler output.")
    endif()
endif()

# googletest and the #define "new" used for heap debugging don't get along.

if(DUNE_CRT_HEAP_DEBUG)
    set(ENABLE_TESTS OFF)
else()
    set(ENABLE_TESTS ON)
endif()

option(DUNE_ENABLE_TESTS "Enable tests" "${ENABLE_TESTS}")

if(DUNE_ENABLE_TESTS)
    message(STATUS "Enabling tests")
    enable_testing()
else()
    message(STATUS "Skipping tests")
endif()

if(COMMAND gitversion_create_target)
  gitversion_create_target(dune_gitversion)
endif()

add_subdirectory(external)
add_subdirectory(src)
add_subdirectory(data)

if(DUNE_ENABLE_TESTS)
    add_subdirectory(tests)
endif()

install(FILES README DESTINATION .)

set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF)

if(WIN32)
    if(TARGET_MSI_NAME)
        set(CPACK_PACKAGE_FILE_NAME "${TARGET_MSI_NAME}")
    else()
        set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${DUNE_TARGET_ARCHITECTURE}")
    endif()
endif()

include(CPack)

message(STATUS "              CMAKE_C_FLAGS: ${CMAKE_C_FLAGS}")
message(STATUS "            CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
message(STATUS "     CMAKE_EXE_LINKER_FLAGS: ${CMAKE_EXE_LINKER_FLAGS}")
message(STATUS "       VCPKG_TARGET_TRIPLET: ${VCPKG_TARGET_TRIPLET}")

if(CMAKE_MSVC_RUNTIME_LIBRARY)
    message(STATUS "               MSVC Runtime: ${CMAKE_MSVC_RUNTIME_LIBRARY}")
endif()

foreach(config ${build_list})
    string(TOUPPER "${config}" config)

    message(STATUS "              CMAKE_C_FLAGS_${config}: ${CMAKE_C_FLAGS_${config}}")
    message(STATUS "            CMAKE_CXX_FLAGS_${config}: ${CMAKE_CXX_FLAGS_${config}}")
    message(STATUS "     CMAKE_EXE_LINKER_FLAGS_${config}: ${CMAKE_EXE_LINKER_FLAGS_${config}}")
endforeach()

get_directory_property(COMPILE_OPTIONS COMPILE_OPTIONS)
get_directory_property(LINK_OPTIONS LINK_OPTIONS)

message(STATUS "            COMPILE_OPTIONS: ${COMPILE_OPTIONS}")
message(STATUS "               LINK_OPTIONS: ${LINK_OPTIONS}")

message(STATUS "  DUNE_TARGET_COMPILE_FLAGS: ${DUNE_TARGET_COMPILE_FLAGS}")
