# packages/optfuncs-cuda130/CMakeLists.txt
#
# Build entrypoint for the optfuncs-cuda130 addon wheel. This project reuses the
# native cone sources from the repository root but installs the CUDA extension
# into the independent optfuncs_cuda130 Python package.

cmake_minimum_required(VERSION 3.26...3.31)

option(OPTFUNC_WITH_CUDA
        "Build native cone CUDA code for the cu130 addon"
        ON
)

if (NOT OPTFUNC_WITH_CUDA)
  message(FATAL_ERROR "optfuncs-cuda130 must be built with OPTFUNC_WITH_CUDA=ON")
endif()

if (NOT DEFINED CMAKE_CUDA_ARCHITECTURES AND NOT DEFINED ENV{CUDAARCHS})
  set(CMAKE_CUDA_ARCHITECTURES "75;80;86;89;90" CACHE STRING
          "CUDA architectures for optfuncs-cuda130 wheels"
  )
endif()

project(optfuncs_cuda130_native LANGUAGES CXX CUDA)

if (MSVC)
  add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:/utf-8>")
  add_compile_options("$<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/utf-8>")
endif()

if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CUDA_STANDARD 17)
set(CMAKE_CUDA_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_CUDA_SEPARABLE_COMPILATION ON)

find_package(Python 3.12 COMPONENTS Interpreter Development.Module REQUIRED)

if (NOT nanobind_DIR)
  execute_process(
          COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir
          OUTPUT_VARIABLE _nanobind_cmake_dir
          OUTPUT_STRIP_TRAILING_WHITESPACE
          RESULT_VARIABLE _nanobind_cmake_dir_result
  )
  if (_nanobind_cmake_dir_result EQUAL 0 AND EXISTS "${_nanobind_cmake_dir}")
    set(nanobind_DIR "${_nanobind_cmake_dir}" CACHE PATH "nanobind CMake config directory")
  endif()
endif()

find_package(nanobind CONFIG REQUIRED)
find_package(CUDAToolkit REQUIRED)
find_package(OpenMP COMPONENTS CXX)

set(OPTFUNC_BLAS "AUTO" CACHE STRING
        "Host BLAS selection for native cones: AUTO, OFF, SYSTEM, or OPENBLAS"
)
set_property(CACHE OPTFUNC_BLAS PROPERTY STRINGS AUTO OFF SYSTEM OPENBLAS)
string(TOUPPER "${OPTFUNC_BLAS}" OPTFUNC_BLAS_UPPER)
if (OPTFUNC_BLAS_UPPER STREQUAL "OFF")
  message(STATUS "optfunc native cones: host BLAS disabled")
elseif (OPTFUNC_BLAS_UPPER STREQUAL "OPENBLAS")
  set(BLA_VENDOR OpenBLAS)
  find_package(BLAS REQUIRED)
elseif (OPTFUNC_BLAS_UPPER STREQUAL "SYSTEM")
  find_package(BLAS REQUIRED)
elseif (OPTFUNC_BLAS_UPPER STREQUAL "AUTO")
  find_package(BLAS QUIET)
else()
  message(FATAL_ERROR
          "OPTFUNC_BLAS must be one of AUTO, OFF, SYSTEM, or OPENBLAS; got ${OPTFUNC_BLAS}"
  )
endif()

option(OPTFUNC_USE_CUBLAS
        "Link cuBLAS for native cone CUDA dense-helper implementations"
        OFF
)

set(OPTFUNC_CUDA_ADDON ON CACHE BOOL "Build the optfuncs-cuda130 addon" FORCE)
set(OPTFUNC_NATIVE_TARGET "_cpp_cuda" CACHE STRING "CUDA addon extension target" FORCE)
set(OPTFUNC_NATIVE_INSTALL_DIR "optfuncs_cuda130" CACHE STRING
        "CUDA addon Python package install directory"
        FORCE
)

add_subdirectory(
        "${CMAKE_CURRENT_LIST_DIR}/../../src/optfunc/cvxs/cones/cpp"
        "${CMAKE_CURRENT_BINARY_DIR}/cones_cpp"
)
