# ---------------------
# hipSYCL-specific setup
# ---------------------

set(HIPSYCL_PLATFORMS_STRING "")

set(HIPSYCL_NUM_AVAILABLE_BACKENDS 0)
if(HIPSYCL_CPU_BACKEND_AVAILABLE)
  MATH(EXPR HIPSYCL_NUM_AVAILABLE_BACKENDS "${HIPSYCL_NUM_AVAILABLE_BACKENDS}+1")
  if(NOT HIPSYCL_DEFAULT_PLATFORM)
    set(HIPSYCL_DEFAULT_PLATFORM "cpu")
  endif()
  if(HIPSYCL_PLATFORMS_STRING)
    set(HIPSYCL_PLATFORMS_STRING "${HIPSYCL_PLATFORMS_STRING}|cpu")
  else()
    set(HIPSYCL_PLATFORMS_STRING "cpu")
  endif()
endif()
if(HIPSYCL_CUDA_BACKEND_AVAILABLE)
  MATH(EXPR HIPSYCL_NUM_AVAILABLE_BACKENDS "${HIPSYCL_NUM_AVAILABLE_BACKENDS}+1")
  if(NOT HIPSYCL_DEFAULT_PLATFORM)
    set(HIPSYCL_DEFAULT_PLATFORM "cuda")
  endif()
  if(HIPSYCL_PLATFORMS_STRING)
    set(HIPSYCL_PLATFORMS_STRING "${HIPSYCL_PLATFORMS_STRING}|cuda")
  else()
    set(HIPSYCL_PLATFORMS_STRING "cuda")
  endif()
endif()
if(HIPSYCL_ROCM_BACKEND_AVAILABLE)
  MATH(EXPR HIPSYCL_NUM_AVAILABLE_BACKENDS "${HIPSYCL_NUM_AVAILABLE_BACKENDS}+1")
  if(NOT HIPSYCL_DEFAULT_PLATFORM)
    set(HIPSYCL_DEFAULT_PLATFORM "rocm")
  endif()
  if(HIPSYCL_PLATFORMS_STRING)
    set(HIPSYCL_PLATFORMS_STRING "${HIPSYCL_PLATFORMS_STRING}|rocm")
  else()
    set(HIPSYCL_PLATFORMS_STRING "rocm")
  endif()
endif()

set(HIPSYCL_PLATFORM "" CACHE STRING "The platform that hipSYCL should target. One of ${HIPSYCL_PLATFORMS_STRING}.")

# If HIPSYCL_PLATFORM has not been explicitly set by the user, first try to find
# the corresponding environment variable. If that isn't set either, and only
# a single platform is available, default to it. Otherwise throw an error.
if(NOT HIPSYCL_PLATFORM)
  set(HIPSYCL_PLATFORM_ENV $ENV{HIPSYCL_PLATFORM})
  if(HIPSYCL_PLATFORM_ENV)
    message("Found HIPSYCL_PLATFORM from environment: ${HIPSYCL_PLATFORM_ENV}")
    set(HIPSYCL_DEFAULT_PLATFORM ${HIPSYCL_PLATFORM_ENV})
  elseif(HIPSYCL_NUM_AVAILABLE_BACKENDS GREATER 1)
    message(SEND_ERROR "More than one hipSYCL target platform is available.\n"
      "Please specify HIPSYCL_PLATFORM=${HIPSYCL_PLATFORMS_STRING}")
  endif()
  set(HIPSYCL_PLATFORM ${HIPSYCL_DEFAULT_PLATFORM})
  unset(HIPSYCL_PLATFORM_ENV)
endif()

# Determine canonical platform from aliases
if(HIPSYCL_PLATFORM MATCHES "cpu|host|hipcpu")
  set(HIPSYCL_PLATFORM_CANONICAL "cpu")
elseif(HIPSYCL_PLATFORM MATCHES "cuda|nvidia")
  set(HIPSYCL_PLATFORM_CANONICAL "cuda")
elseif(HIPSYCL_PLATFORM MATCHES "rocm|amd|hip|hcc")
  set(HIPSYCL_PLATFORM_CANONICAL "rocm")
else()
  message(SEND_ERROR "Unknown hipSYCL platform '${HIPSYCL_PLATFORM}'")
endif()

unset(HIPSYCL_PLATFORMS_STRING)
unset(HIPSYCL_NUM_AVAILABLE_BACKENDS)
unset(HIPSYCL_DEFAULT_PLATFORM)

set(CMAKE_SYCL_FLAGS_INIT "${CMAKE_SYCL_FLAGS_INIT} --hipsycl-platform=${HIPSYCL_PLATFORM}")

set(HIPSYCL_CLANG "" CACHE STRING "Clang compiler executable used for compilation.")
if(HIPSYCL_CLANG)
  set(CMAKE_SYCL_FLAGS_INIT "${CMAKE_SYCL_FLAGS_INIT} --hipsycl-clang=${HIPSYCL_CLANG}")
endif()

set(HIPSYCL_CUDA_PATH "" CACHE STRING "The path to the CUDA toolkit installation directory.")
if(HIPSYCL_CUDA_PATH)
  if(HIPSYCL_PLATFORM_CANONICAL STREQUAL "cuda")
    set(CMAKE_SYCL_FLAGS_INIT "${CMAKE_SYCL_FLAGS_INIT} --hipsycl-cuda-path=${HIPSYCL_CUDA_PATH}")
  else()
    message(WARNING "HIPSYCL_CUDA_PATH (${HIPSYCL_CUDA_PATH}) is ignored for current platform (${HIPSYCL_PLATFORM})")
  endif()
endif()

set(HIPSYCL_ROCM_PATH "" CACHE STRING "The path to the ROCm installation directory.")
if(HIPSYCL_ROCM_PATH)
  if(HIPSYCL_PLATFORM_CANONICAL STREQUAL "rocm")
    set(CMAKE_SYCL_FLAGS_INIT "${CMAKE_SYCL_FLAGS_INIT} --hipsycl-rocm-path=${HIPSYCL_ROCM_PATH}")
  else()
    message(WARNING "HIPSYCL_ROCM_PATH (${HIPSYCL_ROCM_PATH}) is ignored for current platform (${HIPSYCL_PLATFORM})")
  endif()
endif()

set(HIPSYCL_GPU_ARCH "" CACHE STRING "GPU architecture used by ROCm / CUDA.")
if(HIPSYCL_GPU_ARCH)
  if(HIPSYCL_PLATFORM_CANONICAL STREQUAL "cuda" OR HIPSYCL_PLATFORM_CANONICAL STREQUAL "rocm")
    set(CMAKE_SYCL_FLAGS_INIT "${CMAKE_SYCL_FLAGS_INIT} --hipsycl-gpu-arch=${HIPSYCL_GPU_ARCH}")
  else()
    message(WARNING "HIPSYCL_GPU_ARCH (${HIPSYCL_GPU_ARCH}) is ignored for current platform (${HIPSYCL_PLATFORM})")
  endif()
else()
  set(_TMP $ENV{HIPSYCL_GPU_ARCH})
  if((HIPSYCL_PLATFORM_CANONICAL STREQUAL "cuda" OR HIPSYCL_PLATFORM_CANONICAL STREQUAL "rocm") AND NOT _TMP)
    message(SEND_ERROR "Please specify HIPSYCL_GPU_ARCH")
  endif()
  unset(_TMP)
endif()

set(HIPSYCL_CPU_CXX "" CACHE STRING "The compiler that should be used when targeting only CPUs.")
if(HIPSYCL_CPU_CXX)
  if(HIPSYCL_PLATFORM_CANONICAL STREQUAL "cpu")
    set(CMAKE_SYCL_FLAGS_INIT "${CMAKE_SYCL_FLAGS_INIT} --hipsycl-cpu-cxx=${HIPSYCL_CPU_CXX}")
  else()
    message(WARNING "HIPSYCL_CPU_CXX (${HIPSYCL_CPU_CXX}) is ignored for current platform (${HIPSYCL_PLATFORM})")
  endif()
endif()

# ---------------------
# Compilation flags and rules
# These are mostly based on https://github.com/Kitware/CMake/blob/master/Modules/CMakeCXXInformation.cmake
# CMake is distributed under the BSD 3-clause License.
# ---------------------

if(NOT CMAKE_DEPFILE_FLAGS_SYCL)
  set(CMAKE_DEPFILE_FLAGS_SYCL ${CMAKE_DEPFILE_FLAGS_CXX})
endif()

if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_SYCL_FLAG)
  set(CMAKE_SHARED_LIBRARY_RUNTIME_SYCL_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG})
endif()

if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_SYCL_FLAG_SEP)
  set(CMAKE_SHARED_LIBRARY_RUNTIME_SYCL_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG_SEP})
endif()

if(NOT CMAKE_SHARED_LIBRARY_RPATH_LINK_SYCL_FLAG)
  set(CMAKE_SHARED_LIBRARY_RPATH_LINK_SYCL_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_CXX_FLAG})
endif()

if(NOT CMAKE_EXECUTABLE_RUNTIME_SYCL_FLAG)
  set(CMAKE_EXECUTABLE_RUNTIME_SYCL_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG})
endif()

if(NOT CMAKE_EXECUTABLE_RUNTIME_SYCL_FLAG_SEP)
  set(CMAKE_EXECUTABLE_RUNTIME_SYCL_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_SYCL_FLAG_SEP})
endif()

if(NOT CMAKE_EXECUTABLE_RPATH_LINK_SYCL_FLAG)
  set(CMAKE_EXECUTABLE_RPATH_LINK_SYCL_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_SYCL_FLAG})
endif()

if(NOT CMAKE_INCLUDE_FLAG_SYCL)
  set(CMAKE_INCLUDE_FLAG_SYCL ${CMAKE_INCLUDE_FLAG_CXX})
endif()

set(CMAKE_SYCL_FLAGS_INIT "$ENV{SYCLFLAGS} ${CMAKE_SYCL_FLAGS_INIT}")
string(STRIP "${CMAKE_SYCL_FLAGS_INIT}" CMAKE_SYCL_FLAGS_INIT)

foreach(c _DEBUG _RELEASE _MINSIZEREL _RELWITHDEBINFO)
  string(STRIP "${CMAKE_CXX_FLAGS${c}_INIT}" CMAKE_SYCL_FLAGS${c}_INIT)
endforeach()

set(CMAKE_SYCL_FLAGS "${CMAKE_SYCL_FLAGS_INIT}" CACHE STRING
    "Flags used by the compiler during all build types.")

if(NOT CMAKE_NOT_USING_CONFIG_FLAGS)
  set(CMAKE_SYCL_FLAGS_DEBUG "${CMAKE_SYCL_FLAGS_DEBUG_INIT}" CACHE STRING
      "Flags used by the compiler during debug builds.")
  set(CMAKE_SYCL_FLAGS_MINSIZEREL "${CMAKE_SYCL_FLAGS_MINSIZEREL_INIT}" CACHE STRING
      "Flags used by the compiler during release builds for minimum size.")
  set(CMAKE_SYCL_FLAGS_RELEASE "${CMAKE_SYCL_FLAGS_RELEASE_INIT}" CACHE STRING
      "Flags used by the compiler during release builds.")
  set(CMAKE_SYCL_FLAGS_RELWITHDEBINFO "${CMAKE_SYCL_FLAGS_RELWITHDEBINFO_INIT}" CACHE STRING
      "Flags used by the compiler during release builds with debug info.")
endif()

include(CMakeCommonLanguageInclude)

if(NOT CMAKE_SYCL_CREATE_SHARED_LIBRARY)
  set(CMAKE_SYCL_CREATE_SHARED_LIBRARY
      "<CMAKE_SYCL_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
endif()

if(NOT CMAKE_SYCL_CREATE_SHARED_MODULE)
  set(CMAKE_SYCL_CREATE_SHARED_MODULE ${CMAKE_SYCL_CREATE_SHARED_LIBRARY})
endif()

if(NOT DEFINED CMAKE_SYCL_ARCHIVE_CREATE)
  set(CMAKE_SYCL_ARCHIVE_CREATE ${CMAKE_CXX_ARCHIVE_CREATE})
endif()
if(NOT DEFINED CMAKE_SYCL_ARCHIVE_APPEND)
  set(CMAKE_SYCL_ARCHIVE_APPEND ${CMAKE_CXX_ARCHIVE_APPEND})
endif()
if(NOT DEFINED CMAKE_SYCL_ARCHIVE_FINISH)
  set(CMAKE_SYCL_ARCHIVE_FINISH ${CMAKE_CXX_ARCHIVE_FINISH})
endif()

if(NOT CMAKE_SYCL_COMPILE_OBJECT)
  set(CMAKE_SYCL_COMPILE_OBJECT "<CMAKE_SYCL_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
endif()

if(NOT CMAKE_SYCL_LINK_EXECUTABLE)
  set(CMAKE_SYCL_LINK_EXECUTABLE "<CMAKE_SYCL_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS>  -o <TARGET> <LINK_LIBRARIES>")
endif()

set(CMAKE_SYCL_INFORMATION_LOADED 1)

