cmake_minimum_required(VERSION 3.18)
project(ripple_hpc LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

# Python + NumPy
find_package(Python COMPONENTS Interpreter Development.Module NumPy REQUIRED)

execute_process(
  COMMAND "${Python_EXECUTABLE}" -c "import numpy as np, sys; sys.stdout.write(str(np.lib.NumpyVersion(np.__version__).major))"
  OUTPUT_VARIABLE _numpy_major
  OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(_numpy_major VERSION_LESS "2")
  message(WARNING "Building Ripple extensions with NumPy 1.x headers will not produce binaries that are simultaneously compatible with NumPy 1.26 and 2.x. Prefer NumPy >= 2.0 headers.")
endif()

execute_process(
  COMMAND "${Python_EXECUTABLE}" -m pybind11 --cmakedir
  OUTPUT_VARIABLE _pybind11_cmake_dir
  OUTPUT_STRIP_TRAILING_WHITESPACE
)
list(APPEND CMAKE_PREFIX_PATH "${_pybind11_cmake_dir}")

# pybind11 is provided by the build environment from pyproject.toml.
find_package(pybind11 CONFIG REQUIRED)

# Avoid deprecated NumPy C API entry points.
add_compile_definitions(NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION)

# Define one pybind11 extension and install it into ripple/kernel.
function(add_ripple_ext modname source)
  pybind11_add_module(${modname} MODULE ${source})
  target_link_libraries(${modname} PRIVATE Python::Module Python::NumPy)

  if (MSVC)
    target_compile_options(${modname} PRIVATE /O2 /DNDEBUG /bigobj /EHsc /utf-8)
  else()
    target_compile_options(${modname} PRIVATE -O3 -DNDEBUG -fvisibility=hidden)
  endif()

  install(TARGETS ${modname}
    LIBRARY DESTINATION ripple/kernel
    RUNTIME DESTINATION ripple/kernel
    ARCHIVE DESTINATION ripple/kernel
  )
endfunction()

# Source paths are relative to the project root.
add_ripple_ext(rdf_ext        ripple/kernel/rdf_ext.cpp)
add_ripple_ext(ssf_ext        ripple/kernel/ssf_ext.cpp)
add_ripple_ext(vhf_ext        ripple/kernel/vhf_ext.cpp)
add_ripple_ext(isf_ext        ripple/kernel/isf_ext.cpp)
add_ripple_ext(fpcf_ext       ripple/kernel/fpcf_ext.cpp)
add_ripple_ext(msd_ext        ripple/kernel/msd_ext.cpp)
add_ripple_ext(cmsd_ext       ripple/kernel/cmsd_ext.cpp)
add_ripple_ext(alpha2_ext     ripple/kernel/alpha2_ext.cpp)
add_ripple_ext(kappa4_ext     ripple/kernel/kappa4_ext.cpp)
add_ripple_ext(block_mcmc_ext ripple/kernel/block_mcmc_ext.cpp)
