cmake_minimum_required(VERSION 3.16)
project(avalabs-crypto-core CXX C)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# Treat this directory as the package root.
set(CRYPTO_CORE_ROOT "${CMAKE_CURRENT_SOURCE_DIR}")

option(CRYPTO_BUILD_WASM "Build for WebAssembly via Emscripten" OFF)

# secp256k1: vendored at deps/secp256k1 by scripts/setup-secp256k1.sh.
set(SECP256K1_DIR "${CRYPTO_CORE_ROOT}/deps/secp256k1")
if(NOT EXISTS "${SECP256K1_DIR}/CMakeLists.txt")
    message(FATAL_ERROR
        "libsecp256k1 not found at ${SECP256K1_DIR}.\n"
        "Run packages-internal/crypto-core/scripts/setup-secp256k1.sh first.")
endif()

# libsecp256k1 build flags — minimum we need + WASM-safe.
set(SECP256K1_BUILD_BENCHMARK OFF CACHE BOOL "" FORCE)
set(SECP256K1_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(SECP256K1_BUILD_EXHAUSTIVE_TESTS OFF CACHE BOOL "" FORCE)
set(SECP256K1_BUILD_CTIME_TESTS OFF CACHE BOOL "" FORCE)
set(SECP256K1_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(SECP256K1_ENABLE_MODULE_EXTRAKEYS ON CACHE BOOL "" FORCE)
set(SECP256K1_ENABLE_MODULE_RECOVERY ON CACHE BOOL "" FORCE)
set(SECP256K1_ENABLE_MODULE_SCHNORRSIG ON CACHE BOOL "" FORCE)
set(SECP256K1_ENABLE_MODULE_ELLSWIFT OFF CACHE BOOL "" FORCE)
set(SECP256K1_INSTALL OFF CACHE BOOL "" FORCE)
# Disable assembly — Emscripten doesn't support x86_64 asm, and the WASM
# target wouldn't see speedup from it anyway.
set(SECP256K1_ASM "OFF" CACHE STRING "" FORCE)

add_subdirectory("${SECP256K1_DIR}" "${CMAKE_BINARY_DIR}/secp256k1-build" EXCLUDE_FROM_ALL)

# Portable backend sources.
set(CRYPTO_PORTABLE_SRC
    src/backends/portable/secure_zero.cpp
    src/backends/portable/sha256.cpp
    src/backends/portable/sha512.cpp
    src/backends/portable/hmac_sha512.cpp
    src/backends/portable/ripemd160.cpp
    src/backends/portable/ed25519.cpp
)

add_library(avalabs-crypto-core STATIC ${CRYPTO_PORTABLE_SRC})
target_include_directories(avalabs-crypto-core PUBLIC
    "${CRYPTO_CORE_ROOT}/include"
)
target_link_libraries(avalabs-crypto-core PUBLIC secp256k1)

# Reasonable warnings — but don't make them fatal (libsecp256k1's headers
# trip some warning levels on certain compilers).
if(NOT MSVC)
    target_compile_options(avalabs-crypto-core PRIVATE
        -Wall -Wextra -Wpedantic
        -Wno-unused-parameter
    )
endif()

if(CRYPTO_BUILD_WASM)
    # Optimize for size, no exceptions tracking overhead unless needed.
    target_compile_options(avalabs-crypto-core PRIVATE -O3 -fno-rtti)
endif()

# Tests — opt-in. The Nitro and WASM consumers don't need them; only the
# host-side `pnpm --filter @avalabs/crypto-core test` flow turns this on.
option(CRYPTO_BUILD_TESTS "Build crypto-core unit tests (host-only)" OFF)
if(CRYPTO_BUILD_TESTS)
    enable_testing()
    add_subdirectory(test)
endif()
