PROJECT(Zoltan C CXX Fortran)
CMAKE_MINIMUM_REQUIRED(VERSION 3.10)

SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_ROOT}/Modules)

IF(NOT CMAKE_Fortran_MODULE_DIRECTORY)
  SET(CMAKE_Fortran_MODULE_DIRECTORY
    ${PROJECT_BINARY_DIR}/fmodules CACHE PATH "Directory for Fortran modules")
ENDIF()

INCLUDE(tribits_macros)

# MPI Related things
SET(TPL_ENABLE_MPI TRUE INTERNAL)

IF(NOT WITH_MPI)
  MESSAGE(FATAL_ERROR "Zoltan cannot be built in serial")
ENDIF()


SET(PACKAGE_NAME "Zoltan" CACHE STRING "") # TODO: Should this be internal? Or is this even needed? No. TODO: Remove this.
SET(Zoltan_ENABLE_CXX FALSE CACHE BOOL "")
SET(Zoltan_ENABLE_Fortran TRUE CACHE BOOL "")
SET(BUILD_ZOLTAN_F90_INTERFACE TRUE CACHE BOOL "")
SET(Zoltan_ENABLE_CPPDRIVER FALSE CACHE BOOL "")

SET(${PACKAGE_NAME}_ENABLE_METIS FALSE CACHE STRING "" )

SET(ParMetis_FOUND TRUE)
SET(PARMETISROOT "/usr")

SET(ParMetis_FOUND FALSE)
# If libraries are already defined, do nothing
IF(ParMetis_LIBRARIES AND ParMetis_INCLUDE_DIR)
  SET(ParMetis_FOUND TRUE)
ENDIF()

IF(NOT ParMetis_FOUND)
  MESSAGE(STATUS "Finding ParMetis")

  SET(PARMETISINCLUDE
    "${PARMETISROOT}/include"
    "$ENV{PARMETISROOT}/include"
    "$ENV{PARMETIS_ROOT}/include"
    "${CMAKE_SOURCE_DIR}/parmetis/include"
    INTERNAL)

  # Find include
  SET(PARMETIS_INCLUDENAME "parmetis.h" INTERNAL)
  FIND_PATH(ParMetis_INCLUDE_DIR
    NAMES
    ${PARMETIS_INCLUDENAME}
    HINTS
    ${PARMETISINCLUDE}
    )

  SET(PARMETISLIB
    "${PARMETISROOT}/lib"
    "$ENV{PARMETISROOT}/lib"
    "$ENV{PARMETIS_ROOT}/lib"
    "${CMAKE_SOURCE_DIR}/parmetis/lib"
    INTERNAL)

  # Find library
  FIND_LIBRARY(ParMetis_LIBRARIES
    parmetis
    HINTS
    ${PARMETISLIB}
    )

  IF (ParMetis_LIBRARIES AND ParMetis_INCLUDE_DIR)
    SET(ParMetis_FOUND TRUE)
    MESSAGE(STATUS "ParMetis_FOUND is TRUE in cmake file")
  ENDIF()
ENDIF()

IF(ParMetis_FOUND)
  SET(${PACKAGE_NAME}_ENABLE_ParMETIS TRUE CACHE STRING "" )
  SET(ParMETIS_INCLUDE_DIRS "${ParMetis_INCLUDE_DIR}")
  SET(ParMETIS_LIBRARY_DIRS "${PARMETISLIB}")
  MESSAGE(STATUS "Zoltan ParMetis include dir: ${ParMETIS_INCLUDE_DIRS}")
  MESSAGE(STATUS "Zoltan ParMetis libraries: ${ParMETIS_LIBRARY_DIRS}")  
ELSE()
  SET(${PACKAGE_NAME}_ENABLE_PatMETIS FALSE CACHE STRING "" )
  MESSAGE(STATUS "Zoltan compiling without ParMetis")
ENDIF()
SET(${PACKAGE_NAME}_ENABLE_PaToH FALSE CACHE STRING "" )
SET(${PACKAGE_NAME}_ENABLE_Scotch FALSE CACHE STRING "" )
SET(${PACKAGE_NAME}_ENABLE_OVIS FALSE CACHE STRING "" )
SET(${PACKAGE_NAME}_ENABLE_Zlib FALSE CACHE STRING "" )
SET(${PACKAGE_NAME}_ENABLE_PURIFY FALSE CACHE STRING "" )

IF(WITH_MPI)
  # Advanced properties
  MARK_AS_ADVANCED(
    MPI_EXTRA_LIBRARY
    MPI_LIBRARY
    )
  IF (NOT MPI_FOUND)
    FIND_PACKAGE(MPI REQUIRED)
    # Workaround if MPI is found but MPI_FOUND is not set (windows+msmpi+findmpi)
    SET(MPI_FOUND TRUE CACHE BOOL "")
  ENDIF()
  MARK_AS_ADVANCED(MPI_FOUND)
  INCLUDE_DIRECTORIES(${MPI_Fortran_INCLUDE_PATH})
  # MPI libraries may be needed for testing
  SET(CMAKE_C_REQUIRED_LIBRARIES ${MPI_C_LIBRARIES})
  SET(CMAKE_CXX_REQUIRED_LIBRARIES ${MPI_CXX_LIBRARIES})
  SET(CMAKE_Fortran_REQUIRED_LIBRARIES ${MPI_Fortran_LIBRARIES})
ENDIF(WITH_MPI)

CONFIGURE_FILE("cmake/Zoltan_config.h.in" 
  ${CMAKE_CURRENT_BINARY_DIR}/Zoltan_config.h)


TRIBITS_ADD_OPTION_AND_DEFINE( ${PACKAGE_NAME}_ENABLE_UINT_IDS
  UNSIGNED_INT_GLOBAL_IDS
  "typedef unsigned int ZOLTAN_ID_TYPE"
  OFF )

TRIBITS_ADD_OPTION_AND_DEFINE( ${PACKAGE_NAME}_ENABLE_ULONG_IDS
  UNSIGNED_LONG_GLOBAL_IDS
  "typedef unsigned long ZOLTAN_ID_TYPE"
  OFF )

TRIBITS_ADD_OPTION_AND_DEFINE( ${PACKAGE_NAME}_ENABLE_ULLONG_IDS
  UNSIGNED_LONG_LONG_GLOBAL_IDS
  "typedef unsigned long long ZOLTAN_ID_TYPE"
  OFF )

TRIBITS_ADD_OPTION_AND_DEFINE(${PACKAGE_NAME}_ENABLE_HUND
  HAVE_ZOLTAN_HUND
  "Enable support for HUND in ${PACKAGE_NAME}."
  OFF )

TRIBITS_ADD_OPTION_AND_DEFINE(${PACKAGE_NAME}_ENABLE_KNUTH_HASH
  HAVE_ZOLTAN_KNUTH_HASH
  "Enable support for Knuth's hash function in ${PACKAGE_NAME}."
  OFF )

TRIBITS_ADD_OPTION_AND_DEFINE(${PACKAGE_NAME}_ENABLE_F90INTERFACE
  BUILD_ZOLTAN_F90_INTERFACE
  "Enable build of F90 interface to ${PACKAGE_NAME}."
  ON )

TRIBITS_ADD_OPTION_AND_DEFINE(${PACKAGE_NAME}_ENABLE_PURIFY
  HAVE_PURIFY
  "Enable work-arounds to purify bugs."
  OFF )

OPTION(${PACKAGE_NAME}_ENABLE_CPPDRIVER "Enable C++ driver for ${PACKAGE_NAME}." ${${PROJECT_NAME}_ENABLE_CXX} )


IF (${PROJECT_NAME}_ENABLE_CXX) 
  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMPICH_IGNORE_CXX_SEEK")
ENDIF()

IF(${PROJECT_NAME}_ENABLE_Fortran AND BUILD_ZOLTAN_F90_INTERFACE)

  # Special Fortran compiler-specific flags
  IF (${CMAKE_Fortran_COMPILER_ID} MATCHES "PGI")
    SET(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DPGI")
    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPGI")
  ENDIF()

  IF (${CMAKE_Fortran_COMPILER_ID} MATCHES "LAHEY")
    SET(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -DFUJITSU")
    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFUJITSU")
  ENDIF()

  SET(ZOLTAN_BUILD_ZFDRIVE YES)
ENDIF()

#
# C) Add the libraries, tests, and examples
#

IF (NOT TPL_ENABLE_MPI)
  ADD_SUBDIRECTORY(siMPI)
  SET(ZOLTAN_BUILD_ZFDRIVE NO)
ENDIF()

ADD_SUBDIRECTORY(src)

# Install readme containing license of Zoltan
INSTALL(FILES "README" DESTINATION "share/elmersolver/license_texts/Zoltan")

# TRIBITS_ADD_TEST_DIRECTORIES(src/driver) # TODO: What is this? Is this needed?

# TODO: Build library only
# IF(ZOLTAN_BUILD_ZFDRIVE)
  # CMAKE version > 2.6.4 is needed; earlier versions use C++ compiler to link
  # fdriver, while fdriver needs F90.
  # TRIBITS_ADD_TEST_DIRECTORIES(src/fdriver)
  # ADD_SUBDIRECTORY(./src/fdriver)
# ENDIF()

