cmake_minimum_required(VERSION 3.4)

project(common)

include(${CMAKE_CURRENT_LIST_DIR}/cmake/Common.cmake)

add_subdirectory(redis_module)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -g")

include_directories(thirdparty/ae)

# Compile flatbuffers

set(COMMON_FBS_SRC "${CMAKE_CURRENT_LIST_DIR}/format/common.fbs")
set(OUTPUT_DIR ${CMAKE_CURRENT_LIST_DIR}/format/)

set(COMMON_FBS_OUTPUT_FILES
  "${OUTPUT_DIR}/common_generated.h")

add_custom_command(
  OUTPUT ${COMMON_FBS_OUTPUT_FILES}
  # The --gen-object-api flag generates a C++ class MessageT for each
  # flatbuffers message Message, which can be used to store deserialized
  # messages in data structures. This is currently used for ObjectInfo for
  # example.
  COMMAND ${FLATBUFFERS_COMPILER} -c -o ${OUTPUT_DIR} ${COMMON_FBS_SRC} --gen-object-api --scoped-enums
  DEPENDS ${FBS_DEPENDS}
  COMMENT "Running flatc compiler on ${COMMON_FBS_SRC}"
  VERBATIM)

if ("${CMAKE_RAY_LANG_PYTHON}" STREQUAL "YES")
  add_custom_target(gen_common_python_fbs DEPENDS ${COMMON_FBS_OUTPUT_FILES})

  # Generate Python bindings for the flatbuffers objects.
  set(PYTHON_OUTPUT_DIR ${CMAKE_CURRENT_LIST_DIR}/../../python/ray/core/generated/)
  add_custom_command(
    TARGET gen_common_python_fbs
    COMMAND ${FLATBUFFERS_COMPILER} -p -o ${PYTHON_OUTPUT_DIR} ${COMMON_FBS_SRC}
    DEPENDS ${FBS_DEPENDS}
    COMMENT "Running flatc compiler on ${COMMON_FBS_SRC}"
    VERBATIM)

  # Encode the fact that the ray redis module requires the autogenerated
  # flatbuffer files to compile.
  add_dependencies(ray_redis_module gen_common_python_fbs)

  add_dependencies(gen_common_python_fbs flatbuffers_ep)
endif()

if ("${CMAKE_RAY_LANG_JAVA}" STREQUAL "YES")
  add_custom_target(gen_common_java_fbs DEPENDS ${COMMON_FBS_OUTPUT_FILES})

  # Generate Java bindings for the flatbuffers objects.
  set(JAVA_OUTPUT_DIR ${CMAKE_BINARY_DIR}/generated/java)
  add_custom_command(
    TARGET gen_common_java_fbs
    COMMAND ${FLATBUFFERS_COMPILER} -j -o ${JAVA_OUTPUT_DIR} ${COMMON_FBS_SRC}
    DEPENDS ${FBS_DEPENDS}
    COMMENT "Running flatc compiler on ${COMMON_FBS_SRC}"
    VERBATIM)

  # Encode the fact that the ray redis module requires the autogenerated
  # flatbuffer files to compile.
  add_dependencies(ray_redis_module gen_common_java_fbs)

  add_dependencies(gen_common_java_fbs flatbuffers_ep)
endif()

add_custom_target(
   hiredis
   COMMAND make
   WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/thirdparty/hiredis)

add_library(common STATIC
  event_loop.cc
  common.cc
  common_protocol.cc
  task.cc
  io.cc
  net.cc
  logging.cc
  state/redis.cc
  state/table.cc
  state/object_table.cc
  state/task_table.cc
  state/db_client_table.cc
  state/driver_table.cc
  state/actor_notification_table.cc
  state/local_scheduler_table.cc
  state/error_table.cc
  thirdparty/ae/ae.c
  thirdparty/sha256.c)

if ("${CMAKE_RAY_LANG_PYTHON}" STREQUAL "YES")
  add_dependencies(common gen_common_python_fbs)
endif()

if ("${CMAKE_RAY_LANG_JAVA}" STREQUAL "YES")
  add_dependencies(common gen_common_java_fbs)
endif()

target_link_libraries(common "${CMAKE_CURRENT_LIST_DIR}/thirdparty/hiredis/libhiredis.a")

function(define_test test_name library)
  add_executable(${test_name} test/${test_name}.cc ${ARGN})
  add_dependencies(${test_name} hiredis flatbuffers_ep)
  target_link_libraries(${test_name} common ${FLATBUFFERS_STATIC_LIB} ray_static ${PLASMA_STATIC_LIB} ${ARROW_STATIC_LIB} ${library} -lpthread)
  target_compile_options(${test_name} PUBLIC "-DPLASMA_TEST -DLOCAL_SCHEDULER_TEST -DCOMMON_TEST -DRAY_COMMON_LOG_LEVEL=4")
endfunction()

define_test(db_tests "")
define_test(io_tests "")
define_test(task_tests "")
define_test(redis_tests "")
define_test(task_table_tests "")
define_test(object_table_tests "")

add_custom_target(copy_redis ALL)
foreach(file "redis-cli" "redis-server")
add_custom_command(TARGET copy_redis POST_BUILD
                   COMMAND ${CMAKE_COMMAND} -E
                      copy ${CMAKE_CURRENT_LIST_DIR}/../../thirdparty/pkg/redis/src/${file}
                           ${CMAKE_BINARY_DIR}/src/common/thirdparty/redis/src/${file})
endforeach()
