Merge pull request #9358 from jtattermusch/mingw_docs

Update docs on windows build
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9d67736..cce0528 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -122,6 +122,9 @@
     if(TARGET libprotoc)
       set(_gRPC_PROTOBUF_PROTOC_LIBRARIES libprotoc)
     endif()
+    if(TARGET protoc)
+      set(_gRPC_PROTOBUF_PROTOC protoc)
+    endif()
   else()
       message(WARNING "gRPC_PROTOBUF_PROVIDER is \"module\" but PROTOBUF_ROOT_DIR is wrong")
   endif()
@@ -134,6 +137,9 @@
     if(TARGET protobuf::libprotoc)
       set(_gRPC_PROTOBUF_PROTOC_LIBRARIES protobuf::libprotoc)
     endif()
+    if(TARGET protobuf::protoc)
+      set(_gRPC_PROTOBUF_PROTOC protobuf::protoc)
+    endif()
     set(_gRPC_FIND_PROTOBUF "if(NOT protobuf_FOUND)\n  find_package(protobuf CONFIG)\nendif()")
   else()
     find_package(Protobuf MODULE)
@@ -175,7 +181,56 @@
   set(CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/gRPC")
 endif()
 
-  
+# Create directory for generated .proto files
+set(_gRPC_PROTO_GENS_DIR ${CMAKE_BINARY_DIR}/gens)
+file(MAKE_DIRECTORY ${_gRPC_PROTO_GENS_DIR})
+
+#  protobuf_generate_grpc_cpp
+#  --------------------------
+#
+#   Add custom commands to process ``.proto`` files to C++ using protoc and
+#   GRPC plugin::
+#
+#     protobuf_generate_grpc_cpp [<ARGN>...]
+#
+#   ``ARGN``
+#     ``.proto`` files
+#
+function(protobuf_generate_grpc_cpp)
+  if(NOT ARGN)
+    message(SEND_ERROR "Error: PROTOBUF_GENERATE_GRPC_CPP() called without any proto files")
+    return()
+  endif()
+
+  set(_protobuf_include_path -I .)
+  foreach(FIL ${ARGN})
+    get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
+    get_filename_component(FIL_WE ${FIL} NAME_WE)
+    file(RELATIVE_PATH REL_FIL ${CMAKE_SOURCE_DIR} ${ABS_FIL})
+    get_filename_component(REL_DIR ${REL_FIL} DIRECTORY)
+    set(RELFIL_WE "${REL_DIR}/${FIL_WE}")
+    
+    add_custom_command(
+      OUTPUT "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.cc"
+             "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.h"
+             "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc"
+             "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h"
+      COMMAND ${_gRPC_PROTOBUF_PROTOC}
+      ARGS --grpc_out=${_gRPC_PROTO_GENS_DIR}
+           --cpp_out=${_gRPC_PROTO_GENS_DIR}
+           --plugin=protoc-gen-grpc=$<TARGET_FILE:grpc_cpp_plugin>
+           ${_protobuf_include_path}
+           ${REL_FIL}
+      DEPENDS ${ABS_FIL} ${_gRPC_PROTOBUF_PROTOC} grpc_cpp_plugin
+      WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+      COMMENT "Running gRPC C++ protocol buffer compiler on ${FIL}"
+      VERBATIM)
+      
+      set_source_files_properties("${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.cc" "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.h" "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc" "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h" PROPERTIES GENERATED TRUE)
+  endforeach()
+endfunction()
+
+
 add_library(gpr
   src/core/lib/profiling/basic_timers.c
   src/core/lib/profiling/stap_timers.c
@@ -223,6 +278,7 @@
   src/core/lib/support/wrap_memcpy.c
 )
 
+
 target_include_directories(gpr
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -280,7 +336,7 @@
   )
 endforeach()
 
-  
+
 if (gRPC_INSTALL)
   install(TARGETS gpr EXPORT gRPCTargets
     RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
@@ -289,7 +345,7 @@
   )
 endif()
 
-  
+
 add_library(grpc
   src/core/lib/surface/init.c
   src/core/lib/channel/channel_args.c
@@ -510,6 +566,7 @@
   src/core/plugin_registry/grpc_plugin_registry.c
 )
 
+
 target_include_directories(grpc
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -565,7 +622,7 @@
   )
 endforeach()
 
-  
+
 if (gRPC_INSTALL)
   install(TARGETS grpc EXPORT gRPCTargets
     RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
@@ -574,7 +631,7 @@
   )
 endif()
 
-  
+
 add_library(grpc_cronet
   src/core/lib/surface/init.c
   src/core/lib/channel/channel_args.c
@@ -766,6 +823,7 @@
   src/core/plugin_registry/grpc_cronet_plugin_registry.c
 )
 
+
 target_include_directories(grpc_cronet
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -820,7 +878,7 @@
   )
 endforeach()
 
-  
+
 if (gRPC_INSTALL)
   install(TARGETS grpc_cronet EXPORT gRPCTargets
     RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
@@ -829,7 +887,7 @@
   )
 endif()
 
-  
+
 add_library(grpc_unsecure
   src/core/lib/surface/init.c
   src/core/lib/surface/init_unsecure.c
@@ -1022,6 +1080,7 @@
   src/core/plugin_registry/grpc_unsecure_plugin_registry.c
 )
 
+
 target_include_directories(grpc_unsecure
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -1074,7 +1133,7 @@
   )
 endforeach()
 
-  
+
 if (gRPC_INSTALL)
   install(TARGETS grpc_unsecure EXPORT gRPCTargets
     RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
@@ -1083,7 +1142,7 @@
   )
 endif()
 
-  
+
 add_library(grpc++
   src/cpp/client/insecure_credentials.cc
   src/cpp/client/secure_credentials.cc
@@ -1124,6 +1183,7 @@
   src/cpp/codegen/codegen_init.cc
 )
 
+
 target_include_directories(grpc++
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -1238,7 +1298,7 @@
   )
 endforeach()
 
-  
+
 if (gRPC_INSTALL)
   install(TARGETS grpc++ EXPORT gRPCTargets
     RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
@@ -1247,7 +1307,7 @@
   )
 endif()
 
-  
+
 add_library(grpc++_cronet
   src/cpp/client/cronet_credentials.cc
   src/cpp/client/insecure_credentials.cc
@@ -1461,6 +1521,7 @@
   third_party/nanopb/pb_encode.c
 )
 
+
 target_include_directories(grpc++_cronet
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -1585,7 +1646,7 @@
   )
 endforeach()
 
-  
+
 if (gRPC_INSTALL)
   install(TARGETS grpc++_cronet EXPORT gRPCTargets
     RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
@@ -1594,7 +1655,54 @@
   )
 endif()
 
-  
+
+add_library(grpc++_reflection
+  src/cpp/ext/proto_server_reflection.cc
+  src/cpp/ext/proto_server_reflection_plugin.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h
+)
+
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/reflection/v1alpha/reflection.proto
+)
+
+target_include_directories(grpc++_reflection
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${ZLIB_INCLUDE_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(grpc++_reflection
+  grpc++
+)
+
+foreach(_hdr
+  include/grpc++/ext/proto_server_reflection_plugin.h
+)
+  string(REPLACE "include/" "" _path ${_hdr})
+  get_filename_component(_path ${_path} PATH)
+  install(FILES ${_hdr}
+    DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_path}"
+  )
+endforeach()
+
+
+if (gRPC_INSTALL)
+  install(TARGETS grpc++_reflection EXPORT gRPCTargets
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+  )
+endif()
+
+
 add_library(grpc++_unsecure
   src/cpp/client/insecure_credentials.cc
   src/cpp/common/insecure_create_auth_context.cc
@@ -1630,6 +1738,7 @@
   src/cpp/codegen/codegen_init.cc
 )
 
+
 target_include_directories(grpc++_unsecure
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -1744,7 +1853,7 @@
   )
 endforeach()
 
-  
+
 if (gRPC_INSTALL)
   install(TARGETS grpc++_unsecure EXPORT gRPCTargets
     RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
@@ -1753,7 +1862,7 @@
   )
 endif()
 
-  
+
 add_library(grpc_plugin_support
   src/compiler/cpp_generator.cc
   src/compiler/csharp_generator.cc
@@ -1764,6 +1873,7 @@
   src/compiler/ruby_generator.cc
 )
 
+
 target_include_directories(grpc_plugin_support
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
@@ -1787,7 +1897,7 @@
   )
 endforeach()
 
-  
+
 if (gRPC_INSTALL)
   install(TARGETS grpc_plugin_support EXPORT gRPCTargets
     RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
diff --git a/templates/CMakeLists.txt.template b/templates/CMakeLists.txt.template
index 028c1b8..7868d41 100644
--- a/templates/CMakeLists.txt.template
+++ b/templates/CMakeLists.txt.template
@@ -40,6 +40,17 @@
   # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
   <%!
+  
+  import re
+  
+  proto_re = re.compile('(.*)\\.proto')
+  
+  def proto_replace_ext(filename, ext):
+      m = proto_re.match(filename)
+      if not m:
+        return filename
+      return '${_gRPC_PROTO_GENS_DIR}/' + m.group(1) + ext
+  
   def get_deps(target_dict):
     deps = []
     if target_dict.get('baselib', False):
@@ -140,6 +151,9 @@
       if(TARGET libprotoc)
         set(_gRPC_PROTOBUF_PROTOC_LIBRARIES libprotoc)
       endif()
+      if(TARGET protoc)
+        set(_gRPC_PROTOBUF_PROTOC protoc)
+      endif()
     else()
         message(WARNING "gRPC_PROTOBUF_PROVIDER is \"module\" but PROTOBUF_ROOT_DIR is wrong")
     endif()
@@ -152,6 +166,9 @@
       if(TARGET protobuf::libprotoc)
         set(_gRPC_PROTOBUF_PROTOC_LIBRARIES protobuf::libprotoc)
       endif()
+      if(TARGET protobuf::protoc)
+        set(_gRPC_PROTOBUF_PROTOC protobuf::protoc)
+      endif()
       set(_gRPC_FIND_PROTOBUF "if(NOT protobuf_FOUND)\n  find_package(protobuf CONFIG)\nendif()")
     else()
       find_package(Protobuf MODULE)
@@ -192,16 +209,60 @@
   if(NOT DEFINED CMAKE_INSTALL_CMAKEDIR)
     set(CMAKE_INSTALL_CMAKEDIR "<%text>${CMAKE_INSTALL_LIBDIR}</%text>/cmake/gRPC")
   endif()
-
+  
+  # Create directory for generated .proto files
+  set(_gRPC_PROTO_GENS_DIR <%text>${CMAKE_BINARY_DIR}/gens</%text>)
+  file(MAKE_DIRECTORY <%text>${_gRPC_PROTO_GENS_DIR}</%text>)
+  
+  #  protobuf_generate_grpc_cpp
+  #  --------------------------
+  #
+  #   Add custom commands to process ``.proto`` files to C++ using protoc and
+  #   GRPC plugin::
+  #
+  #     protobuf_generate_grpc_cpp [<ARGN>...]
+  #
+  #   ``ARGN``
+  #     ``.proto`` files
+  #
+  function(protobuf_generate_grpc_cpp)
+    if(NOT ARGN)
+      message(SEND_ERROR "Error: PROTOBUF_GENERATE_GRPC_CPP() called without any proto files")
+      return()
+    endif()
+  
+    set(_protobuf_include_path -I .)
+    foreach(FIL <%text>${ARGN}</%text>)
+      get_filename_component(ABS_FIL <%text>${FIL}</%text> ABSOLUTE)
+      get_filename_component(FIL_WE <%text>${FIL}</%text> NAME_WE)
+      file(RELATIVE_PATH REL_FIL <%text>${CMAKE_SOURCE_DIR}</%text> <%text>${ABS_FIL}</%text>)
+      get_filename_component(REL_DIR <%text>${REL_FIL}</%text> DIRECTORY)
+      set(RELFIL_WE "<%text>${REL_DIR}/${FIL_WE}</%text>")
+      
+      add_custom_command(
+        OUTPUT <%text>"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.cc"</%text>
+               <%text>"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.h"</%text>
+               <%text>"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc"</%text>
+               <%text>"${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h"</%text>
+        COMMAND <%text>${_gRPC_PROTOBUF_PROTOC}</%text>
+        ARGS --grpc_out=<%text>${_gRPC_PROTO_GENS_DIR}</%text>
+             --cpp_out=<%text>${_gRPC_PROTO_GENS_DIR}</%text>
+             --plugin=protoc-gen-grpc=$<TARGET_FILE:grpc_cpp_plugin>
+             <%text>${_protobuf_include_path}</%text>
+             <%text>${REL_FIL}</%text>
+        DEPENDS <%text>${ABS_FIL}</%text> <%text>${_gRPC_PROTOBUF_PROTOC}</%text> grpc_cpp_plugin
+        WORKING_DIRECTORY <%text>${CMAKE_SOURCE_DIR}</%text>
+        COMMENT "Running gRPC C++ protocol buffer compiler on <%text>${FIL}</%text>"
+        VERBATIM)
+        
+        <%text>set_source_files_properties("${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.cc" "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.h" "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc" "${_gRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h" PROPERTIES GENERATED TRUE)</%text>
+    endforeach()
+  endfunction()
+  
   % for lib in libs:
   % if lib.build in ["all", "protoc", "tool"] and lib.language in ['c', 'c++']:
-  ## TODO(jtattermusch): grpc++_reflection includes .proto files
-  ## which is not yet supported and thus fails the entire build.
-  ## Re-enable once fixed.
-  % if lib.name != 'grpc++_reflection':
-    ${cc_library(lib)}
-    ${cc_install(lib)}
-  % endif
+  ${cc_library(lib)}
+  ${cc_install(lib)}
   % endif
   % endfor
 
@@ -215,9 +276,24 @@
   <%def name="cc_library(lib)">
   add_library(${lib.name}
   % for src in lib.src:
+  % if not proto_re.match(src):
     ${src}
+  % else:
+    ${proto_replace_ext(src, '.pb.cc')}
+    ${proto_replace_ext(src, '.grpc.pb.cc')}
+    ${proto_replace_ext(src, '.pb.h')}
+    ${proto_replace_ext(src, '.grpc.pb.h')}
+  % endif
   % endfor
   )
+  
+  % for src in lib.src:
+  % if proto_re.match(src):
+  protobuf_generate_grpc_cpp(
+    ${src}
+  )
+  % endif
+  % endfor
 
   target_include_directories(${lib.name}
     PRIVATE <%text>${CMAKE_CURRENT_SOURCE_DIR}</%text>
@@ -226,6 +302,9 @@
     PRIVATE <%text>${PROTOBUF_ROOT_DIR}</%text>/src
     PRIVATE <%text>${ZLIB_INCLUDE_DIR}</%text>
     PRIVATE <%text>${CMAKE_CURRENT_BINARY_DIR}</%text>/third_party/zlib
+  % if any(proto_re.match(src) for src in lib.src):
+    PRIVATE <%text>${_gRPC_PROTO_GENS_DIR}</%text>
+  % endif
   )
 
   % if len(get_deps(lib)) > 0: