cmake_minimum_required(VERSION 3.12)
project(laplacian C)

# Disallow in-source builds
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
   message(FATAL_ERROR "In-source builds are not allowed. Please create a separate build directory and run CMake from there.")
endif()

set(CMAKE_C_STANDARD 99)

# Add the cmake folder to the module path
#list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../cmake")

# Check if we're building as part of the main project
if(NOT TARGET HYPREDRV::HYPREDRV)
    # Standalone build - try to find installed HYPREDRV
    find_package(HYPREDRV REQUIRED)
endif()

# Common build configuration
add_executable(laplacian laplacian.c)
target_link_libraries(laplacian PRIVATE HYPREDRV::HYPREDRV)
hypredrv_add_hypre_build_dependency(laplacian)
if(COMMAND hypredrv_set_relative_install_rpath)
    hypredrv_set_relative_install_rpath(laplacian)
endif()

# If Caliper is enabled, we need to link C++ standard library (Caliper is C++)
if(HYPREDRV_ENABLE_CALIPER)
    enable_language(CXX OPTIONAL)
    if(CMAKE_CXX_COMPILER)
        if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
            target_link_libraries(laplacian PRIVATE stdc++)
        elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
            # Clang can use either libstdc++ or libc++
            # Default to stdc++ on Linux
            if(UNIX AND NOT APPLE)
                target_link_libraries(laplacian PRIVATE stdc++)
            else()
                target_link_libraries(laplacian PRIVATE c++)
            endif()
        endif()
    endif()
endif()

# Add opt-in OpenMP support for parallel assembly
if(NOT COMMAND hypredrv_link_example_omp)
    include("${CMAKE_CURRENT_LIST_DIR}/../../../cmake/HYPREDRV_Platform.cmake")
endif()
hypredrv_link_example_omp(laplacian)

# Apply sanitizer link flags if sanitizers are enabled
get_property(_sanitizer_enabled GLOBAL PROPERTY HYPREDRV_SANITIZER_ENABLED)
get_property(_sanitizer_flags GLOBAL PROPERTY HYPREDRV_SANITIZER_LINK_FLAGS)
if(_sanitizer_enabled AND _sanitizer_flags)
    foreach(flag IN LISTS _sanitizer_flags)
        target_link_options(laplacian PRIVATE ${flag})
    endforeach()
endif()

# Add an RPATH to the lib directory for MacOS (libraries are in lib/)
if(APPLE)
    target_link_options(laplacian PRIVATE  "-Wl,-rpath,${CMAKE_BINARY_DIR}/lib")
endif()

# Add the laplacian driver to the test suite when testing is enabled
if(HYPREDRV_ENABLE_TESTING)
    include(${CMAKE_SOURCE_DIR}/cmake/HYPREDRV_Testing.cmake)

    # 7-point stencil tests (default)
    add_executable_test(laplacian_7pt_test_1proc laplacian 1
        ARGS -n 6 6 6 -s 7 -ns 1 -v 1
        RUN_SERIAL
    )
    add_executable_test(laplacian_7pt_test_4proc laplacian 4
        ARGS -n 6 6 6 -P 2 2 1 -s 7 -ns 1 -v 1
    )

    # 19-point stencil tests
    add_executable_test(laplacian_19pt_test_1proc laplacian 1
        ARGS -n 6 6 6 -s 19 -ns 1 -v 1
        RUN_SERIAL
    )
    add_executable_test(laplacian_19pt_test_4proc laplacian 4
        ARGS -n 6 6 6 -P 2 2 1 -s 19 -ns 1 -v 1
    )

    # 27-point stencil tests
    add_executable_test(laplacian_27pt_test_1proc laplacian 1
        ARGS -n 6 6 6 -s 27 -ns 1 -v 1
        RUN_SERIAL
    )
    add_executable_test(laplacian_27pt_test_4proc laplacian 4
        ARGS -n 6 6 6 -P 2 2 1 -s 27 -ns 1 -v 1
    )

    # 125-point stencil tests
    add_executable_test(laplacian_125pt_test_1proc laplacian 1
        ARGS -n 6 6 6 -s 125 -ns 1 -v 1
        RUN_SERIAL
    )
    add_executable_test(laplacian_125pt_test_4proc laplacian 4
        ARGS -n 6 6 6 -P 2 2 1 -s 125 -ns 1 -v 1
    )

    # Hypredrive CLI override pass-through test (-a requires -i)
    set(_laplacian_args_yaml "${CMAKE_CURRENT_BINARY_DIR}/laplacian_args.yml")
    file(WRITE "${_laplacian_args_yaml}" "solver: pcg\npreconditioner: amg\n")
    add_executable_test(laplacian_hypredrive_args laplacian 1
        ARGS -n 6 6 6 -s 7 -ns 1 -v 0 -i "${_laplacian_args_yaml}"
             -a --general:statistics on --solver:pcg:print_level 1
        RUN_SERIAL
        REQUIRE_CONTAINS
            "STATISTICS SUMMARY"
    )
endif()

# Install the laplacian example binary when examples are built
install(TARGETS laplacian
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
