# Keep this in sync with llvm/cmake/CMakeLists.txt!

set(LLVM_INSTALL_PACKAGE_DIR "lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm")
set(POLLY_INSTALL_PACKAGE_DIR "lib${LLVM_LIBDIR_SUFFIX}/cmake/polly")
if (CMAKE_CONFIGURATION_TYPES)
  set(POLLY_EXPORTS_FILE_NAME "PollyExports-$<LOWER_CASE:$<CONFIG>>.cmake")
else()
  # avoid conflicts in the build-tree when changing configuration
  set(POLLY_EXPORTS_FILE_NAME "PollyExports-all.cmake")
endif()

set(POLLY_CONFIG_EXPORTED_TARGETS Polly ${ISL_TARGET})
if (NOT WIN32 AND LLVM_ENABLE_PIC)
  # LLVMPolly is a dummy target on Win or if PIC code is disabled.
  list(APPEND POLLY_CONFIG_EXPORTED_TARGETS LLVMPolly)
endif()
if (POLLY_ENABLE_GPGPU_CODEGEN)
  list(APPEND POLLY_CONFIG_EXPORTED_TARGETS PollyPPCG)
endif()

# Get the target type for every exported target
foreach(tgt IN LISTS POLLY_CONFIG_EXPORTED_TARGETS)
  get_target_property(tgt_type ${tgt} TYPE)
  string(REPLACE "_LIBRARY" "" tgt_type ${tgt_type})
  set(POLLY_CONFIG_TARGET_${tgt}_TYPE ${tgt_type})
endforeach()

set(llvm_cmake_builddir "${LLVM_BINARY_DIR}/${LLVM_INSTALL_PACKAGE_DIR}")
set(POLLY_CONFIG_LLVM_CMAKE_DIR "${llvm_cmake_builddir}")

# generate the import code for bundled/undbundled libisl versions
if (NOT POLLY_BUNDLED_ISL)
  get_property(incl TARGET ISL PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
  get_property(lib TARGET ISL PROPERTY INTERFACE_LINK_LIBRARIES)
  get_property(opt TARGET ISL PROPERTY INTERFACE_COMPILE_OPTIONS)
  set(ISL_CONFIG_CODE "
add_library(ISL INTERFACE IMPORTED)
set_property(TARGET ISL APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${incl})
set_property(TARGET ISL APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${lib})
set_property(TARGET ISL APPEND PROPERTY INTERFACE_COMPILE_OPTIONS ${opt})")
else()
  set(ISL_CONFIG_CODE "
if (NOT TARGET PollyISL)
  add_library(PollyISL ${POLLY_CONFIG_TARGET_PollyISL_TYPE} IMPORTED)
endif()")
endif()

# Generate PollyConfig.cmake for the build tree.
set(POLLY_CONFIG_CMAKE_DIR "${CMAKE_BINARY_DIR}/${POLLY_INSTALL_PACKAGE_DIR}")
set(POLLY_CONFIG_INCLUDE_DIRS
  ${POLLY_SOURCE_DIR}/include
  ${ISL_INCLUDE_DIRS}
  ${POLLY_BINARY_DIR}/include
  )
set(POLLY_CONFIG_LIBRARY_DIRS "${POLLY_BINARY_DIR}/lib")

# set locations for imported targets
foreach(tgt IN LISTS POLLY_CONFIG_EXPORTED_TARGETS)
  get_target_property(tgt_type ${tgt} TYPE)
  if (NOT tgt_type STREQUAL "INTERFACE_LIBRARY")
    set(POLLY_EXPORTS
      "set_target_properties(${tgt} PROPERTIES
              IMPORTED_LOCATION$<$<NOT:$<CONFIG:>>:_$<UPPER_CASE:$<CONFIG>>> $<TARGET_FILE:${tgt}>)
${POLLY_EXPORTS}")
  endif()
endforeach(tgt)

# PollyConfig holds the target definitions and general settings, PollyExports
# the imported locations
configure_file(
  ${CMAKE_CURRENT_SOURCE_DIR}/PollyConfig.cmake.in
  ${POLLY_CONFIG_CMAKE_DIR}/PollyConfig.cmake
  @ONLY)

file(GENERATE
  OUTPUT ${POLLY_CONFIG_CMAKE_DIR}/${POLLY_EXPORTS_FILE_NAME}
  CONTENT "${POLLY_EXPORTS}")


# Generate PollyConfig.cmake for the install tree.
unset(POLLY_EXPORTS)
set(POLLY_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
set(POLLY_CONFIG_LLVM_CMAKE_DIR "${LLVM_BINARY_DIR}/${LLVM_INSTALL_PACKAGE_DIR}")
set(POLLY_CONFIG_CMAKE_DIR "${POLLY_INSTALL_PREFIX}/${POLLY_INSTALL_PACKAGE_DIR}")
set(POLLY_CONFIG_LIBRARY_DIRS "${POLLY_INSTALL_PREFIX}/lib${LLVM_LIBDIR_SUFFIX}")
if (POLLY_BUNDLED_ISL)
  set(POLLY_CONFIG_INCLUDE_DIRS
    "${POLLY_INSTALL_PREFIX}/include"
    "${POLLY_INSTALL_PREFIX}/include/polly"
    )
else()
  set(POLLY_CONFIG_INCLUDE_DIRS
    "${POLLY_INSTALL_PREFIX}/include"
    ${ISL_INCLUDE_DIRS}
    )
endif()

# set locations for imported targets. The path is constructed to be relative to
# the config file
foreach(tgt IN LISTS POLLY_CONFIG_EXPORTED_TARGETS)
  get_target_property(tgt_type ${tgt} TYPE)
  if (tgt_type STREQUAL "EXECUTABLE")
    set(tgt_prefix "bin/")
  else()
    set(tgt_prefix "lib/")
  endif()

  set(tgt_path "${CMAKE_INSTALL_PREFIX}/${tgt_prefix}$<TARGET_FILE_NAME:${tgt}>")
  file(RELATIVE_PATH tgt_path ${POLLY_CONFIG_CMAKE_DIR} ${tgt_path})

  if (NOT tgt_type STREQUAL "INTERFACE_LIBRARY")
    set(POLLY_EXPORTS
"set_target_properties(${tgt} PROPERTIES
        IMPORTED_LOCATION$<$<NOT:$<CONFIG:>>:_$<UPPER_CASE:$<CONFIG>>> \${CMAKE_CURRENT_LIST_DIR}/${tgt_path})
${POLLY_EXPORTS}")
  endif()
endforeach(tgt)

configure_file(
  ${CMAKE_CURRENT_SOURCE_DIR}/PollyConfig.cmake.in
  ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/PollyConfig.cmake
  @ONLY)
file(GENERATE OUTPUT
  ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${POLLY_EXPORTS_FILE_NAME}
  CONTENT "${POLLY_EXPORTS}")

if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
  install(
    FILES
    "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/PollyConfig.cmake"
    "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${POLLY_EXPORTS_FILE_NAME}"
    DESTINATION "${POLLY_INSTALL_PACKAGE_DIR}")
endif ()
