cmake_minimum_required(VERSION 3.20)
project(DeriWeavePython VERSION 0.3.0 LANGUAGES CXX)

option(DERIWEAVE_PY_BUILD_TESTS "Build native tests and the Python reference executable" OFF)
option(DERIWEAVE_ENABLE_OPENMP "Enable native OpenMP pricing (runtime required)" OFF)
if(NOT DEFINED DERIWEAVE_SOURCE_DIR)
  if(DEFINED ENV{DERIWEAVE_CPP_DIR} AND NOT "$ENV{DERIWEAVE_CPP_DIR}" STREQUAL "")
    set(DERIWEAVE_SOURCE_DIR "$ENV{DERIWEAVE_CPP_DIR}" CACHE PATH "DeriWeave C++ sources")
  else()
    set(DERIWEAVE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/deriweave" CACHE PATH "DeriWeave C++ sources")
  endif()
endif()
if(NOT EXISTS "${DERIWEAVE_SOURCE_DIR}/CMakeLists.txt")
  message(FATAL_ERROR "DeriWeave C++ sources missing. Run python prepare_windows.py or set DERIWEAVE_SOURCE_DIR.")
endif()
find_package(Eigen3 3.4 QUIET NO_MODULE)
if(NOT Eigen3_FOUND)
  set(DERIWEAVE_EIGEN_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/eigen-source")
  if(NOT EXISTS "${DERIWEAVE_EIGEN_INCLUDE_DIR}/Eigen/Core")
    message(FATAL_ERROR "Eigen 3.4+ missing. Install Eigen or run python prepare_windows.py.")
  endif()
  include(CMakePackageConfigHelpers)
  set(Eigen3_DIR "${CMAKE_CURRENT_BINARY_DIR}/eigen-package")
  file(MAKE_DIRECTORY "${Eigen3_DIR}")
  configure_file(cmake/Eigen3Config.cmake.in "${Eigen3_DIR}/Eigen3Config.cmake" @ONLY)
  write_basic_package_version_file("${Eigen3_DIR}/Eigen3ConfigVersion.cmake"
    VERSION 3.4.0 COMPATIBILITY SameMajorVersion ARCH_INDEPENDENT)
  find_package(Eigen3 3.4 REQUIRED NO_MODULE)
endif()
set(DERIWEAVE_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(DERIWEAVE_BUILD_TESTS ${DERIWEAVE_PY_BUILD_TESTS} CACHE BOOL "" FORCE)
if(DERIWEAVE_PY_BUILD_TESTS)
  include(CTest)
endif()
find_package(Python COMPONENTS Interpreter Development.Module REQUIRED)
set(PYBIND11_FINDPYTHON ON)
find_package(pybind11 3.0 CONFIG REQUIRED)
add_subdirectory("${DERIWEAVE_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/deriweave_cpp" EXCLUDE_FROM_ALL)
pybind11_add_module(_core NO_EXTRAS bindings/module.cpp bindings/composition.cpp)
target_compile_features(_core PRIVATE cxx_std_20)
target_link_libraries(_core PRIVATE DeriWeave::deriweave_core)
install(TARGETS _core LIBRARY DESTINATION deriweave_py COMPONENT python RUNTIME DESTINATION deriweave_py COMPONENT python)
install(FILES "${DERIWEAVE_SOURCE_DIR}/LICENSE" DESTINATION deriweave_py/licenses
        RENAME DeriWeave-LICENSE COMPONENT python)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/vendor/eigen-source/COPYING.MPL2")
  install(FILES vendor/eigen-source/COPYING.MPL2 vendor/eigen-source/COPYING.BSD
                vendor/eigen-source/COPYING.MINPACK vendor/eigen-source/COPYING.README
          DESTINATION deriweave_py/licenses COMPONENT python)
endif()
if(DERIWEAVE_PY_BUILD_TESTS)
  add_custom_target(native_tests)
  get_property(_native_targets DIRECTORY "${DERIWEAVE_SOURCE_DIR}" PROPERTY BUILDSYSTEM_TARGETS)
  foreach(_target IN LISTS _native_targets)
    if(_target MATCHES "_tests$")
      add_dependencies(native_tests "${_target}")
    endif()
  endforeach()
  add_executable(native_reference tests/native_reference.cpp)
  target_link_libraries(native_reference PRIVATE DeriWeave::deriweave_core)
endif()
