cmake_minimum_required(VERSION 3.20)

set(CMAKE_PROJECT_INCLUDE_BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/cmake/ClioVersion.cmake)

project(clio VERSION ${CLIO_VERSION} HOMEPAGE_URL "https://github.com/XRPLF/clio"
        DESCRIPTION "An XRP Ledger API Server"
)

# =========================== Options ====================================== #
option(verbose "Verbose build" FALSE)
option(tests "Build unit tests" FALSE)
option(integration_tests "Build integration tests" FALSE)
option(benchmark "Build benchmarks" FALSE)
option(docs "Generate doxygen docs" FALSE)
option(coverage "Build test coverage report" FALSE)
option(packaging "Create distribution packages" FALSE)
option(lint "Run clang-tidy checks during compilation" FALSE)
option(static "Statically linked Clio" FALSE)
option(snapshot "Build snapshot tool" FALSE)

# ========================================================================== #
set(san "" CACHE STRING "Add sanitizer instrumentation")
set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
set_property(CACHE san PROPERTY STRINGS ";undefined;memory;address;thread")
# ========================================================================== #

set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})

# Include required modules
include(Ccache)
include(CheckCXXCompilerFlag)
include(ClangTidy)

add_library(clio_options INTERFACE)
target_compile_features(clio_options INTERFACE cxx_std_23) # Clio needs c++23 but deps can remain c++20 for now
target_include_directories(clio_options INTERFACE ${CMAKE_SOURCE_DIR}/src)

if (verbose)
  set(CMAKE_VERBOSE_MAKEFILE TRUE)
endif ()

if (packaging)
  add_definitions(-DPKG=1)
  target_compile_definitions(clio_options INTERFACE PKG=1)
endif ()

# Clio tweaks and checks
include(CheckCompiler)
include(Settings)
include(SourceLocation)

# Clio deps
include(deps/libxrpl)
include(deps/Boost)
include(deps/OpenSSL)
include(deps/Threads)
include(deps/libfmt)
include(deps/cassandra)
include(deps/libbacktrace)

add_subdirectory(src)
add_subdirectory(tests)

if (benchmark)
  add_subdirectory(benchmarks)
endif ()

# Enable selected sanitizer if enabled via `san`
if (san)
  set(SUPPORTED_SANITIZERS "address" "thread" "memory" "undefined")
  list(FIND SUPPORTED_SANITIZERS "${san}" INDEX)
  if (INDEX EQUAL -1)
    message(FATAL_ERROR "Error: Unsupported sanitizer '${san}'. Supported values are: ${SUPPORTED_SANITIZERS}.")
  endif ()

  target_compile_options(
    clio_options INTERFACE # Sanitizers recommend minimum of -O1 for reasonable performance
                           $<$<CONFIG:Debug>:-O1> ${SAN_FLAG} -fno-omit-frame-pointer
  )
  target_compile_definitions(
    clio_options INTERFACE $<$<STREQUAL:${san},address>:SANITIZER=ASAN> $<$<STREQUAL:${san},thread>:SANITIZER=TSAN>
                           $<$<STREQUAL:${san},memory>:SANITIZER=MSAN> $<$<STREQUAL:${san},undefined>:SANITIZER=UBSAN>
  )
  target_link_libraries(clio_options INTERFACE ${SAN_FLAG} ${SAN_LIB})
endif ()

# Generate `docs` target for doxygen documentation if enabled Note: use `make docs` to generate the documentation
if (docs)
  add_subdirectory(docs)
endif ()

include(install/install)
if (packaging)
  include(cmake/packaging.cmake) # This file exists only in build runner
endif ()

if (snapshot)
  add_subdirectory(tools/snapshot)
endif ()
