cmake_minimum_required(VERSION 3.24)
project(NIRYUKTI VERSION 0.2.1 LANGUAGES CXX)
# Preferred public spelling; existing build scripts retain their legacy options.
foreach(feature CUDA OPENMP SPARSE_LU SANITIZE)
 if(DEFINED NIRYUKTI_${feature})
  set(VANTAGE_${feature} ${NIRYUKTI_${feature}} CACHE BOOL "NIRYUKTI build option" FORCE)
 endif()
endforeach()
option(VANTAGE_CUDA "Build CUDA backend" OFF)
option(VANTAGE_HIP "Build experimental HIP/hipSPARSE backend" OFF)
if(VANTAGE_CUDA AND VANTAGE_HIP)
 message(FATAL_ERROR "Choose CUDA or HIP in a build, not both")
endif()
option(VANTAGE_SPARSE_LU "Use vendored Eigen sparse numerical basis factorization" ON)
option(VANTAGE_OPENMP "Use OpenMP" ON)
option(VANTAGE_SANITIZE "Enable address and undefined behavior sanitizers" OFF)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_library(vantage src/model.cpp src/certificate.cpp src/io.cpp src/verify.cpp src/preprocess.cpp src/cpu.cpp src/solver.cpp src/mip.cpp src/research.cpp src/simplex.cpp src/cuts.cpp src/barrier.cpp src/portfolio.cpp src/advisor.cpp)
target_include_directories(vantage PUBLIC include PRIVATE third_party)
set_target_properties(vantage PROPERTIES POSITION_INDEPENDENT_CODE ON)
if(VANTAGE_SPARSE_LU)
 target_include_directories(vantage SYSTEM PRIVATE third_party/eigen)
 target_compile_definitions(vantage PRIVATE VANTAGE_SPARSE_LU EIGEN_DONT_PARALLELIZE)
endif()
find_package(Threads REQUIRED)
target_link_libraries(vantage PRIVATE Threads::Threads)
target_compile_options(vantage PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Wall;-Wextra;-Wpedantic>)
if(VANTAGE_OPENMP)
 find_package(OpenMP)
 if(OpenMP_CXX_FOUND)
  target_link_libraries(vantage PUBLIC OpenMP::OpenMP_CXX)
 endif()
endif()
if(VANTAGE_CUDA)
 enable_language(CUDA)
 find_package(CUDAToolkit REQUIRED)
 target_sources(vantage PRIVATE src/cuda.cu)
 target_compile_definitions(vantage PUBLIC VANTAGE_HAS_CUDA)
 target_link_libraries(vantage PRIVATE CUDA::cudart CUDA::cusparse)
 set_target_properties(vantage PROPERTIES CUDA_STANDARD 17 CUDA_STANDARD_REQUIRED ON)
elseif(VANTAGE_HIP)
 enable_language(HIP)
 find_package(hip REQUIRED CONFIG)
 find_package(hipsparse REQUIRED CONFIG)
 set_source_files_properties(src/cuda.cu PROPERTIES LANGUAGE HIP)
 target_sources(vantage PRIVATE src/cuda.cu)
 target_compile_definitions(vantage PUBLIC VANTAGE_HAS_HIP)
 target_link_libraries(vantage PRIVATE hip::host roc::hipsparse)
 set_target_properties(vantage PROPERTIES HIP_STANDARD 17 HIP_STANDARD_REQUIRED ON)
else()
 target_sources(vantage PRIVATE src/cuda_stub.cpp)
endif()
if(VANTAGE_SANITIZE)
 target_compile_options(vantage PUBLIC -fsanitize=address,undefined -fno-omit-frame-pointer)
 target_link_options(vantage PUBLIC -fsanitize=address,undefined)
endif()
add_executable(vantage_cli app/main.cpp)
add_library(vantage_c SHARED src/c_api.cpp)
target_include_directories(vantage_c PRIVATE third_party)
target_link_libraries(vantage_c PRIVATE vantage)
set_target_properties(vantage_c PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON OUTPUT_NAME niryukti_c)
add_custom_command(TARGET vantage_c POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy
 $<TARGET_FILE:vantage_c> ${CMAKE_CURRENT_BINARY_DIR}/libvantage_c${CMAKE_SHARED_LIBRARY_SUFFIX})
add_library(NIRYUKTI::core ALIAS vantage)
set_target_properties(vantage_cli PROPERTIES OUTPUT_NAME niryukti)
target_include_directories(vantage_cli PRIVATE third_party)
target_link_libraries(vantage_cli PRIVATE vantage)
# Keep existing developer scripts working while the installed CLI uses NIRYUKTI.
add_custom_command(TARGET vantage_cli POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy
 $<TARGET_FILE:vantage_cli> ${CMAKE_CURRENT_BINARY_DIR}/vantage${CMAKE_EXECUTABLE_SUFFIX})
include(CTest)
if(BUILD_TESTING)
add_executable(vantage_tests tests/test_core.cpp)
target_link_libraries(vantage_tests PRIVATE vantage)
add_test(NAME core COMMAND vantage_tests)
add_executable(niryukti_advisor_tests tests/test_advisor.cpp)
target_link_libraries(niryukti_advisor_tests PRIVATE vantage)
add_test(NAME advisor COMMAND niryukti_advisor_tests)
add_executable(vantage_research_tests tests/test_research.cpp)
target_link_libraries(vantage_research_tests PRIVATE vantage)
add_test(NAME research COMMAND vantage_research_tests)
add_executable(vantage_certificate_tests tests/test_certificate.cpp)
target_include_directories(vantage_certificate_tests PRIVATE third_party src)
target_link_libraries(vantage_certificate_tests PRIVATE vantage)
add_test(NAME certificates COMMAND vantage_certificate_tests)
set_tests_properties(core research PROPERTIES WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
endif()
if(SKBUILD)
 install(TARGETS vantage_cli RUNTIME DESTINATION vantage/_native/bin)
 install(TARGETS vantage_c LIBRARY DESTINATION vantage/_native/lib RUNTIME DESTINATION vantage/_native/lib)
 install(FILES LICENSE NOTICE third_party/JSON-LICENSE.MIT third_party/eigen/COPYING.MPL2 third_party/eigen/COPYING.BSD third_party/eigen/COPYING.MINPACK third_party/eigen/COPYING.APACHE third_party/eigen/COPYING.README DESTINATION vantage/_native/licenses)
else()
install(TARGETS vantage vantage_cli vantage_c)
install(DIRECTORY include/vantage include/niryukti DESTINATION include)
endif()

execute_process(COMMAND git rev-parse HEAD WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
 OUTPUT_VARIABLE VANTAGE_COMMIT OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
if(VANTAGE_COMMIT MATCHES "^[0-9a-f]+$")
 target_compile_definitions(vantage PRIVATE VANTAGE_GIT_COMMIT="${VANTAGE_COMMIT}")
endif()
