function(target_proto_generate)
  cmake_parse_arguments(
    PROTO
    ""
    "TARGET;GEN_DIR;SRC_DIR"
    "DEFINITIONS"
    ${ARGN}
  )

  message(STATUS "proto target: ${PROTO_TARGET}")
  message(STATUS "  proto output dir: ${PROTO_GEN_DIR}")
  message(STATUS "  proto src dir: ${PROTO_SRC_DIR}")

  # FIXME: remove hardcoded googleapis include below
  foreach (proto ${PROTO_DEFINITIONS})
    get_filename_component(_proto ${proto} ABSOLUTE)
    get_filename_component(_proto_path "${_proto}" PATH)
    get_filename_component(_proto_name ${proto} NAME_WLE)
    string(REPLACE ${PROTO_SRC_DIR} ${PROTO_GEN_DIR} _proto_gen_path ${_proto_path})

    message(STATUS "  proto generate [${_proto_name}] from ${_proto} to ${_proto_gen_path}")

    # Generated sources
    set(_proto_src "${_proto_gen_path}/${_proto_name}.pb.cc")
    set(_proto_hdr "${_proto_gen_path}/${_proto_name}.pb.h")
    add_custom_command(
      OUTPUT "${_proto_src}" "${_proto_hdr}"
      COMMAND ${PROTOBUF_PROTOC}
      ARGS
      --cpp_out "${PROTO_GEN_DIR}"
      --proto_path "${PROTO_SRC_DIR}"
      -I "${_proto_path}"
      -I "${CMAKE_SOURCE_DIR}/src/vereign/proto/googleapis"
      "${_proto}"
      DEPENDS "${_proto}")

    target_sources(${PROTO_TARGET} PRIVATE ${_proto_src})
  endforeach()
endfunction()

function(target_grpc_generate)
  cmake_parse_arguments(
    PROTO
    ""
    "TARGET;GEN_DIR;SRC_DIR"
    "DEFINITIONS"
    ${ARGN}
  )

  message(STATUS "grpc target: ${PROTO_TARGET}")
  message(STATUS "  grpc output dir: ${PROTO_GEN_DIR}")
  message(STATUS "  grpc src dir: ${PROTO_SRC_DIR}")

  # FIXME: remove hardcoded googleapis include below
  foreach (proto ${PROTO_DEFINITIONS})
    get_filename_component(_proto ${proto} ABSOLUTE)
    get_filename_component(_proto_path "${_proto}" PATH)
    get_filename_component(_proto_name ${proto} NAME_WLE)
    string(REPLACE ${PROTO_SRC_DIR} ${PROTO_GEN_DIR} _proto_gen_path ${_proto_path})

    message(STATUS "  grpc generate [${_proto_name}] from ${_proto} to ${_proto_gen_path}")

    # Generated sources
    set(_proto_src "${_proto_gen_path}/${_proto_name}.grpc.pb.cc")
    set(_proto_hdr "${_proto_gen_path}/${_proto_name}.grpc.pb.h")
    add_custom_command(
      OUTPUT "${_proto_src}" "${_proto_hdr}"
      COMMAND ${PROTOBUF_PROTOC}
      ARGS
      --grpc_out "${PROTO_GEN_DIR}"
      --cpp_out "${PROTO_GEN_DIR}"
      --proto_path "${PROTO_SRC_DIR}"
      -I "${_proto_path}"
      -I "${CMAKE_SOURCE_DIR}/src/vereign/proto/googleapis"
      --plugin=protoc-gen-grpc="${GRPC_CPP_PLUGIN_EXECUTABLE}"
      "${_proto}"
      DEPENDS "${_proto}")

    target_sources(${PROTO_TARGET} PRIVATE ${_proto_src})
  endforeach()
endfunction()