cmake_minimum_required(VERSION 3.16)

if(POLICY CMP0074)
    cmake_policy(SET CMP0074 NEW)
endif()
if(POLICY CMP0077)
    cmake_policy(SET CMP0077 NEW)
endif()

# Fix "unrecognized escape" issues when passing CMAKE_MODULE_PATH on Windows.
if(DEFINED CMAKE_MODULE_PATH)
    file(TO_CMAKE_PATH "${CMAKE_MODULE_PATH}" CMAKE_MODULE_PATH)
endif()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

# Must be set before project() because project() consumes it when configuring the compiler and SDK.
# A user-provided -DCMAKE_OSX_DEPLOYMENT_TARGET still takes precedence.
#
# CMAKE_SYSTEM_NAME can't be used before project(), so CMAKE_HOST_SYSTEM_NAME is used instead.
#
# When CMAKE_OSX_DEPLOYMENT_TARGET is bumped to >=26.0, FastFloat dependency won't be needed anymore
if(
    CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin"
    AND NOT DEFINED CMAKE_OSX_DEPLOYMENT_TARGET
)
    set(CMAKE_OSX_DEPLOYMENT_TARGET
        "15.0"
        CACHE STRING
        "Minimum macOS deployment version"
    )
endif()

project(xrpl)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

include(CompilationEnv)

if(is_gcc)
    # GCC-specific fixes
    add_compile_options(-Wno-unknown-pragmas -Wno-subobject-linkage)
    # -Wno-subobject-linkage can be removed when we upgrade GCC version to at least 13.3
elseif(is_clang)
    # Clang-specific fixes
    add_compile_options(-Wno-unknown-warning-option) # Ignore unknown warning options
elseif(is_msvc)
    # MSVC-specific fixes
    add_compile_options(/wd4068) # Ignore unknown pragmas
endif()

# Enable ccache to speed up builds.
include(Ccache)

if(thread_safety_analysis)
    add_compile_options(
        -Wthread-safety
        -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS
        -DXRPL_ENABLE_THREAD_SAFETY_ANNOTATIONS
    )
    add_compile_options("-stdlib=libc++")
    add_link_options("-stdlib=libc++")
endif()

include(CheckCXXCompilerFlag)
include(FetchContent)
include(ExternalProject)
include(CMakeFuncs) # must come *after* ExternalProject b/c it overrides one function in EP
if(target)
    message(
        FATAL_ERROR
        "The target option has been removed - use native cmake options to control build"
    )
endif()

include(PatchNixBinary)

include(XrplSanity)
include(XrplVersion)
include(XrplSettings)
# this check has to remain in the top-level cmake because of the early return statement
if(packages_only)
    if(NOT TARGET rpm)
        message(
            FATAL_ERROR
            "packages_only requested, but targets were not created - is docker installed?"
        )
    endif()
    return()
endif()
include(XrplCompiler)
include(XrplSanitizers)
include(XrplInterface)

option(only_docs "Include only the docs target?" FALSE)
include(XrplDocs)
if(only_docs)
    return()
endif()

include(deps/dilithium)
include(deps/Boost)

add_subdirectory(external/antithesis-sdk)
find_package(date REQUIRED)
find_package(ed25519 REQUIRED)
find_package(FastFloat REQUIRED)
find_package(gRPC REQUIRED)
find_package(LibArchive REQUIRED)
find_package(lz4 REQUIRED)
find_package(mpt-crypto REQUIRED)
find_package(nudb REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(secp256k1 REQUIRED)
find_package(SOCI REQUIRED)
find_package(SQLite3 REQUIRED)
find_package(xxHash REQUIRED)

target_link_libraries(
    xrpl_libs
    INTERFACE
        ed25519::ed25519
        FastFloat::fast_float
        lz4::lz4
        mpt-crypto::mpt-crypto
        OpenSSL::Crypto
        OpenSSL::SSL
        secp256k1::secp256k1
        soci::soci
        SQLite::SQLite3
)

option(rocksdb "Enable RocksDB" ON)
if(rocksdb)
    find_package(RocksDB REQUIRED)
    set_target_properties(
        RocksDB::rocksdb
        PROPERTIES INTERFACE_COMPILE_DEFINITIONS XRPL_ROCKSDB_AVAILABLE=1
    )
    target_link_libraries(xrpl_libs INTERFACE RocksDB::rocksdb)
endif()

# Work around changes to Conan recipe for now.
if(TARGET nudb::core)
    set(nudb nudb::core)
elseif(TARGET NuDB::nudb)
    set(nudb NuDB::nudb)
else()
    message(FATAL_ERROR "unknown nudb target")
endif()
target_link_libraries(xrpl_libs INTERFACE ${nudb})

if(benchmark)
    find_package(benchmark REQUIRED)
endif()

if(coverage)
    include(XrplCov)
endif()

add_custom_target(tidy_prerequisites)

if(rust)
    add_subdirectory(crates)
endif()
include(XrplCore)

include(XrplProtocolAutogen)
include(XrplInstall)
include(XrplValidatorKeys)
# Must come after XrplValidatorKeys: the 'package' target depends on the
# validator-keys target existing.
include(XrplPackaging)

if(tests)
    include(CTest)
    add_subdirectory(src/tests/libxrpl)
endif()

if(benchmark)
    add_subdirectory(src/benchmarks/libxrpl)
endif()
