# JeMalloc

function (JEMALLOC_LIB_SEARCH MMGR_LIB PREFIX)
  if (NOT 3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB})
    set (JEMALLOC_PATH_SUFFIXES "lib" "bin")
    set (3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB} "3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB}-NOTFOUND")
    if (3RDPARTY_JEMALLOC_DIR AND EXISTS "${3RDPARTY_JEMALLOC_DIR}")
      find_library (3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB} NAMES ${MMGR_LIB}
                    PATHS "${3RDPARTY_JEMALLOC_LIBRARY_DIR}" "${3RDPARTY_JEMALLOC_DIR}"
                    PATH_SUFFIXES ${JEMALLOC_PATH_SUFFIXES}
                    CMAKE_FIND_ROOT_PATH_BOTH
                    NO_DEFAULT_PATH)
    else()
      find_library (3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB} NAMES ${MMGR_LIB}
                    PATH_SUFFIXES ${JEMALLOC_PATH_SUFFIXES}
                    CMAKE_FIND_ROOT_PATH_BOTH)
    endif()
    if (3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB})
      get_filename_component (3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB} "${3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB}}" PATH)
      set (3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB} "${3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB}}")
    else()
      set (3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB} "")
    endif()
  endif()
  if (3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB})
    list (APPEND 3RDPARTY_LIBRARY_DIRS "${3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB}}" PARENT_SCOPE)
    set (3RDPARTY_JEMALLOC_LIBRARY_DIR "${3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB}}" CACHE PATH "The directory containing JEMALLOC libraries" FORCE)
  elseif("${PREFIX}" STREQUAL "SHARED")
    return()
  else()
    message(STATUS "Cannot find ${MMGR_LIB} library in jemalloc 3rdparty")
    list (APPEND 3RDPARTY_NO_LIBS 3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB} PARENT_SCOPE)
    set (3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB} "" PARENT_SCOPE)
  endif()

  set(JEMALLOC_IS_STATIC_LIB FALSE)
  if ("${PREFIX}" STREQUAL "STATIC")
    set(JEMALLOC_IS_STATIC_LIB TRUE)
  endif()

  if (${JEMALLOC_IS_STATIC_LIB})
    set (OLD_CSF_MMGR ${CSF_MMGR})
    list (APPEND OLD_CSF_MMGR "${3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB}}")
    set (CSF_MMGR "${OLD_CSF_MMGR}" PARENT_SCOPE)
  endif()
  # install instructions
  if (INSTALL_JEMALLOC AND NOT JEMALLOC_IS_STATIC_LIB)
    OCCT_MAKE_OS_WITH_BITNESS()
    OCCT_MAKE_COMPILER_SHORT_NAME()
    get_filename_component(3RDPARTY_JEMALLOC_LIBRARY ${3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB}} REALPATH)
    if (SINGLE_GENERATOR)
      install (FILES "${3RDPARTY_JEMALLOC_LIBRARY}"
               DESTINATION "${INSTALL_DIR}/${INSTALL_DIR_LIB}")
    else()
        install (FILES "${3RDPARTY_JEMALLOC_LIBRARY}"
               CONFIGURATIONS Debug
               DESTINATION "${JEMALLOC_INSTALL_DESTINATION}d")
        install (FILES "${3RDPARTY_JEMALLOC_LIBRARY}"
                 CONFIGURATIONS Release
                 DESTINATION "${JEMALLOC_INSTALL_DESTINATION}")
        install (FILES "${3RDPARTY_JEMALLOC_LIBRARY}"
                 CONFIGURATIONS RelWithDebInfo
                 DESTINATION "${JEMALLOC_INSTALL_DESTINATION}i")
    endif()
    set (USED_3RDPARTY_JEMALLOC_DIR "" PARENT_SCOPE)
  elseif(NOT JEMALLOC_IS_STATIC_LIB)
    # the library directory for using by the executable
    set (USED_3RDPARTY_JEMALLOC_DIR ${3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB}} PARENT_SCOPE)
  endif()
  unset(3RDPARTY_JEMALLOC_LIBRARY_DIR_${MMGR_LIB} CACHE)
  unset(3RDPARTY_JEMALLOC_LIBRARY_${PREFIX}_${MMGR_LIB} CACHE)
endfunction()

macro (SEARCH_JEMALLOC)
  # find static jemalloc lib
  SET(CMAKE_FIND_LIBRARY_SUFFIXES ".dll.a" ".lib" ".a")
  if (WIN32)
    JEMALLOC_LIB_SEARCH ("jemalloc" "STATIC")
  elseif(NOT WIN32)
    JEMALLOC_LIB_SEARCH ("jemalloc_pic" "STATIC")
    SET(CMAKE_FIND_LIBRARY_SUFFIXES "" "so")
    JEMALLOC_LIB_SEARCH ("jemalloc.so.2" "SHARED")
  endif()
  
  # find shared jemalloc lib
  SET(CMAKE_FIND_LIBRARY_SUFFIXES ".dll" ".so")
  JEMALLOC_LIB_SEARCH ("jemalloc" "SHARED")
endmacro()

# Reset CSF variable
set (CSF_MMGR "")

# vcpkg processing
if (BUILD_USE_VCPKG)
  set (3RDPARTY_JEMALLOC_DIR "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}")
  OCCT_CHECK_AND_UNSET_GROUP (3RDPARTY_JEMALLOC_LIBRARY_SHARED)
  OCCT_CHECK_AND_UNSET_GROUP (3RDPARTY_JEMALLOC_LIBRARY_STATIC)
  SEARCH_JEMALLOC()
  list (APPEND 3RDPARTY_INCLUDE_DIRS "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/include/jemalloc")
  return()
endif()

if (NOT DEFINED INSTALL_JEMALLOC)
  set (INSTALL_JEMALLOC OFF CACHE BOOL "${INSTALL_INSTALL_JEMALLOC_DESCR}")
endif()

# include occt macros. compiler_bitness, os_with_bit, compiler
OCCT_INCLUDE_CMAKE_FILE ("adm/cmake/occt_macros")

# specify JEMALLOC folder in connection with 3RDPARTY_DIR
if (3RDPARTY_DIR AND EXISTS "${3RDPARTY_DIR}")
  if (NOT 3RDPARTY_JEMALLOC_DIR OR NOT EXISTS "${3RDPARTY_JEMALLOC_DIR}")
    FIND_PRODUCT_DIR ("${3RDPARTY_DIR}" jemalloc JEMALLOC_DIR_NAME)
    if (JEMALLOC_DIR_NAME)
      set (3RDPARTY_JEMALLOC_DIR "${3RDPARTY_DIR}/${JEMALLOC_DIR_NAME}" CACHE PATH "The directory containing JEMALLOC" FORCE)
      set (3RDPARTY_JEMALLOC_DIR "${3RDPARTY_DIR}/${JEMALLOC_DIR_NAME}")
      message(STATUS "Info: JEMALLOC detected in ${3RDPARTY_JEMALLOC_DIR}")
    endif()
  endif()
  else()
endif()

# define required JEMALLOC variables
if (NOT DEFINED 3RDPARTY_JEMALLOC_INCLUDE_DIR)
  set (3RDPARTY_JEMALLOC_INCLUDE_DIR  "" CACHE PATH "the path of headers directory")
endif()

# check 3RDPARTY_${PRODUCT_NAME}_ paths for consistency with specified 3RDPARTY_${PRODUCT_NAME}_DIR
if (3RDPARTY_JEMALLOC_DIR AND EXISTS "${3RDPARTY_JEMALLOC_DIR}")
  CHECK_PATH_FOR_CONSISTENCY (3RDPARTY_JEMALLOC_DIR 3RDPARTY_JEMALLOC_INCLUDE_DIR PATH "the path to JEMALLOC")
  CHECK_PATH_FOR_CONSISTENCY (3RDPARTY_JEMALLOC_DIR 3RDPARTY_JEMALLOC_LIBRARY_DIR FILEPATH "The directory containing JEMALLOC libraries")
endif()

# header
if (NOT 3RDPARTY_JEMALLOC_INCLUDE_DIR OR NOT EXISTS "${3RDPARTY_JEMALLOC_INCLUDE_DIR}")
  set (HEADER_NAMES jemalloc.h)
  
  # set 3RDPARTY_JEMALLOC_INCLUDE_DIR as notfound, otherwise find_library can't assign a new value to 3RDPARTY_JEMALLOC_INCLUDE_DIR
  set (3RDPARTY_JEMALLOC_INCLUDE_DIR "3RDPARTY_JEMALLOC_INCLUDE_DIR-NOTFOUND" CACHE FILEPATH "the path to header directory" FORCE)
  
  if (3RDPARTY_JEMALLOC_DIR AND EXISTS "${3RDPARTY_JEMALLOC_DIR}")
    find_path (3RDPARTY_JEMALLOC_INCLUDE_DIR NAMES ${HEADER_NAMES}
                                               PATHS ${3RDPARTY_JEMALLOC_DIR}
                                               PATH_SUFFIXES include/jemalloc
                                               CMAKE_FIND_ROOT_PATH_BOTH
                                               NO_DEFAULT_PATH)
  else()
    find_path (3RDPARTY_JEMALLOC_INCLUDE_DIR NAMES ${HEADER_NAMES}
                                               PATHS ${3RDPARTY_JEMALLOC_DIR}
                                               PATH_SUFFIXES include/jemalloc
                                               CMAKE_FIND_ROOT_PATH_BOTH)
  endif()
endif()

if (3RDPARTY_JEMALLOC_INCLUDE_DIR AND EXISTS "${3RDPARTY_JEMALLOC_INCLUDE_DIR}")
  list (APPEND 3RDPARTY_INCLUDE_DIRS "${3RDPARTY_JEMALLOC_INCLUDE_DIR}")
else()
  list (APPEND 3RDPARTY_NOT_INCLUDED 3RDPARTY_JEMALLOC_INCLUDE_DIR)
  set (3RDPARTY_JEMALLOC_INCLUDE_DIR "" CACHE FILEPATH "the path to jemalloc.h" FORCE)
endif()

# Installing destination path
if (WIN32)
  set (JEMALLOC_INSTALL_DESTINATION "${INSTALL_DIR}/${INSTALL_DIR_BIN}")
else()
  set (JEMALLOC_INSTALL_DESTINATION "${INSTALL_DIR}/${INSTALL_DIR_LIB}")
endif()

# find static jemalloc lib
SEARCH_JEMALLOC()