cmake_minimum_required(VERSION 3.26)
project(secrethider VERSION 0.2.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)

if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  set(CMAKE_BUILD_TYPE Release)
endif()

option(SECRETHIDER_BUILD_TESTS  "Build C++ unit tests"        ${PROJECT_IS_TOP_LEVEL})
option(SECRETHIDER_BUILD_BENCH  "Build C++ benchmarks"        OFF)
option(SECRETHIDER_BUILD_PYTHON "Build the Python extension"  OFF)
option(SECRETHIDER_SANITIZE     "Enable ASan+UBSan (gcc/clang)" OFF)
option(SECRETHIDER_BUILD_FUZZ   "Build the libFuzzer target (clang)" OFF)
option(SECRETHIDER_WITH_RE2     "Custom regex rules via RE2 (pulls abseil)" ON)

if(MSVC)
  add_compile_options(/EHsc /utf-8)
endif()

if(SECRETHIDER_BUILD_TESTS)
  enable_testing()
endif()

# Sanitizers must reach every target (static libraries need them at the final link, and the
# dependencies should be instrumented too), so they are global rather than per target.
if(SECRETHIDER_SANITIZE AND NOT MSVC)
  add_compile_options(-fsanitize=address,undefined -fno-omit-frame-pointer)
  add_link_options(-fsanitize=address,undefined)
  if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
    # third-party sources are not ours to fix (RE2 constructs a zero-length array at a null pointer)
    add_compile_options(-fsanitize-ignorelist=${CMAKE_CURRENT_SOURCE_DIR}/.ubsan-ignorelist)
  endif()
endif()

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
include(Warnings)
include(Dependencies)

add_subdirectory(core)

if(SECRETHIDER_BUILD_PYTHON)
  add_subdirectory(bindings/python)
endif()
# The Node addon is built by cmake-js from bindings/node/CMakeLists.txt.
