cmake_minimum_required(VERSION 3.16)
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
  project(hprqp_native_polishing LANGUAGES C CXX)
  set(CMAKE_CXX_STANDARD 17)
  set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type")
endif()
get_filename_component(HPRQP_SOURCE_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../.." ABSOLUTE)
set(HPRQP_NATIVE_ROOT "${HPRQP_SOURCE_ROOT}/.deps/native" CACHE PATH
    "Private BLAS/LAPACK dependencies installed by make")
# Runtime libraries suffice; development symlinks are not present everywhere.
find_library(HPRQP_BLAS NAMES blas libblas.so.3 openblas HINTS "${HPRQP_NATIVE_ROOT}/lib")
find_library(HPRQP_LAPACK NAMES lapack liblapack.so.3 HINTS "${HPRQP_NATIVE_ROOT}/lib")
find_library(HPRQP_CRYPTO NAMES libcrypto.so.3 libcrypto.so.1.1)
if(NOT HPRQP_BLAS OR NOT HPRQP_LAPACK)
  message(FATAL_ERROR "HPRQP_NATIVE_BLAS_LAPACK_MISSING: Native CPU polishing requires BLAS and LAPACK. Run make setup-native for automatic local setup, or install libblas-dev/liblapack-dev.")
endif()
if(NOT HPRQP_CRYPTO)
  message(FATAL_ERROR "Native polishing publication requires OpenSSL libcrypto.so.3 or libcrypto.so.1.1.")
endif()
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_EXPORT_NO_PACKAGE_REGISTRY ON)
set(enable_single OFF CACHE BOOL "" FORCE)
set(enable_complex OFF CACHE BOOL "" FORCE)
set(enable_complex16 OFF CACHE BOOL "" FORCE)
set(enable_examples OFF CACHE BOOL "" FORCE)
set(enable_tests OFF CACHE BOOL "" FORCE)
set(enable_fortran OFF CACHE BOOL "" FORCE)
set(TPL_BLAS_LIBRARIES "${HPRQP_BLAS}" CACHE STRING "" FORCE)
add_subdirectory("${HPRQP_SOURCE_ROOT}/third_party/superlu" "${CMAKE_CURRENT_BINARY_DIR}/superlu" EXCLUDE_FROM_ALL)
add_library(hprqp_native_polish STATIC model.cpp system.cpp checker.cpp linalg.cpp access.cpp spatial.cpp episode.cpp)
target_compile_features(hprqp_native_polish PUBLIC cxx_std_17)
target_include_directories(hprqp_native_polish PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" "${HPRQP_SOURCE_ROOT}/third_party" "${HPRQP_SOURCE_ROOT}/third_party/eigen" PRIVATE "${HPRQP_SOURCE_ROOT}/third_party/superlu/SRC" "${CMAKE_CURRENT_BINARY_DIR}/superlu/SRC")
target_compile_definitions(hprqp_native_polish PUBLIC EIGEN_DONT_PARALLELIZE EIGEN_MPL2_ONLY)
target_link_libraries(hprqp_native_polish PUBLIC superlu "${HPRQP_LAPACK}" "${HPRQP_BLAS}")
add_executable(hprqp_polish_worker worker.cpp)
target_include_directories(hprqp_polish_worker PRIVATE "${HPRQP_SOURCE_ROOT}/src/shared")
target_link_libraries(hprqp_polish_worker PRIVATE hprqp_native_polish ${CMAKE_DL_LIBS})
add_executable(hprqp_polish_inspect EXCLUDE_FROM_ALL
  "${HPRQP_SOURCE_ROOT}/tests/polishing/native_inspect.cpp")
target_link_libraries(hprqp_polish_inspect PRIVATE hprqp_native_polish)

if(EXISTS "${HPRQP_NATIVE_ROOT}/lib")
  # Keep the worker relocatable without requiring an LD_LIBRARY_PATH override.
  # DT_RPATH is intentional: LAPACK's Fortran dependency is transitive.
  file(COPY "${HPRQP_NATIVE_ROOT}/lib/" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/lib")
  foreach(worker hprqp_polish_worker hprqp_polish_inspect)
    target_link_options(${worker} PRIVATE "LINKER:--disable-new-dtags"
      "LINKER:-rpath-link,${HPRQP_NATIVE_ROOT}/lib")
    set_target_properties(${worker} PROPERTIES
      BUILD_RPATH "$ORIGIN/lib;${HPRQP_NATIVE_ROOT}/lib"
      INSTALL_RPATH "$ORIGIN/lib")
    add_custom_command(TARGET ${worker} POST_BUILD
      COMMAND "${CMAKE_COMMAND}" -E copy_directory
              "${HPRQP_NATIVE_ROOT}/lib" "$<TARGET_FILE_DIR:${worker}>/lib")
  endforeach()
endif()
