cmake_minimum_required (VERSION 3.16.5)

if(WIN32)
  set(CMAKE_IGNORE_PATH "C:/Strawberry/c/bin")
endif()

project (vereign)

if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
  if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.0.24215.1")
    message(FATAL_ERROR "Microsoft Visual C++ version MSVC 19.0.24215.1 required")
  endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
  if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0")
    message(FATAL_ERROR "Insufficient clang version - clang 9.0+ required")
  endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
  if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "7.5")
    message(FATAL_ERROR "Insufficient GNU compiler version - 7.5+ required")
  endif()
else()
  message(WARNING "Unknown compiler...")
endif()

if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
  add_definitions(-D_WIN32_WINNT=0x0601)
  set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Release>:Release>")
  set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

  set(CMAKE_C_FLAGS "/DNDEBUG /DWIN32 /D_WINDOWS /W3")
  set(CMAKE_CXX_FLAGS "/DNDEBUG /DWIN32 /D_WINDOWS /W3 /GR /EHsc")

  set(CMAKE_C_FLAGS_DEBUG "/MTd /Zi /Ob0 /Od /RTC1")
  set(CMAKE_CXX_FLAGS_DEBUG "/MTd /Zi /Ob0 /Od /RTC1")

  set(CMAKE_CXX_FLAGS_RELEASE "/Gd /MT /O2 /Oi /Ot /Gy /Zi /GL")
  set(CMAKE_C_FLAGS_RELEASE "/Gd /MT /O2 /Oi /Ot /Gy /Zi /GL")

  if (CMAKE_BUILD_TYPE STREQUAL "Release")
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG /OPT:REF /OPT:ICF /LTCG")
    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUG /OPT:REF /OPT:ICF /LTCG")
    set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /LTCG")
  endif()
endif()

if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
  set(CMAKE_CXX_FLAGS_RELEASE "-g -O3 -Wall -Wextra -pedantic")
  set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra -pedantic")
endif()

if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    set(CMAKE_CXX_FLAGS_RELEASE "-g -O3 -Wall -Wextra -pedantic")
    set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra -pedantic")
endif()

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_EXTENSIONS OFF)

message("Generator: " "${CMAKE_GENERATOR}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY  "${CMAKE_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE}")

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

message("Build type: " "${CMAKE_BUILD_TYPE}")
message("CXX Flags: " "${CMAKE_CXX_FLAGS}")
message("CXX debug flags: " "${CMAKE_CXX_FLAGS_DEBUG}")
message("CXX release flags: " "${CMAKE_CXX_FLAGS_RELEASE}")
message("CXX linker flags: " "${CMAKE_EXE_LINKER_FLAGS}")
message("CXX dll linker flags: " "${CMAKE_SHARED_LINKER_FLAGS}")
message("CXX static linker flags: " "${CMAKE_STATIC_LINKER_FLAGS}")

string(TOLOWER "${CMAKE_BUILD_TYPE}" _build_type)
set(VENDOR_INSTALL_DIR ${CMAKE_SOURCE_DIR}/cmake-install-vendor-${_build_type} CACHE STRING "vendor directory")
message(STATUS "Using vendor install dir: ${VENDOR_INSTALL_DIR}")
#set(VENDOR_INSTALL_DIR /home/daniel/workspace/local)
set(_cmake_prefix_paths
  ${VENDOR_INSTALL_DIR}
  ${VENDOR_INSTALL_DIR}/grpc
)
set(CMAKE_PREFIX_PATH ${_cmake_prefix_paths} CACHE STRING "")

include(CMakeToolsHelpers OPTIONAL)
include(Helpers)
include(ProtoGenerate)

enable_testing()

find_package(fmt 6.2.0 REQUIRED)

set(OPENSSL_USE_STATIC_LIBS ON)
set(OPENSSL_ROOT_DIR ${VENDOR_INSTALL_DIR}/boringssl)
find_package(OpenSSL)

set(Boost_USE_STATIC_LIBS ON)
find_package(
  Boost
  1.72.0
  EXACT
  REQUIRED
  COMPONENTS regex thread system
)

find_package(Protobuf CONFIG REQUIRED)
message(STATUS "Using protobuf ${protobuf_VERSION}")
if(CMAKE_CROSSCOMPILING)
  find_program(PROTOBUF_PROTOC protoc)
else()
  set(PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)
endif()

# Find gRPC installation
# Looks for gRPCConfig.cmake file installed by gRPC's cmake installation.
find_package(gRPC CONFIG REQUIRED)
message(STATUS "Using gRPC ${gRPC_VERSION}")
if(CMAKE_CROSSCOMPILING)
  find_program(GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin)
else()
  set(GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_cpp_plugin>)
endif()

add_subdirectory("src")
add_subdirectory("tests")

get_target_property(_protobuflib_location protobuf::libprotobuf LOCATION)
get_target_property(_grpclib_location gRPC::grpc++ LOCATION)
get_target_property(_grpclib_reflection_location gRPC::grpc++_reflection LOCATION)
set(
  _grpc_libs
  ${_protobuflib_location}
  ${_grpclib_location}
  ${_grpclib_reflection_location}
)

string(TOUPPER "${CMAKE_BUILD_TYPE}" _build_type)
message(STATUS "summary of build options:

  Package version: ${VERSION}
  Library version: ${LT_CURRENT}:${LT_REVISION}:${LT_AGE}
  Install prefix:  ${CMAKE_INSTALL_PREFIX}
  Target system:   ${CMAKE_SYSTEM_NAME}
  Compiler:
    Build type:     ${CMAKE_BUILD_TYPE}
    C compiler:     ${CMAKE_C_COMPILER}
    CFLAGS:         ${CMAKE_C_FLAGS_${_build_type}} ${CMAKE_C_FLAGS}
    C++ compiler:   ${CMAKE_CXX_COMPILER}
    CXXFLAGS:       ${CMAKE_CXX_FLAGS_${_build_type}} ${CMAKE_CXX_FLAGS}
    WARNCFLAGS:     ${WARNCFLAGS}
    CXX1XCXXFLAGS:  ${CXX1XCXXFLAGS}
  Libs:
    fmt:            ${fmt_FOUND} [${fmt_VERSION}] (DIR='${fmt_DIR}')
    OpenSSL:        ${OpenSSL_FOUND} [${OPENSSL_VERSION}] (LIBS='${OPENSSL_LIBRARIES}')
    Zlib:           ${ZLIB_FOUND} [${ZLIB_VERSION_STRING}] (LIBS='${ZLIB_LIBRARIES}')
    Boost           ${Boost_FOUND} [${Boost_VERSION_STRING}] (DIR='${Boost_DIR}')
    Boost libs      ${Boost_LIBRARIES}
    gRPC            ${gRPC_FOUND} [${gRPC_VERSION}] (LIBS='${_grpc_libs}')
")