#########
# Local rewrite of the protobuf support in cmake.
#
# Supports cross-module protobuf dependencies and protobufs inside
# packages much better than the one built into cmake.
#########
#
# Locate and configure the Google Protocol Buffers library.
# Defines the following variables:
#
#   PROTOBUF_FOUND - Found the Google Protocol Buffers library
#   PROTOBUF_INCLUDE_DIRS - Include directories for Google Protocol Buffers
#   PROTOBUF_LIBRARIES - The protobuf library
#
# The following cache variables are also defined:
#   PROTOBUF_LIBRARY - The protobuf library
#   PROTOBUF_STATIC_LIBRARY - The protobuf library (static link)
#   PROTOBUF_PROTOC_LIBRARY   - The protoc library
#   PROTOBUF_INCLUDE_DIR - The include directory for protocol buffers
#   PROTOBUF_PROTOC_EXECUTABLE - The protoc compiler
#
#  ====================================================================
#  Example:
#
#   find_package(Protobuf REQUIRED)
#   include_directories(${PROTOBUF_INCLUDE_DIRS})
#
#   include_directories(${CMAKE_CURRENT_BINARY_DIR})
#   PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS PROTO_TGTS
#     [SOURCE_ROOT <root from which source is found>]
#     [BINARY_ROOT <root into which binaries are built>]
#     PROTO_FILES foo.proto)
#   add_executable(bar bar.cc ${PROTO_SRCS} ${PROTO_HDRS})
#   target_link_libraries(bar ${PROTOBUF_LIBRARY})
#
# NOTE: You may need to link against pthreads, depending
# on the platform.
#  ====================================================================
#
# PROTOBUF_GENERATE_CPP (public function)
#   SRCS = Variable to define with autogenerated
#          source files
#   HDRS = Variable to define with autogenerated
#          header files
#   TGTS = Variable to define with autogenerated
#          custom targets; if SRCS/HDRS need to be used in multiple
#          libraries, those libraries should depend on these targets
#          in order to "serialize" the protoc invocations
#  ====================================================================


#=============================================================================
# Copyright 2011 Kirill A. Korinskiy <catap@catap.ru>
# Copyright 2009 Kitware, Inc.
# Copyright 2009 Philip Lowman <philip@yhbt.com>
# Copyright 2008 Esben Mose Hansen, Ange Optimization ApS
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distributed this file outside of CMake, substitute the full
#  License text for the above reference.)

function(PROTOBUF_GENERATE_CPP SRCS HDRS TGTS)
  if(NOT ARGN)
    message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files")
    return()
  endif(NOT ARGN)

  set(options)
  set(one_value_args SOURCE_ROOT BINARY_ROOT)
  set(multi_value_args EXTRA_PROTO_PATHS PROTO_FILES)
  cmake_parse_arguments(ARG "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
  if(ARG_UNPARSED_ARGUMENTS)
    message(SEND_ERROR "Error: unrecognized arguments: ${ARG_UNPARSED_ARGUMENTS}")
  endif()

  set(${SRCS})
  set(${HDRS})
  set(${TGTS})

  set(EXTRA_PROTO_PATH_ARGS)
  foreach(PP ${ARG_EXTRA_PROTO_PATHS})
    set(EXTRA_PROTO_PATH_ARGS ${EXTRA_PROTO_PATH_ARGS} --proto_path ${PP})
  endforeach()

  if("${ARG_SOURCE_ROOT}" STREQUAL "")
    SET(ARG_SOURCE_ROOT "${CMAKE_CURRENT_SOURCE_DIR}")
  endif()
  GET_FILENAME_COMPONENT(ARG_SOURCE_ROOT ${ARG_SOURCE_ROOT} ABSOLUTE)

  if("${ARG_BINARY_ROOT}" STREQUAL "")
    SET(ARG_BINARY_ROOT "${CMAKE_CURRENT_BINARY_DIR}")
  endif()
  GET_FILENAME_COMPONENT(ARG_BINARY_ROOT ${ARG_BINARY_ROOT} ABSOLUTE)

  foreach(FIL ${ARG_PROTO_FILES})
    get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
    get_filename_component(FIL_WE ${FIL} NAME_WE)

    # Ensure that the protobuf file is within the source root.
    # This is a requirement of protoc.
    FILE(RELATIVE_PATH PROTO_REL_TO_ROOT "${ARG_SOURCE_ROOT}" "${ABS_FIL}")

    GET_FILENAME_COMPONENT(REL_DIR "${PROTO_REL_TO_ROOT}" PATH)

    if(NOT REL_DIR STREQUAL "")
      SET(REL_DIR "${REL_DIR}/")
    endif()

    set(PROTO_CC_OUT "${ARG_BINARY_ROOT}/${REL_DIR}${FIL_WE}.pb.cc")
    set(PROTO_H_OUT "${ARG_BINARY_ROOT}/${REL_DIR}${FIL_WE}.pb.h")
    list(APPEND ${SRCS} "${PROTO_CC_OUT}")
    list(APPEND ${HDRS} "${PROTO_H_OUT}")

    if(NOT EXISTS ${PROTO_DST_ROOT}/${FIL_PT})
        file(MAKE_DIRECTORY ${PROTO_DST_ROOT}/${FIL_PT})
    endif()

    add_custom_command(
      OUTPUT "${PROTO_CC_OUT}" "${PROTO_H_OUT}"
      COMMAND  ${PROTOBUF_PROTOC_EXECUTABLE}
      ARGS
        --plugin $<TARGET_FILE:protoc-gen-insertions>
        --cpp_out ${ARG_BINARY_ROOT}
        --insertions_out ${ARG_BINARY_ROOT}
        --proto_path ${ARG_SOURCE_ROOT}
        # Used to find built-in .proto files (e.g. FileDescriptorProto)
        --proto_path ${PROTOBUF_INCLUDE_DIR}
        ${EXTRA_PROTO_PATH_ARGS} ${ABS_FIL}
      DEPENDS ${ABS_FIL} protoc-gen-insertions
      COMMENT "Running C++ protocol buffer compiler on ${FIL}"
      VERBATIM )

    # This custom target enforces that there's just one invocation of protoc
    # when there are multiple consumers of the generated files. The target name
    # must be unique; adding parts of the filename helps ensure this.
    set(TGT_NAME ${REL_DIR}${FIL})
    string(REPLACE "/" "-" TGT_NAME ${TGT_NAME})
    add_custom_target(${TGT_NAME}
      DEPENDS "${PROTO_CC_OUT}" "${PROTO_H_OUT}")
    list(APPEND ${TGTS} "${TGT_NAME}")
  endforeach()

  set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
  set(${SRCS} ${${SRCS}} PARENT_SCOPE)
  set(${HDRS} ${${HDRS}} PARENT_SCOPE)
  set(${TGTS} ${${TGTS}} PARENT_SCOPE)
endfunction()


find_path(PROTOBUF_INCLUDE_DIR google/protobuf/service.h
  ${THIRDPARTY_PREFIX}/include
  NO_DEFAULT_PATH
)

# Google's provided vcproj files generate libraries with a "lib"
# prefix on Windows
if(WIN32)
    set(PROTOBUF_ORIG_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}")
    set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "")
endif()

find_library(PROTOBUF_LIBRARY NAMES libprotobuf${CMAKE_SHARED_LIBRARY_SUFFIX}
             DOC "The Google Protocol Buffers Library"
             PATHS ${THIRDPARTY_PREFIX}/lib
             NO_DEFAULT_PATH
)
find_file(PROTOBUF_STATIC_LIBRARY libprotobuf.a
         DOC "Static version of the Google Protocol Buffers Library"
         PATHS ${THIRDPARTY_PREFIX}/lib
         NO_DEFAULT_PATH)

find_library(PROTOBUF_PROTOC_LIBRARY NAMES libprotoc${CMAKE_SHARED_LIBRARY_SUFFIX}
             DOC "The Google Protocol Buffers Compiler Library"
             PATHS ${THIRDPARTY_PREFIX}/lib
             NO_DEFAULT_PATH
)
find_library(PROTOBUF_PROTOC_STATIC_LIBRARY NAMES libprotoc.a
         DOC "Static version of the Google Protocol Buffers Compiler Library"
         PATHS ${THIRDPARTY_PREFIX}/lib
         NO_DEFAULT_PATH)

find_program(PROTOBUF_PROTOC_EXECUTABLE NAMES protoc
             DOC "The Google Protocol Buffers Compiler"
             PATHS ${THIRDPARTY_PREFIX}/bin
             NO_DEFAULT_PATH
)

mark_as_advanced(PROTOBUF_INCLUDE_DIR
                 PROTOBUF_LIBRARY
                 PROTOBUF_STATIC_LIBRARY
                 PROTOBUF_PROTOC_LIBRARY
                 PROTOBUF_PROTOC_STATIC_LIBRARY
                 PROTOBUF_PROTOC_EXECUTABLE)

# Restore original find library prefixes
if(WIN32)
    set(CMAKE_FIND_LIBRARY_PREFIXES "${PROTOBUF_ORIG_FIND_LIBRARY_PREFIXES}")
endif()

include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PROTOBUF DEFAULT_MSG
    PROTOBUF_LIBRARY PROTOBUF_INCLUDE_DIR)

if(PROTOBUF_FOUND)
    set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIR})
    set(PROTOBUF_LIBRARIES    ${PROTOBUF_LIBRARY})
endif()
