# Copyright (c) 1998 Lawrence Livermore National Security, LLC and other
# HYPRE Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)


####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() #######
####### Any changes to this file will be overwritten by the next CMake run ####
####### The input file was HYPREConfig.cmake.in                            ########

get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../../../../../" ABSOLUTE)

macro(set_and_check _var _file)
  set(${_var} "${_file}")
  if(NOT EXISTS "${_file}")
    message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !")
  endif()
endmacro()

macro(check_required_components _NAME)
  foreach(comp ${${_NAME}_FIND_COMPONENTS})
    if(NOT ${_NAME}_${comp}_FOUND)
      if(${_NAME}_FIND_REQUIRED_${comp})
        set(${_NAME}_FOUND FALSE)
      endif()
    endif()
  endforeach()
endmacro()

####################################################################################

include(CMakeFindDependencyMacro)
# Temporarily clear CMAKE_FIND_PACKAGE_NAME to avoid warning when FindPkgConfig
# calls find_package_handle_standard_args internally
set(_old_find_package_name_top "${CMAKE_FIND_PACKAGE_NAME}")
unset(CMAKE_FIND_PACKAGE_NAME)
include(FindPkgConfig)
if(DEFINED _old_find_package_name_top)
  set(CMAKE_FIND_PACKAGE_NAME "${_old_find_package_name_top}")
else()
  unset(CMAKE_FIND_PACKAGE_NAME)
endif()

function(find_hypre_dependency name)
  string(TOUPPER ${name} UPPER_NAME)
  if(HYPRE_ENABLE_${UPPER_NAME})
    # 1) Try CMake package config non-fatally
    find_package(${name} CONFIG QUIET HINTS ${HYPRE_DEPENDENCY_DIRS})
    if(${name}_FOUND)
      message(STATUS "Found ${UPPER_NAME} (CMake package).")
      return()
    endif()

    # 2) Fallback to pkg-config
    # Note: FindPkgConfig is already included at the top level
    set(_pc_name "${name}")
    if("${UPPER_NAME}" STREQUAL "DSUPERLU")
      set(_pc_name "superlu_dist")
    endif()
    if(DEFINED TPL_${UPPER_NAME}_PKGCONFIG_NAME)
      set(_pc_name "${TPL_${UPPER_NAME}_PKGCONFIG_NAME}")
    endif()

    if(PKG_CONFIG_FOUND)
      # Seed PKG_CONFIG_PATH from HYPRE_DEPENDENCY_DIRS
      set(_old_pc_path "$ENV{PKG_CONFIG_PATH}")
      set(_pc_hints)
      foreach(_d IN LISTS HYPRE_DEPENDENCY_DIRS)
        if(EXISTS "${_d}/pkgconfig")
          list(APPEND _pc_hints "${_d}/pkgconfig")
        endif()
        get_filename_component(_parent "${_d}" DIRECTORY)
        if(EXISTS "${_parent}/lib/pkgconfig")
          list(APPEND _pc_hints "${_parent}/lib/pkgconfig")
        endif()
        if(EXISTS "${_parent}/lib64/pkgconfig")
          list(APPEND _pc_hints "${_parent}/lib64/pkgconfig")
        endif()
        if(EXISTS "${_parent}/share/pkgconfig")
          list(APPEND _pc_hints "${_parent}/share/pkgconfig")
        endif()
      endforeach()
      list(REMOVE_DUPLICATES _pc_hints)
      if(_pc_hints)
        if(_old_pc_path)
          set(ENV{PKG_CONFIG_PATH} "${_pc_hints}:$ENV{PKG_CONFIG_PATH}")
        else()
          set(ENV{PKG_CONFIG_PATH} "${_pc_hints}")
        endif()
      endif()

      # Temporarily clear CMAKE_FIND_PACKAGE_NAME to avoid warning when pkg_check_modules
      # calls find_package_handle_standard_args internally
      set(_old_find_package_name "${CMAKE_FIND_PACKAGE_NAME}")
      unset(CMAKE_FIND_PACKAGE_NAME)
      pkg_check_modules(PC_${UPPER_NAME} QUIET ${_pc_name})
      if(DEFINED _old_find_package_name)
        set(CMAKE_FIND_PACKAGE_NAME "${_old_find_package_name}")
      else()
        unset(CMAKE_FIND_PACKAGE_NAME)
      endif()

      # Restore PKG_CONFIG_PATH
      set(ENV{PKG_CONFIG_PATH} "${_old_pc_path}")

      if(PC_${UPPER_NAME}_FOUND)
        message(STATUS "Found ${UPPER_NAME} via pkg-config: ${_pc_name}")
        # Ensure an imported target exists matching the link interface recorded at install time
        if(NOT TARGET PkgConfig::PC_${UPPER_NAME})
          add_library(PkgConfig::PC_${UPPER_NAME} INTERFACE IMPORTED)
          # Prefer link flags if provided; otherwise use libraries
          set(_pc_ll "${PC_${UPPER_NAME}_LDFLAGS}")
          if(NOT _pc_ll AND PC_${UPPER_NAME}_LINK_LIBRARIES)
            set(_pc_ll "${PC_${UPPER_NAME}_LINK_LIBRARIES}")
          endif()
          if(PC_${UPPER_NAME}_INCLUDE_DIRS)
            set_target_properties(PkgConfig::PC_${UPPER_NAME}
              PROPERTIES
                INTERFACE_INCLUDE_DIRECTORIES "${PC_${UPPER_NAME}_INCLUDE_DIRS}")
          endif()
          if(_pc_ll)
            # It is OK if these contain full paths or -l/-L flags
            set_target_properties(PkgConfig::PC_${UPPER_NAME}
              PROPERTIES
                INTERFACE_LINK_LIBRARIES "${_pc_ll}")
          endif()
        endif()
        return()
      endif()
    endif()

    message(FATAL_ERROR "${UPPER_NAME} not found (no CMake package or pkg-config entry).")
  endif()
endfunction()

set(HYPRE_DEPENDENCY_DIRS "")
set(HYPRE_ENABLE_BIGINT OFF)
set(HYPRE_ENABLE_MIXEDINT OFF)
set(HYPRE_ENABLE_SINGLE OFF)
set(HYPRE_ENABLE_LONG_DOUBLE OFF)
set(HYPRE_ENABLE_COMPLEX OFF)
set(HYPRE_ENABLE_MIXED_PRECISION OFF)
set(HYPRE_ENABLE_HYPRE_BLAS ON)
set(HYPRE_ENABLE_HYPRE_LAPACK ON)
set(HYPRE_ENABLE_PERSISTENT_COMM OFF)
set(HYPRE_ENABLE_FEI OFF)
set(HYPRE_ENABLE_MPI OFF)
set(HYPRE_ENABLE_OPENMP ON)
set(HYPRE_ENABLE_HOPSCOTCH OFF)
set(HYPRE_ENABLE_PRINT_ERRORS OFF)
set(HYPRE_ENABLE_TIMING OFF)
set(HYPRE_ENABLE_HOST_MEMORY ON)
set(HYPRE_ENABLE_TEST_USING_HOST OFF)
set(HYPRE_ENABLE_CUDA OFF)
set(HYPRE_ENABLE_HIP OFF)
set(HYPRE_ENABLE_SYCL OFF)
set(HYPRE_ENABLE_UNIFIED_MEMORY OFF)
set(HYPRE_ENABLE_CUDA_STREAMS ON)
set(HYPRE_ENABLE_DEVICE_MALLOC_ASYNC OFF)
set(HYPRE_ENABLE_THRUST_NOSYNC OFF)
set(HYPRE_ENABLE_CUSPARSE ON)
set(HYPRE_ENABLE_CUBLAS ON)
set(HYPRE_ENABLE_CURAND ON)
set(HYPRE_ENABLE_CUSOLVER ON)
set(HYPRE_ENABLE_GPU_AWARE_MPI OFF)
set(HYPRE_ENABLE_GPU_PROFILING OFF)
set(HYPRE_ENABLE_ROCSPARSE ON)
set(HYPRE_ENABLE_ROCBLAS ON)
set(HYPRE_ENABLE_ROCRAND ON)
set(HYPRE_ENABLE_ROCSOLVER ON)
set(HYPRE_ENABLE_ONEMKLSPARSE OFF)
set(HYPRE_ENABLE_ONEMKLBLAS OFF)
set(HYPRE_ENABLE_ONEMKLRAND OFF)
set(HYPRE_ENABLE_FPE_TRAP OFF)
set(HYPRE_BUILD_EXAMPLES OFF)
set(HYPRE_BUILD_TESTS OFF)
set(HYPRE_ENABLE_DSUPERLU OFF)
set(HYPRE_ENABLE_MAGMA OFF)
set(HYPRE_ENABLE_CALIPER OFF)
set(HYPRE_ENABLE_UMPIRE OFF)
set(HYPRE_ENABLE_UMPIRE_HOST OFF)
set(HYPRE_ENABLE_UMPIRE_DEVICE OFF)
set(HYPRE_ENABLE_UMPIRE_UM OFF)
set(HYPRE_ENABLE_UMPIRE_PINNED OFF)
set(HYPRE_HAVE_MPI_COMM_F2C )

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")

if (UNIX)
  list(APPEND TPL_LIBRARIES m)
endif()

if(NOT HYPRE_ENABLE_HYPRE_BLAS)
  find_dependency(BLAS)
endif()

if(NOT HYPRE_ENABLE_HYPRE_LAPACK)
  find_dependency(LAPACK)
endif()

# Synthesize BLAS::BLAS if module only provided BLAS_LIBRARIES
if(NOT HYPRE_ENABLE_HYPRE_BLAS)
  if(NOT TARGET BLAS::BLAS AND DEFINED BLAS_LIBRARIES AND BLAS_LIBRARIES)
    add_library(BLAS::BLAS INTERFACE IMPORTED)
    set_target_properties(BLAS::BLAS PROPERTIES
      INTERFACE_LINK_LIBRARIES "${BLAS_LIBRARIES}")
  endif()
endif()

# Synthesize LAPACK::LAPACK if module only provided LAPACK_LIBRARIES
if(NOT HYPRE_ENABLE_HYPRE_LAPACK)
  if(NOT TARGET LAPACK::LAPACK AND DEFINED LAPACK_LIBRARIES AND LAPACK_LIBRARIES)
    add_library(LAPACK::LAPACK INTERFACE IMPORTED)
    set_target_properties(LAPACK::LAPACK PROPERTIES
      INTERFACE_LINK_LIBRARIES "${LAPACK_LIBRARIES}")
  endif()
endif()

if(HYPRE_ENABLE_MPI)
  enable_language(C)
  find_dependency(MPI  COMPONENTS C)
endif()

if(HYPRE_ENABLE_OPENMP)
  find_dependency(OpenMP)
endif()

find_hypre_dependency(caliper)
find_hypre_dependency(dsuperlu)
find_hypre_dependency(magma)
find_hypre_dependency(umpire)

if(HYPRE_ENABLE_CUDA OR HYPRE_ENABLE_HIP OR HYPRE_ENABLE_SYCL)
  # List of required GPU libraries
  set(REQUIRED_GPU_COMPONENTS)

  if(HYPRE_ENABLE_CUDA)
    list(APPEND REQUIRED_GPU_COMPONENTS cudart)
    if(HYPRE_ENABLE_CUSPARSE)
      list(APPEND REQUIRED_GPU_COMPONENTS cusparse)
    endif()

    if(HYPRE_ENABLE_CUBLAS)
      list(APPEND REQUIRED_GPU_COMPONENTS cublas)
    endif()

    if(HYPRE_ENABLE_CURAND)
      list(APPEND REQUIRED_GPU_COMPONENTS curand)
    endif()

    if(HYPRE_ENABLE_CUSOLVER)
      list(APPEND REQUIRED_GPU_COMPONENTS cusolver)
    endif()
  elseif(HYPRE_ENABLE_HIP)
    if(HYPRE_ENABLE_ROCSPARSE)
      list(APPEND REQUIRED_GPU_COMPONENTS rocsparse)
    endif()

    if(HYPRE_ENABLE_ROCBLAS)
      list(APPEND REQUIRED_GPU_COMPONENTS rocblas)
    endif()

    if(HYPRE_ENABLE_ROCRAND)
      list(APPEND REQUIRED_GPU_COMPONENTS rocrand)
    endif()

    if(HYPRE_ENABLE_ROCSOLVER)
      list(APPEND REQUIRED_GPU_COMPONENTS rocsolver)
    endif()
  elseif(HYPRE_ENABLE_SYCL)
    if(HYPRE_ENABLE_ONEMKLSPARSE)
      list(APPEND REQUIRED_GPU_COMPONENTS onemklsparse)
    endif()

    if(HYPRE_ENABLE_ONEMKLBLAS)
      list(APPEND REQUIRED_GPU_COMPONENTS onemklblas)
    endif()

    if(HYPRE_ENABLE_ONEMKLRAND)
      list(APPEND REQUIRED_GPU_COMPONENTS onemklrand)
    endif()
  endif()

  if(REQUIRED_GPU_COMPONENTS)
    if(HYPRE_ENABLE_CUDA)
      set(GPU_TOOLKIT_NAME "CUDA")
      message(STATUS "Finding CUDA Toolkit components: ${REQUIRED_GPU_COMPONENTS}")
      find_dependency(CUDAToolkit REQUIRED COMPONENTS ${REQUIRED_GPU_COMPONENTS})
      set(GPU_TOOLKIT_FOUND ${CUDAToolkit_FOUND})
      set(GPU_TOOLKIT_VERSION ${CUDAToolkit_VERSION})

    elseif(HYPRE_ENABLE_HIP)
      # Add HIP root to prefix path to find ROCm components
      if(DEFINED ROCM_PATH)
        set(HIP_PATH ${ROCM_PATH})
      elseif(DEFINED ENV{ROCM_PATH})
        set(HIP_PATH $ENV{ROCM_PATH})
      elseif(DEFINED rocm_ROOT)
        set(HIP_PATH ${rocm_ROOT})
      elseif(DEFINED ENV{ROCM_ROOT})
        set(HIP_PATH $ENV{ROCM_ROOT})
      elseif(DEFINED hip_ROOT)
        set(HIP_PATH ${hip_ROOT})
      elseif(DEFINED ENV{hip_ROOT})
        set(HIP_PATH $ENV{hip_ROOT})
      elseif(EXISTS "/opt/rocm")
        set(HIP_PATH "/opt/rocm")
      else()
        message(WARNING "ROCM_PATH or HIP_PATH not set. Linking to ROCm libraries may not work.")
      endif()

      # Add HIP path to prefix path to find ROCm components
      list(APPEND CMAKE_PREFIX_PATH "${HIP_PATH}")

      set(GPU_TOOLKIT_NAME "HIP")
      message(STATUS "Finding HIP Toolkit components: ${REQUIRED_GPU_COMPONENTS}")
      find_dependency(hip REQUIRED)
      set(GPU_TOOLKIT_FOUND ${hip_FOUND})
      set(GPU_TOOLKIT_VERSION ${hip_VERSION})

      # Find ROCm components
      foreach(component ${REQUIRED_GPU_COMPONENTS})
        find_dependency(${component} REQUIRED)
      endforeach()

    elseif(HYPRE_ENABLE_SYCL)
      set(GPU_TOOLKIT_NAME "IntelSYCL")
      message(STATUS "Finding IntelSYCL Toolkit components: ${REQUIRED_GPU_COMPONENTS}")
      find_dependency(IntelSYCL REQUIRED)
      set(GPU_TOOLKIT_FOUND ${IntelSYCL_FOUND})
      set(GPU_TOOLKIT_VERSION ${IntelSYCL_VERSION})
    endif()

    if(GPU_TOOLKIT_FOUND)
      message(STATUS "GPU Toolkit found: ${GPU_TOOLKIT_NAME} ${GPU_TOOLKIT_VERSION}")
      set(MISSING_COMPONENTS)
      foreach(component ${REQUIRED_GPU_COMPONENTS})
        if(HYPRE_ENABLE_CUDA AND NOT TARGET CUDA::${component})
          list(APPEND MISSING_COMPONENTS ${component})
        elseif(HYPRE_ENABLE_HIP AND NOT TARGET roc::${component})
          list(APPEND MISSING_COMPONENTS ${component})
        elseif(HYPRE_ENABLE_SYCL AND NOT TARGET sycl::${component})
          list(APPEND MISSING_COMPONENTS ${component})
        endif()
      endforeach()
      if(MISSING_COMPONENTS)
        message(FATAL_ERROR "Required GPU components not found: ${MISSING_COMPONENTS}")
      else()
        message(STATUS "Required GPU components found: ${REQUIRED_GPU_COMPONENTS}")
      endif()
    else()
      message(FATAL_ERROR "GPU Toolkit not found.")
    endif()
  endif()
endif()

# Ensure BLAS::BLAS exists in consumer scope (some platforms/modules only set variables)
if(NOT TARGET BLAS::BLAS)
  # Try to find a proper imported target first
  find_package(BLAS QUIET)
  if(NOT TARGET BLAS::BLAS)
    add_library(BLAS::BLAS INTERFACE IMPORTED)
    if(DEFINED BLAS_LIBRARIES AND BLAS_LIBRARIES)
      # Use detected library list
      set_target_properties(BLAS::BLAS PROPERTIES
        INTERFACE_LINK_LIBRARIES "${BLAS_LIBRARIES}")
    else()
      # Last resort: assume a plain 'blas' link is available
      set_target_properties(BLAS::BLAS PROPERTIES
        INTERFACE_LINK_LIBRARIES "blas")
    endif()
  endif()
endif()

# Ensure LAPACK::LAPACK exists in consumer scope
if(NOT TARGET LAPACK::LAPACK)
  find_package(LAPACK QUIET)
  if(NOT TARGET LAPACK::LAPACK)
    add_library(LAPACK::LAPACK INTERFACE IMPORTED)
    if(DEFINED LAPACK_LIBRARIES AND LAPACK_LIBRARIES)
      set_target_properties(LAPACK::LAPACK PROPERTIES
        INTERFACE_LINK_LIBRARIES "${LAPACK_LIBRARIES}")
    else()
      set_target_properties(LAPACK::LAPACK PROPERTIES
        INTERFACE_LINK_LIBRARIES "lapack")
    endif()
  endif()
endif()

include("${CMAKE_CURRENT_LIST_DIR}/HYPRETargets.cmake")
