# service-ple: Flash-Next / Engram-style PLE tables served over the network (server + per-machine agent + client library)
cmake_minimum_required(VERSION 3.22)
project(service-ple LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
option(SPLE_SANITIZE "Build with AddressSanitizer and UBSan" OFF)
if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE RelWithDebInfo)
endif()
add_compile_options(-Wall -Wextra)
if(SPLE_SANITIZE)
  add_compile_options(-fsanitize=address,undefined -fno-omit-frame-pointer)
  add_link_options(-fsanitize=address,undefined)
endif()
find_package(Threads REQUIRED)

add_library(sple_tabla STATIC lib/tabla.cpp)
target_include_directories(sple_tabla PUBLIC lib)

# client library with a C ABI (ctypes from Python engines, direct link from C++ engines)
add_library(serviceple SHARED lib/cliente.cpp)
target_include_directories(serviceple PUBLIC lib)
target_link_libraries(serviceple PRIVATE Threads::Threads ${CMAKE_DL_LIBS})

# Python wheels (scikit-build-core). SPLE_WHEEL=plugin (pyproject.toml at the root): only the client library, inside the vllm_service_ple
# package. SPLE_WHEEL=servicios (packaging/service-ple): the server, the agent and the installer as commands (see the end of this file).
set(SPLE_WHEEL "plugin" CACHE STRING "which wheel scikit-build-core is building")
if(SKBUILD AND SPLE_WHEEL STREQUAL "plugin")
  install(TARGETS serviceple LIBRARY DESTINATION vllm_service_ple)
  return()
endif()

add_executable(service-ple-server server/main.cpp)
target_link_libraries(service-ple-server PRIVATE sple_tabla Threads::Threads)

add_executable(service-ple-agent agent/main.cpp lib/cliente.cpp)
target_link_libraries(service-ple-agent PRIVATE sple_tabla Threads::Threads ${CMAKE_DL_LIBS})

foreach(t prueba caidas perdidas robustez preferido)
  add_executable(service-ple-test-${t} tests/${t}.cpp lib/cliente.cpp)
  target_link_libraries(service-ple-test-${t} PRIVATE sple_tabla Threads::Threads ${CMAKE_DL_LIBS})
endforeach()

# measurement tools: load generator (any destination) and 4 KB random reads (the disk behind an agent without a server)
add_executable(service-ple-carga bench/carga.cpp)
target_link_libraries(service-ple-carga PRIVATE serviceple Threads::Threads)
add_executable(service-ple-lecturas bench/lecturas.cpp)
target_link_libraries(service-ple-lecturas PRIVATE Threads::Threads)

if(SKBUILD)
  # native executables in the environment's bin/ (wheel .data/scripts: no Python wrapper); the installer finds them next to itself
  install(TARGETS service-ple-server service-ple-agent service-ple-lecturas RUNTIME DESTINATION ${SKBUILD_SCRIPTS_DIR})
  install(PROGRAMS deploy/install.sh DESTINATION ${SKBUILD_SCRIPTS_DIR} RENAME service-ple-install)
  return()
endif()

install(TARGETS service-ple-server service-ple-agent serviceple)
