cmake_minimum_required(VERSION 3.20)
project(sangi
    VERSION 0.1.0
    DESCRIPTION "Modern C++23 comprehensive math library"
    LANGUAGES CXX
)

# ==============================================================================
# C++ standard and global settings
# ==============================================================================
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# Enable folder display in Solution Explorer
set_property(GLOBAL PROPERTY USE_FOLDERS ON)

# Avoid generate.stamp contention during VS "Rebuild All"
# Disables the stamp check that CMake embeds into each .vcxproj.
# Because all projects in the same directory try to touch the same
# generate.stamp simultaneously, causing a file lock conflict (MSB8066).
# Note: when CMakeLists.txt changes, you must re-run cmake manually.
set(CMAKE_SUPPRESS_REGENERATION ON)

# ==============================================================================
# Options
# ==============================================================================
option(SANGI_USE_MKL "Enable Intel MKL backend" OFF)
option(SANGI_BUILD_SHARED "Build sangi_core as shared library (DLL)" OFF)
option(BUILD_TESTING "Build tests" OFF)

# ==============================================================================
# Compiler-specific flags
# ==============================================================================
if(MSVC)
    add_compile_options(
        /utf-8              # UTF-8 support (UTF-8 source + execution charset)
        /EHsc               # C++ exception model
        /W3                 # Warning level 3
        /Zc:__cplusplus     # Set __cplusplus macro to the actual C++ standard version
    )
    # AVX2 on x64 only (ARM excluded)
    if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT CMAKE_SYSTEM_PROCESSOR MATCHES "ARM")
        add_compile_options(/arch:AVX2)
    endif()
else()
    # GCC / Clang
    add_compile_options(-Wall)
    include(CheckCXXCompilerFlag)
    check_cxx_compiler_flag(-mavx2 COMPILER_SUPPORTS_AVX2)
    if(COMPILER_SUPPORTS_AVX2)
        add_compile_options(-mavx2 -mfma -mbmi2 -madx)
    endif()
endif()

# ==============================================================================
# MKL (optional)
# ==============================================================================
if(SANGI_USE_MKL)
    # Search via MKLROOT environment variable or system path
    find_package(MKL QUIET)
    if(NOT MKL_FOUND AND DEFINED ENV{MKLROOT})
        set(MKL_INCLUDE_DIR "$ENV{MKLROOT}/include")
        set(MKL_LIB_DIR "$ENV{MKLROOT}/lib")
        if(EXISTS "${MKL_INCLUDE_DIR}/mkl.h")
            set(MKL_FOUND TRUE)
            message(STATUS "MKL found via MKLROOT: $ENV{MKLROOT}")
        endif()
    endif()
    if(NOT MKL_FOUND)
        message(WARNING "MKL not found. Building without MKL support.")
        set(SANGI_USE_MKL OFF)
    endif()
endif()

# ==============================================================================
# Subdirectories
# ==============================================================================
add_subdirectory(lib)

add_subdirectory(examples)

# ==============================================================================
# Public-source curation guard (ctest)
# ==============================================================================
# Detects regressions in the bundled public source: pro/secret material leaking
# in, or un-bundled dependencies. Pure CMake (cmake -P), so it runs on `ctest`
# anywhere without extra tooling and never affects normal builds.
enable_testing()
add_test(
    NAME public_source_audit
    COMMAND ${CMAKE_COMMAND}
            -DSANGI_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}
            -P ${CMAKE_CURRENT_SOURCE_DIR}/tools/audit_public_source.cmake
)
