#===============================================================================
# Copyright 2020-2022 Intel Corporation.
#
# This software and the related documents are Intel copyrighted  materials,  and
# your use of  them is  governed by the  express license  under which  they were
# provided to you (License).  Unless the License provides otherwise, you may not
# use, modify, copy, publish, distribute,  disclose or transmit this software or
# the related documents without Intel's prior written permission.
#
# This software and the related documents  are provided as  is,  with no express
# or implied  warranties,  other  than those  that are  expressly stated  in the
# License.
#===============================================================================

cmake_minimum_required(VERSION 3.13)
enable_testing()

# Add cmake scripts and modules to CMake search path
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../cmake")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

# Generate domainList and ${domain}_funcList
include(generate_examples_list)

if(blas IN_LIST domainList)
  set(ENABLE_BLAS95 ON)
endif()
if(lapack IN_LIST domainList)
  set(ENABLE_LAPACK95 ON)
endif()

# Define language and compiler
set(TEST_LANG Fortran)
set(TEST_EXT f)
set(DATA_EXT d)
include(setup_examples)

project(MKL_Examples LANGUAGES ${TEST_LANG})

find_package(MKL CONFIG REQUIRED)

if(WIN32)
  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO")
endif()

# Define target for each function from each domain
if(domainList)
foreach(domain IN LISTS domainList)
  set(TEST_INCLUDE "")
  set(TEST_COPT "")
  set(TEST_LOPT "")

  if(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
    list(APPEND TEST_COPT -fcray-pointer -fno-range-check -finit-local-zero -cpp)
  elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "Intel" OR CMAKE_Fortran_COMPILER_ID STREQUAL "IntelLLVM")
    list(APPEND TEST_COPT -fpp -nogen-interfaces)
  endif()

  # Build Fortran 95 wrappers if Intel pre-built wrappers can't be used
  if(NOT CMAKE_Fortran_COMPILER_ID STREQUAL "Intel" AND NOT CMAKE_Fortran_COMPILER_ID STREQUAL "InteLLVM")
    set(95_libname mkl_${domain}95_${MKL_INTERFACE})

    file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${domain}_mod")
    set(CMAKE_Fortran_MODULE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${domain}_mod")
    list(APPEND TEST_INCLUDE ${CMAKE_CURRENT_BINARY_DIR}/${domain}_mod)

    if(NOT WIN32)
      set(WRAPPERS_COPT -fPIC)
    endif()
    if(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
      list(APPEND WRAPPERS_COPT -fautomatic)
    endif()

    file(GLOB WRAPPERS_SRC ${MKL_ROOT}/share/mkl/interfaces/${domain}95/source/*)
    list(APPEND WRAPPERS_SRC ${MKL_ROOT}/include/mkl_${domain}.f90)
    add_library(${95_libname} ${WRAPPERS_SRC})
    target_compile_options(${95_libname} PUBLIC $<TARGET_PROPERTY:MKL::MKL,INTERFACE_COMPILE_OPTIONS>)

    list(APPEND TEST_LOPT ${95_libname})
  endif()

  # Domain specific options and targets
  if(domain STREQUAL "blas")
    add_library(blas_common ${PROJECT_SOURCE_DIR}/blas/source/common_func.f)
    target_include_directories(blas_common PUBLIC $<TARGET_PROPERTY:MKL::MKL,INTERFACE_INCLUDE_DIRECTORIES>)
    target_compile_options(blas_common PUBLIC ${TEST_COPT} $<TARGET_PROPERTY:MKL::MKL,INTERFACE_COMPILE_OPTIONS>)
    list(APPEND TEST_LOPT blas_common)
  endif()

  # Build target for each example
  message(STATUS "Functions list ${domain}: ${${domain}_funcList}")
  foreach(func IN LISTS ${domain}_funcList)
    string(STRIP ${func} func_name)
    set(func "${domain}-${func_name}")

    file(GLOB_RECURSE ${domain}_${func}_SRC ${PROJECT_SOURCE_DIR}/${domain}/*/${func_name}.${TEST_EXT}*)
    if(NOT ${domain}_${func}_SRC)
      message(FATAL_ERROR "${domain} source file ${func_name}.${TEST_EXT}* was not found")
    endif()

    add_executable(${func} ${${domain}_${func}_SRC})
    target_include_directories(${func} PUBLIC ${TEST_INCLUDE} $<TARGET_PROPERTY:MKL::MKL,INTERFACE_INCLUDE_DIRECTORIES>)
    target_compile_options(${func} PUBLIC ${TEST_COPT} $<TARGET_PROPERTY:MKL::MKL,INTERFACE_COMPILE_OPTIONS>)
    target_link_libraries(${func} PUBLIC ${TEST_LOPT} $<LINK_ONLY:MKL::MKL>)

    # Register example as ctest
    file(GLOB_RECURSE ${domain}_${func_name}_DATA ${PROJECT_SOURCE_DIR}/${domain}/*/${func_name}.${DATA_EXT})
    if(EXISTS ${${domain}_${func_name}_DATA})
      if (WIN32)
        add_test(NAME ${func} COMMAND ${CMAKE_COMMAND} -E chdir $<TARGET_FILE_DIR:${func}> $ENV{ComSpec} /c "$<TARGET_FILE_NAME:${func}> < ${${domain}_${func_name}_DATA}")
      else()
        add_test(NAME ${func} COMMAND sh -c "./${func} <${${domain}_${func_name}_DATA}")
      endif()
    else()
      add_test(NAME ${func} COMMAND ${func})
    endif()

    # Add Environment variables
    if(MKL_ENV)
      set_tests_properties(${func} PROPERTIES ENVIRONMENT "${MKL_ENV}")
    endif()
  endforeach() #${domain}_funcList
endforeach() #domainList
endif() #not empty domainList
