cmake_minimum_required(VERSION 3.18)
project(krylov_gmres VERSION 0.1.0 LANGUAGES CXX)

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

option(KRYLOV_BUILD_TESTS "Build krylov unit tests" ON)

# 避免 Eigen / spdlog 把自己的测试注册进 CTest
set(BUILD_TESTING OFF CACHE BOOL "" FORCE)
set(EIGEN_BUILD_TESTING OFF CACHE BOOL "" FORCE)
set(EIGEN_BUILD_DOC OFF CACHE BOOL "" FORCE)

# ---------------- 第三方依赖 ----------------
include(FetchContent)

FetchContent_Declare(
    eigen
    GIT_REPOSITORY https://aliyun.mayblog.top/devtools/eigen.git
    GIT_TAG 3.4.0
)

FetchContent_Declare(
    spdlog
    GIT_REPOSITORY https://aliyun.mayblog.top/devtools/spdlog.git
    GIT_TAG v1.11.0
)

# Eigen 是 header-only，避免 add_subdirectory 把其庞大测试集带进 CTest
FetchContent_GetProperties(eigen)
if(NOT eigen_POPULATED)
    FetchContent_Populate(eigen)
endif()
add_library(Eigen3_Eigen INTERFACE)
target_include_directories(Eigen3_Eigen INTERFACE ${eigen_SOURCE_DIR})
add_library(Eigen3::Eigen ALIAS Eigen3_Eigen)

FetchContent_MakeAvailable(spdlog)

# ---------------- 通用 logger 库（与 krylov 解耦，可独立复用） ----------------
add_library(logger STATIC
    src/logger/logger.cpp
)
target_include_directories(logger PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}/include
)
target_link_libraries(logger PUBLIC spdlog::spdlog)

# ---------------- Krylov 核心库 ----------------
# 算法实现（arnoldi / gmres ...）集中到 krylov_core。
# 目前仅依赖 Eigen 与通用 logger。
add_library(krylov_core INTERFACE)
target_include_directories(krylov_core INTERFACE
    ${CMAKE_CURRENT_SOURCE_DIR}/include
)
target_link_libraries(krylov_core INTERFACE
    Eigen3::Eigen
    logger
)
add_library(krylov::core ALIAS krylov_core)

# ---------------- 可执行文件 ----------------
add_executable(krylov_solver src/main.cpp)
target_link_libraries(krylov_solver PRIVATE krylov::core)

# ---------------- 测试 ----------------
if(KRYLOV_BUILD_TESTS)
    enable_testing()

    add_executable(test_logger tests/test_logger.cpp)
    target_link_libraries(test_logger PRIVATE krylov::core)
    add_test(NAME test_logger COMMAND test_logger)

    add_executable(test_eigen tests/test_eigen.cpp)
    target_link_libraries(test_eigen PRIVATE krylov::core)
    add_test(NAME test_eigen COMMAND test_eigen)
endif()
