cmake_minimum_required(VERSION 3.20)

include(cmake/Utils.cmake)
include(cmake/Env.cmake)

project("OceanBase"
  VERSION 1.3.0.0
  DESCRIPTION "OceanBase seekdb database system"
  HOMEPAGE_URL "https://www.oceanbase.ai"
  LANGUAGES CXX C ASM)

if(WIN32)
  find_program(LLVM_LIB_PROGRAM llvm-lib)
  if(LLVM_LIB_PROGRAM)
    set(CMAKE_AR "${LLVM_LIB_PROGRAM}" CACHE FILEPATH "Archiver" FORCE)
  endif()
  add_compile_definitions(strncasecmp=_strnicmp strcasecmp=_stricmp)
endif()

if(ANDROID)
  # Boost headers use std::unary_function removed in C++17; NDK libc++ supports this compat macro
  add_definitions(-D_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION)
  # Force-include Android compat header for test code portability fixes
  add_compile_options(-include ${CMAKE_SOURCE_DIR}/include/android_compat.h)
endif()

if(ENABLE_COMPILE_DLL_MODE)
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DCOMPILE_DLL_MODE")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCOMPILE_DLL_MODE")
endif()

if(OB_ERRSIM)
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DERRSIM")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DERRSIM")
endif()

if(TRANS_MODULE_TEST)
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DTRANS_MODULE_TEST")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTRANS_MODULE_TEST")
endif()

# TODO: remove ENABLE_DEBUG_LOG
if(FALSE AND ENABLE_DEBUG_LOG)
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_DEBUG_LOG")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DENABLE_DEBUG_LOG")
  if(NOT DEFINED ENABLE_SERIALIZATION_CHECK)
    set(ENABLE_SERIALIZATION_CHECK ${ENABLE_DEBUG_LOG})
  endif()
endif()

if(ENABLE_SERIALIZATION_CHECK)
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_SERIALIZATION_CHECK")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DENABLE_SERIALIZATION_CHECK")
endif()

if (OB_GPERF_MODE)
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__NEED_PERF__")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__NEED_PERF__")
endif()

if (ENABLE_PERF_MODE)
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPERF_MODE")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPERF_MODE")
endif()

if (ENABLE_OBJ_LEAK_CHECK)
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_OBJ_LEAK_CHECK=1")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DENABLE_OBJ_LEAK_CHECK=1")
endif()

if (ENABLE_FATAL_ERROR_HANG)
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFATAL_ERROR_HANG")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DFATAL_ERROR_HANG")
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_500_MEMORY_LIMIT")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DENABLE_500_MEMORY_LIMIT")
endif()

if (DETECT_RECURSION)
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDETECT_RECURSION")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDETECT_RECURSION")
endif()

if(OB_USE_ASAN)
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DOB_USE_ASAN")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOB_USE_ASAN")
endif()

if (ENABLE_SANITY)
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_SANITY")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DENABLE_SANITY")
endif()

if (OB_BUILD_PACKAGE)
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DOB_BUILD_PACKAGE")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOB_BUILD_PACKAGE")
endif()

if (OB_ENABLE_MCMODEL)
  if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mcmodel=large")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcmodel=large")
  endif()
endif()

message(STATUS "This is BINARY dir " ${PROJECT_BINARY_DIR})
message(STATUS "This is SOURCE dir " ${PROJECT_SOURCE_DIR})

set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(STDC_SHARED_LIB "")
set(STDC_SHARED_LIB_SYMLINK "")

if(APPLE)
  set(CMAKE_NO_SYSTEM_FROM_IMPORTED 1)
  # Set CMake policy CMP0152 to suppress warning about file(REAL_PATH) behavior
  if(POLICY CMP0152)
    cmake_policy(SET CMP0152 NEW)
  endif()
  set(STDC_SHARED_LIB_SYMLINK "${DEVTOOLS_DIR}/lib64/libstdc++.dylib")
elseif(UNIX)
  set(STDC_SHARED_LIB_SYMLINK "${DEVTOOLS_DIR}/lib64/libstdc++.so")
endif()
# Disable Boost header deprecation warnings (clang uses -Wno-#pragma-messages)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-#pragma-messages")

# Only resolve path if it exists (on macOS, this directory may not exist)
if(EXISTS "${STDC_SHARED_LIB_SYMLINK}")
  file(REAL_PATH ${STDC_SHARED_LIB_SYMLINK} STDC_SHARED_LIB)
  message(STATUS "STDC_SHARED_LIB: ${STDC_SHARED_LIB}")
endif()

add_subdirectory(deps/oblib)
add_subdirectory(src/objit)
add_subdirectory(src)
add_subdirectory(sqlite-benchmark)

include(CMakeDependentOption)
# OB_BUILD_PACKAGE => include tools and build them.
# otherwise    => include tools but don't build them.
option(OB_INCLUDE_TOOLS "" ON)
cmake_dependent_option(
  OB_BUILD_TOOLS "Build tools" ON
  "OB_BUILD_PACKAGE" OFF)
# OB_BUILD_PACKAGE => don't include unittest or build them.
# otherwise    => include unittest but don't build them.
cmake_dependent_option(
  OB_INCLUDE_UNITTEST "Include unittest" ON
  "NOT OB_BUILD_PACKAGE" OFF)
option(OB_BUILD_UNITTEST "" OFF)

# OB_BUILD_PACKAGE => don't include test or build them.
# otherwise    => include test but don't build them.
cmake_dependent_option(
  OB_INCLUDE_TEST "Include test" ON
  "NOT OB_BUILD_PACKAGE" OFF)
option(OB_BUILD_TEST "" OFF)

# OB_BUILD_PACKAGE => build sql proxy parser
cmake_dependent_option(
  OB_BUILD_LIBOB_SQL_PROXY_PARSER "Build lib_sql_proxy_parser" OFF
  "NOT OB_BUILD_PACKAGE" ON
)

# OB_BUILD_PACKAGE => build OB_BUILD_LIBOBTABLE
cmake_dependent_option(
  OB_BUILD_LIBOBTABLE "Build liboblog" OFF
  "NOT OB_BUILD_PACKAGE" ON
)

# OB_BUILD_PACKAGE => build OB_BUILD_OBADMIN
cmake_dependent_option(
  OB_BUILD_OBADMIN "Build ob_admin" OFF
  "NOT OB_BUILD_PACKAGE" ON
)

include(CTest)
if (OB_BUILD_UNITTEST)
  add_subdirectory(unittest)
elseif(OB_INCLUDE_UNITTEST)
  add_subdirectory(unittest EXCLUDE_FROM_ALL)
endif()

if (OB_BUILD_TOOLS)
  add_subdirectory(tools)
elseif (OB_INCLUDE_TOOLS)
  add_subdirectory(tools EXCLUDE_FROM_ALL)
endif()

if(ANDROID)
  # Android: no packaging needed
elseif(APPLE)
  if(CMAKE_BUILD_TGZ)
    include(cmake/TGZ.cmake)
  endif()
elseif(UNIX)
  if (CMAKE_BUILD_RPM)
    include(cmake/RPM.cmake)
  elseif(CMAKE_BUILD_DEB)
    include(cmake/DEB.cmake)
  else()
    if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
      include(FindPkgConfig)
      if(PKG_CONFIG_FOUND)
        execute_process(
          COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=systemdsystemunitdir systemd
          RESULT_VARIABLE result_var
          OUTPUT_VARIABLE output_var
          ERROR_QUIET
          OUTPUT_STRIP_TRAILING_WHITESPACE
        )
        if("${result_var}" STREQUAL "0" AND "${output_var}" STREQUAL "/lib/systemd/system")
          include(cmake/DEB.cmake)
        else()
          include(cmake/RPM.cmake)
        endif()
      endif()
    else()
      message(FATAL_ERROR "Unsupported system: ${CMAKE_SYSTEM_NAME}")
    endif()
  endif()
elseif(WIN32)
  if(OB_BUILD_PACKAGE)
    message(STATUS "Windows package environment adapting")
    include(cmake/WIX.cmake)
  endif()
endif()
