CMAKE_MINIMUM_REQUIRED(VERSION 3.8)

# UltraInfer basic infos
set(ULTRAINFER_VERSION @ULTRAINFER_VERSION@)
set(LIBRARY_NAME @LIBRARY_NAME@)

# If compile with GLIBC_CXX_ABI=0
set(NEED_ABI0 @NEED_ABI0@)

# Hardware and Language API
set(WITH_GPU @WITH_GPU@)
set(WITH_IPU @WITH_IPU@)
set(WITH_OPENCL @WITH_OPENCL@)
set(WITH_ASCEND @WITH_ASCEND@)
set(WITH_DIRECTML @WITH_DIRECTML@)
set(WITH_TIMVX @WITH_TIMVX@)
set(WITH_KUNLUNXIN @WITH_KUNLUNXIN@)
set(WITH_CAPI @WITH_CAPI@)
set(WITH_CSHARPAPI @WITH_CSHARPAPI@)
set(WITH_TESTING @WITH_TESTING@)
set(BUILD_ON_JETSON @BUILD_ON_JETSON@)
set(RKNN2_TARGET_SOC "@RKNN2_TARGET_SOC@")

# Inference backend and UltraInfer Module
set(ENABLE_ORT_BACKEND @ENABLE_ORT_BACKEND@)
set(ENABLE_RKNPU2_BACKEND @ENABLE_RKNPU2_BACKEND@)
set(ENABLE_TVM_BACKEND @ENABLE_TVM_BACKEND@)
set(ENABLE_HORIZON_BACKEND @ENABLE_HORIZON_BACKEND@)
set(ENABLE_SOPHGO_BACKEND @ENABLE_SOPHGO_BACKEND@)
set(ENABLE_LITE_BACKEND @ENABLE_LITE_BACKEND@)
set(ENABLE_PADDLE_BACKEND @ENABLE_PADDLE_BACKEND@)
set(ENABLE_OPENVINO_BACKEND @ENABLE_OPENVINO_BACKEND@)
set(ENABLE_POROS_BACKEND @ENABLE_POROS_BACKEND@)
set(ENABLE_TRT_BACKEND @ENABLE_TRT_BACKEND@)
set(ENABLE_OM_BACKEND @ENABLE_OM_BACKEND@)
set(ENABLE_PADDLE2ONNX @ENABLE_PADDLE2ONNX@)
set(BUILD_PADDLE2ONNX @BUILD_PADDLE2ONNX@)

set(ENABLE_VISION @ENABLE_VISION@)
set(ENABLE_FLYCV @ENABLE_FLYCV@)
set(ENABLE_CVCUDA @ENABLE_CVCUDA@)
set(ENABLE_TEXT @ENABLE_TEXT@)
set(ENABLE_BENCHMARK @ENABLE_BENCHMARK@)

# Version infos and custom settings for third libs
set(PADDLEINFERENCE_VERSION @PADDLEINFERENCE_VERSION@)
set(POROS_VERSION @POROS_VERSION@)
set(OPENVINO_VERSION @OPENVINO_VERSION@)
set(OPENCV_FILENAME @OPENCV_FILENAME@)
set(OPENVINO_FILENAME @OPENVINO_FILENAME@)
set(PADDLELITE_FILENAME @PADDLELITE_FILENAME@)
set(OPENCV_DIRECTORY "@OPENCV_DIRECTORY@")
set(ORT_DIRECTORY "@ORT_DIRECTORY@")
set(OPENVINO_DIRECTORY "@OPENVINO_DIRECTORY@")

set(ULTRAINFER_LIBS "")
set(ULTRAINFER_INCS "")
list(APPEND ULTRAINFER_INCS ${CMAKE_CURRENT_LIST_DIR}/include)

# Note(zhoushunjie): include some useful utils function
include(${CMAKE_CURRENT_LIST_DIR}/utils.cmake)

# Set C++11 as standard for the whole project
if(NOT MSVC)
  set(CMAKE_CXX_STANDARD 11)
  set(CMAKE_CXX_FLAGS "-Wno-format")
  if(NEED_ABI0)
    add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
  else()
    add_definitions(-D_GLIBCXX_USE_CXX11_ABI=1)
  endif()
endif(NOT MSVC)

# Still need omp while using UltraInfer static lib.
# This is due to the use of openmp for Paddle Lite's
# static library.

find_library(FDLIB ${LIBRARY_NAME} ${CMAKE_CURRENT_LIST_DIR}/lib NO_DEFAULT_PATH)
list(APPEND ULTRAINFER_LIBS ${FDLIB})

if(ENABLE_ORT_BACKEND)
  if (ORT_DIRECTORY)
    set(ORT_LIB_PATH ${ORT_DIRECTORY}/lib)
  else()
    set(ORT_LIB_PATH ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/onnxruntime/lib)
  endif()
  message(STATUS "The path of ONNXRuntime is ${ORT_LIB_PATH}.")
  find_library(ORT_LIB onnxruntime ${ORT_LIB_PATH}  NO_DEFAULT_PATH)
  list(APPEND ULTRAINFER_LIBS ${ORT_LIB})
endif()

if(ENABLE_TVM_BACKEND)
    if(APPLE)
        set(TVM_RUNTIME_LIB ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/tvm/lib/libtvm_runtime.dylib)
    else()
        set(TVM_RUNTIME_LIB ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/tvm/lib/libtvm_runtime.so)
    endif()
    list(APPEND ULTRAINFER_LIBS ${TVM_RUNTIME_LIB})
endif()

if(ENABLE_PADDLE_BACKEND)
  string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)" _ "${PADDLEINFERENCE_VERSION}")
  set(PADDLEINFERENCE_VERSION_MAJOR "${CMAKE_MATCH_1}")
  set(PADDLEINFERENCE_VERSION_MINOR "${CMAKE_MATCH_2}")
  set(PADDLEINFERENCE_VERSION_PATCH "${CMAKE_MATCH_3}")
  find_library(PADDLE_LIB paddle_inference ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/paddle_inference/paddle/lib NO_DEFAULT_PATH)
  if(WIN32)
    if(PADDLEINFERENCE_VERSION_MAJOR EQUAL 2)
      set(DNNL_LIB "${CMAKE_CURRENT_LIST_DIR}/third_libs/install/paddle_inference/third_party/install/mkldnn/lib/mkldnn.lib")
    else()
      set(DNNL_LIB "${CMAKE_CURRENT_LIST_DIR}/third_libs/install/paddle_inference/third_party/install/onednn/lib/dnnl.lib")
    endif()
    set(IOMP_LIB "${CMAKE_CURRENT_LIST_DIR}/third_libs/install/paddle_inference/third_party/install/mklml/lib/libiomp5md.lib")
  elseif(APPLE)
    message(STATUS "No third parties libs(mkldnn and omp) need to link into paddle_inference on MacOS OSX.")
  else()
    if(PADDLEINFERENCE_VERSION_MAJOR EQUAL 2)
      set(DNNL_LIB "${CMAKE_CURRENT_LIST_DIR}/third_libs/install/paddle_inference/third_party/install/mkldnn/lib/libmkldnn.so.0")
    else()
      set(DNNL_LIB "${CMAKE_CURRENT_LIST_DIR}/third_libs/install/paddle_inference/third_party/install/onednn/lib/libdnnl.so.3")
    endif()
    set(IOMP_LIB "${CMAKE_CURRENT_LIST_DIR}/third_libs/install/paddle_inference/third_party/install/mklml/lib/libiomp5.so")
  endif()
  list(APPEND ULTRAINFER_LIBS ${PADDLE_LIB})
  if(EXISTS "${DNNL_LIB}")
    list(APPEND ULTRAINFER_LIBS ${DNNL_LIB} ${IOMP_LIB})
  endif()
endif()

if(ENABLE_OPENVINO_BACKEND)
  if (OPENVINO_DIRECTORY)
    set(OPENVINO_DIR ${OPENVINO_DIRECTORY})
  else()
    set(OPENVINO_DIR ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/${OPENVINO_FILENAME}/runtime)
  endif()
  get_openvino_libs(${OPENVINO_DIR})
  message(STATUS "OPENVINO_LIBS = ${OPENVINO_LIBS}")
  list(APPEND ULTRAINFER_LIBS ${OPENVINO_LIBS})
endif()

if(ENABLE_RKNPU2_BACKEND)
  if(RKNN2_TARGET_SOC STREQUAL "RK356X")
    set(RKNPU2_LIB ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/rknpu2_runtime/lib/librknnrt.so)
  elseif (RKNN2_TARGET_SOC STREQUAL "RK3588")
    set(RKNPU2_LIB ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/rknpu2_runtime/lib/librknnrt.so)
  else ()
    message(FATAL_ERROR "RKNN2_TARGET_SOC is not set, ref value: RK356X or RK3588")
  endif()
  message(STATUS "The path of RKNPU2 is ${RKNPU2_LIB}.")
  list(APPEND ULTRAINFER_LIBS ${RKNPU2_LIB})
endif()

if(ENABLE_HORIZON_BACKEND)
  set(DNN_PATH ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/dnn)
  set(APPSDK_PATH ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/appsdk/appuser/)

  set(DNN_LIB_PATH ${DNN_PATH}/lib)
  set(APPSDK_LIB_PATH ${APPSDK_PATH}/lib/hbbpu)
  set(BPU_libs dnn cnn_intf hbrt_bernoulli_aarch64)

  link_directories(${DNN_LIB_PATH}
                  ${APPSDK_PATH}/lib/hbbpu
                  ${APPSDK_PATH}/lib)

  list(APPEND ULTRAINFER_LIBS ${BPU_libs})

endif()
if(ENABLE_LITE_BACKEND)
  set(LITE_DIR ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/${PADDLELITE_FILENAME})
  # Linux/Mac/Win/...
  find_library(LITE_LIB paddle_full_api_shared ${LITE_DIR}/lib NO_DEFAULT_PATH)
  list(APPEND ULTRAINFER_LIBS ${LITE_LIB})
endif()

if(ENABLE_POROS_BACKEND)
  find_library(POROS_LIB poros ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/poros/lib NO_DEFAULT_PATH)
  find_library(TORCH_LIB torch ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/torch/lib NO_DEFAULT_PATH)
  set(TORCH_INCLUDE "${CMAKE_CURRENT_LIST_DIR}/third_libs/install/torch/include")
  list(APPEND ULTRAINFER_LIBS ${POROS_LIB} ${TORCH_LIB})
  list(APPEND ULTRAINFER_INCS ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/poros/include ${TORCH_INCLUDE})
endif()

if(ENABLE_OM_BACKEND)
  set(LIB_PATH $ENV{NPU_HOST_LIB})
  if (NOT DEFINED ENV{NPU_HOST_LIB})
    set(LIB_PATH "/usr/local/Ascend/ascend-toolkit/latest/x86_64-linux/lib64")
    message(STATUS "set default LIB_PATH: ${LIB_PATH}")
  else()
    message(STATUS "set LIB_PATH: ${LIB_PATH}")
  endif ()

  set(INC_PATH $ENV{DDK_PATH})
  if (NOT DEFINED ENV{DDK_PATH})
    set(INC_PATH "/usr/local/Ascend/ascend-toolkit/latest")
    message(STATUS "set default INC_PATH: ${INC_PATH}")
  else()
    message(STATUS "set INC_PATH: ${INC_PATH}")
  endif ()

  set(NPU_libs ascendcl stdc++)

  link_directories(${LIB_PATH})

  list(APPEND ULTRAINFER_LIBS ${NPU_libs})

  list(APPEND ULTRAINFER_INCS ${INC_PATH}/runtime/include/)
endif()

if(WITH_GPU)
  if(NOT CUDA_DIRECTORY)
    set(CUDA_DIRECTORY "/usr/local/cuda")
  endif()
  if(WIN32)
    find_library(CUDA_LIB cudart ${CUDA_DIRECTORY}/lib/x64)
    find_library(NVJPEG_LIB nvjpeg ${CUDA_DIRECTORY}/lib/x64)
  else()
    find_library(CUDA_LIB cudart ${CUDA_DIRECTORY}/lib64)
    if(NOT BUILD_ON_JETSON)
      find_library(NVJPEG_LIB nvjpeg ${CUDA_DIRECTORY}/lib64)
    endif()
  endif()
  if(NOT CUDA_LIB)
    message(FATAL_ERROR "[UltraInfer] Cannot find library cudart in ${CUDA_DIRECTORY}, Please define CUDA_DIRECTORY, e.g -DCUDA_DIRECTORY=/path/to/cuda")
  endif()
  list(APPEND ULTRAINFER_LIBS ${CUDA_LIB} ${NVJPEG_LIB})
  list(APPEND ULTRAINFER_INCS ${CUDA_DIRECTORY}/include)

  if(ENABLE_TRT_BACKEND)
    if(BUILD_ON_JETSON)
      find_library(TRT_INFER_LIB nvinfer /usr/lib/aarch64-linux-gnu/)
      find_library(TRT_ONNX_LIB nvonnxparser /usr/lib/aarch64-linux-gnu/)
      find_library(TRT_PLUGIN_LIB nvinfer_plugin /usr/lib/aarch64-linux-gnu/)
    else()
      if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/tensorrt/)
        find_library(TRT_INFER_LIB nvinfer ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/tensorrt/lib NO_DEFAULT_PATH)
        find_library(TRT_ONNX_LIB nvonnxparser ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/tensorrt/lib NO_DEFAULT_PATH)
        find_library(TRT_PLUGIN_LIB nvinfer_plugin ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/tensorrt/lib NO_DEFAULT_PATH)
      else()
        find_library(TRT_INFER_LIB nvinfer /usr/lib/x86_64-linux-gnu/)
        find_library(TRT_ONNX_LIB nvonnxparser /usr/lib/x86_64-linux-gnu/)
        find_library(TRT_PLUGIN_LIB nvinfer_plugin /usr/lib/x86_64-linux-gnu/)
      endif()
    endif()
    list(APPEND ULTRAINFER_LIBS ${TRT_INFER_LIB} ${TRT_ONNX_LIB} ${TRT_PLUGIN_LIB})
  endif()
endif()

if(ENABLE_VISION)
  if(OPENCV_DIRECTORY)
    set(OpenCV_DIR ${OPENCV_DIRECTORY})
  else()
    set(OpenCV_DIR ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/${OPENCV_FILENAME})
    if(WIN32)
      set(OpenCV_DIR ${OpenCV_DIR}/build)
    endif()
  endif()
  message(STATUS "The path of OpenCV is ${OpenCV_DIR}.")

  # Win/Linux/Mac
  find_package(OpenCV REQUIRED PATHS ${OpenCV_DIR} NO_DEFAULT_PATH)
  list(APPEND ULTRAINFER_INCS ${OpenCV_INCLUDE_DIRS})
  list(APPEND ULTRAINFER_LIBS ${OpenCV_LIBS})

  if(ENABLE_FLYCV)
    include_directories(${CMAKE_CURRENT_LIST_DIR}/third_libs/install/flycv/include)
    set(FLYCV_LIB_DIR ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/flycv/lib)

    find_library(FLYCV_LIB flycv_shared ${FLYCV_LIB_DIR} NO_DEFAULT_PATH)
    list(APPEND ULTRAINFER_LIBS ${FLYCV_LIB})
  endif()

  if(ENABLE_CVCUDA)
    find_library(CVCUDA_LIB cvcuda ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/cvcuda/lib NO_DEFAULT_PATH)
    find_library(NVCV_TYPES_LIB nvcv_types ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/cvcuda/lib NO_DEFAULT_PATH)
    list(APPEND ULTRAINFER_LIBS ${CVCUDA_LIB} ${NVCV_TYPES_LIB})
    list(APPEND ULTRAINFER_INCS ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/cvcuda/include NO_DEFAULT_PATH)
    add_definitions(-DENABLE_CVCUDA)
  endif()

endif()

if (ENABLE_TEXT)
  # Add dependency libs later: Linux/Mac/Win/...
  find_library(FAST_TOKENIZER_LIB core_tokenizers ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/fast_tokenizer/lib NO_DEFAULT_PATH)
  list(APPEND ULTRAINFER_LIBS ${FAST_TOKENIZER_LIB})

  list(APPEND ULTRAINFER_INCS ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/fast_tokenizer/include)
  list(APPEND ULTRAINFER_INCS ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/fast_tokenizer/third_party/include)
endif()

if(ENABLE_PADDLE2ONNX)
  if(NOT BUILD_PADDLE2ONNX)
    find_library(PADDLE2ONNX_LIB paddle2onnx  ${CMAKE_CURRENT_LIST_DIR}/third_libs/install/paddle2onnx/lib NO_DEFAULT_PATH)
    list(APPEND ULTRAINFER_LIBS ${PADDLE2ONNX_LIB})
  endif()
endif()

if(WITH_KUNLUNXIN)
  list(APPEND ULTRAINFER_LIBS -lpthread -lrt -ldl)
endif()

remove_duplicate_libraries(ULTRAINFER_LIBS)

include(${CMAKE_CURRENT_LIST_DIR}/summary.cmake)
ultra_infer_summary()
message(STATUS "  DEPENDENCY_LIBS           : ${ULTRAINFER_LIBS}")

if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
  if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.4.0")
    string(STRIP "${CMAKE_CXX_COMPILER_VERSION}" CMAKE_CXX_COMPILER_VERSION)
    message(FATAL_ERROR "[ERROR] UltraInfer require g++ version >= 5.4.0, but now your g++ version is ${CMAKE_CXX_COMPILER_VERSION}, this may cause failure! Use -DCMAKE_CXX_COMPILER to define path of your compiler.")
  endif()
endif()

function(install_ultra_infer_libraries DESTINATION_DIR)
  set(DYN_LIB_SUFFIX "*.so*")
  if(WIN32)
    set(DYN_LIB_SUFFIX "*.dll")
  elseif(APPLE)
    set(DYN_LIB_SUFFIX "*.dylib*")
  endif()
  if(UltraInfer_DIR)
    set(DYN_SEARCH_DIR ${UltraInfer_DIR})
  elseif(ULTRAINFER_INSTALL_DIR)
    set(DYN_SEARCH_DIR ${ULTRAINFER_INSTALL_DIR})
  else()
    message(FATAL_ERROR "Please set UltraInfer_DIR/ULTRAINFER_INSTALL_DIR before call install_ultra_infer_libraries.")
  endif()
  file(GLOB_RECURSE ALL_NEED_DYN_LIBS ${DYN_SEARCH_DIR}/lib/${DYN_LIB_SUFFIX})
  file(GLOB_RECURSE ALL_DEPS_DYN_LIBS ${DYN_SEARCH_DIR}/third_libs/${DYN_LIB_SUFFIX})

  if(ENABLE_VISION)
    # OpenCV
    file(GLOB_RECURSE ALL_OPENCV_DYN_LIBS ${OpenCV_DIR}/${DYN_LIB_SUFFIX})
    list(REMOVE_ITEM ALL_DEPS_DYN_LIBS ${ALL_OPENCV_DYN_LIBS})

    if(WIN32)
      file(GLOB OPENCV_DYN_LIBS ${OpenCV_DIR}/x64/vc15/bin/${DYN_LIB_SUFFIX})
      file(INSTALL ${OPENCV_DYN_LIBS} DESTINATION ${DESTINATION_DIR})
    else() # linux/mac
      file(GLOB OPENCV_DYN_LIBS ${OpenCV_DIR}/lib/${DYN_LIB_SUFFIX})
      file(INSTALL ${OPENCV_DYN_LIBS} DESTINATION ${DESTINATION_DIR})
    endif()

    # FlyCV
    if(ENABLE_FLYCV)
      file(GLOB_RECURSE ALL_FLYCV_DYN_LIBS ${FLYCV_LIB_DIR}/${DYN_LIB_SUFFIX})
      list(REMOVE_ITEM ALL_DEPS_DYN_LIBS ${ALL_FLYCV_DYN_LIBS})
    endif()
  endif()

  if(ENABLE_OPENVINO_BACKEND)
    # need plugins.xml for openvino backend
    set(OPENVINO_RUNTIME_BIN_DIR ${OPENVINO_DIR}/bin)
    file(GLOB OPENVINO_PLUGIN_XML ${OPENVINO_RUNTIME_BIN_DIR}/*.xml)
    file(INSTALL ${OPENVINO_PLUGIN_XML} DESTINATION ${DESTINATION_DIR})
  endif()

  # Install other libraries
  file(INSTALL ${ALL_NEED_DYN_LIBS} DESTINATION ${DESTINATION_DIR})
  file(INSTALL ${ALL_DEPS_DYN_LIBS} DESTINATION ${DESTINATION_DIR})
endfunction()
