diff options
Diffstat (limited to 'third_party/cpp/googleapis/cmake/CompileProtos.cmake')
-rw-r--r-- | third_party/cpp/googleapis/cmake/CompileProtos.cmake | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/third_party/cpp/googleapis/cmake/CompileProtos.cmake b/third_party/cpp/googleapis/cmake/CompileProtos.cmake new file mode 100644 index 000000000000..788267c8d99e --- /dev/null +++ b/third_party/cpp/googleapis/cmake/CompileProtos.cmake @@ -0,0 +1,271 @@ +# ~~~ +# Copyright 2019 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ~~~ + +# Introduce a new TARGET property to associate proto files with a target. +# +# We use a function to define the property so it can be called multiple times +# without introducing the property over and over. +function (google_cloud_cpp_add_protos_property) + set_property( + TARGET + PROPERTY PROTO_SOURCES BRIEF_DOCS + "The list of .proto files for a target." FULL_DOCS + "List of .proto files specified for a target.") +endfunction () + +# Generate C++ for .proto files preserving the directory hierarchy +# +# Receives a list of `.proto` file names and (a) creates the runs to convert +# these files to `.pb.h` and `.pb.cc` output files, (b) returns the list of +# `.pb.cc` files and `.pb.h` files in @p HDRS, and (c) creates the list of files +# preserving the directory hierarchy, such that if a `.proto` file says: +# +# import "foo/bar/baz.proto" +# +# the resulting C++ code says: +# +# #include <foo/bar/baz.pb.h> +# +# Use the `PROTO_PATH` option to provide one or more directories to search for +# proto files in the import. +# +# @par Example +# +# google_cloud_cpp_generate_proto( MY_PB_FILES "foo/bar/baz.proto" +# "foo/bar/qux.proto" PROTO_PATH_DIRECTORIES "another/dir/with/protos") +# +# Note that `protoc` the protocol buffer compiler requires your protos to be +# somewhere in the search path defined by the `--proto_path` (aka -I) options. +# For example, if you want to generate the `.pb.{h,cc}` files for +# `foo/bar/baz.proto` then the directory containing `foo` must be in the search +# path. +function (google_cloud_cpp_generate_proto SRCS) + cmake_parse_arguments(_opt "" "" "PROTO_PATH_DIRECTORIES" ${ARGN}) + if (NOT _opt_UNPARSED_ARGUMENTS) + message(SEND_ERROR "Error: google_cloud_cpp_generate_proto() called" + " without any proto files") + return() + endif () + + # Build the list of `--proto_path` options. Use the absolute path for each + # option given, and do not include any path more than once. + set(protobuf_include_path) + foreach (dir ${_opt_PROTO_PATH_DIRECTORIES}) + get_filename_component(absolute_path ${dir} ABSOLUTE) + list(FIND protobuf_include_path "${absolute_path}" + already_in_search_path) + if (${already_in_search_path} EQUAL -1) + list(APPEND protobuf_include_path "--proto_path" "${absolute_path}") + endif () + endforeach () + + set(${SRCS}) + foreach (filename ${_opt_UNPARSED_ARGUMENTS}) + get_filename_component(file_directory "${filename}" DIRECTORY) + # This gets the filename without the extension, analogous to $(basename + # "${filename}" .proto) + get_filename_component(file_stem "${filename}" NAME_WE) + + # Strip all the prefixes in ${_opt_PROTO_PATH_DIRECTORIES} from the + # source proto directory + set(D "${file_directory}") + if (DEFINED _opt_PROTO_PATH_DIRECTORIES) + foreach (P ${_opt_PROTO_PATH_DIRECTORIES}) + string(REGEX REPLACE "^${P}" "" T "${D}") + set(D ${T}) + endforeach () + endif () + set(pb_cc "${CMAKE_CURRENT_BINARY_DIR}/${D}/${file_stem}.pb.cc") + set(pb_h "${CMAKE_CURRENT_BINARY_DIR}/${D}/${file_stem}.pb.h") + list(APPEND ${SRCS} "${pb_cc}" "${pb_h}") + add_custom_command( + OUTPUT "${pb_cc}" "${pb_h}" + COMMAND + $<TARGET_FILE:protobuf::protoc> ARGS --cpp_out + "${CMAKE_CURRENT_BINARY_DIR}" ${protobuf_include_path} + "${filename}" + DEPENDS "${filename}" protobuf::protoc + COMMENT "Running C++ protocol buffer compiler on ${filename}" + VERBATIM) + endforeach () + + set_source_files_properties(${${SRCS}} PROPERTIES GENERATED TRUE) + set(${SRCS} + ${${SRCS}} + PARENT_SCOPE) +endfunction () + +# Generate gRPC C++ files from .proto files preserving the directory hierarchy. +# +# Receives a list of `.proto` file names and (a) creates the runs to convert +# these files to `.grpc.pb.h` and `.grpc.pb.cc` output files, (b) returns the +# list of `.grpc.pb.cc` and `.pb.h` files in @p SRCS, and (c) creates the list +# of files preserving the directory hierarchy, such that if a `.proto` file says +# +# import "foo/bar/baz.proto" +# +# the resulting C++ code says: +# +# #include <foo/bar/baz.pb.h> +# +# Use the `PROTO_PATH` option to provide one or more directories to search for +# proto files in the import. +# +# @par Example +# +# google_cloud_cpp_generate_grpc( MY_GRPC_PB_FILES "foo/bar/baz.proto" +# "foo/bar/qux.proto" PROTO_PATH_DIRECTORIES "another/dir/with/protos") +# +# Note that `protoc` the protocol buffer compiler requires your protos to be +# somewhere in the search path defined by the `--proto_path` (aka -I) options. +# For example, if you want to generate the `.pb.{h,cc}` files for +# `foo/bar/baz.proto` then the directory containing `foo` must be in the search +# path. +function (google_cloud_cpp_generate_grpcpp SRCS) + cmake_parse_arguments(_opt "" "" "PROTO_PATH_DIRECTORIES" ${ARGN}) + if (NOT _opt_UNPARSED_ARGUMENTS) + message( + SEND_ERROR "Error: google_cloud_cpp_generate_grpc() called without" + " any proto files") + return() + endif () + + # Build the list of `--proto_path` options. Use the absolute path for each + # option given, and do not include any path more than once. + set(protobuf_include_path) + foreach (dir ${_opt_PROTO_PATH_DIRECTORIES}) + get_filename_component(absolute_path ${dir} ABSOLUTE) + list(FIND protobuf_include_path "${absolute_path}" + already_in_search_path) + if (${already_in_search_path} EQUAL -1) + list(APPEND protobuf_include_path "--proto_path" "${absolute_path}") + endif () + endforeach () + + set(${SRCS}) + foreach (filename ${_opt_UNPARSED_ARGUMENTS}) + get_filename_component(file_directory "${filename}" DIRECTORY) + # This gets the filename without the extension, analogous to $(basename + # "${filename}" .proto) + get_filename_component(file_stem "${filename}" NAME_WE) + + # Strip all the prefixes in ${_opt_PROTO_PATH_DIRECTORIES} from the + # source proto directory + set(D "${file_directory}") + if (DEFINED _opt_PROTO_PATH_DIRECTORIES) + foreach (P ${_opt_PROTO_PATH_DIRECTORIES}) + string(REGEX REPLACE "^${P}" "" T "${D}") + set(D ${T}) + endforeach () + endif () + set(grpc_pb_cc + "${CMAKE_CURRENT_BINARY_DIR}/${D}/${file_stem}.grpc.pb.cc") + set(grpc_pb_h "${CMAKE_CURRENT_BINARY_DIR}/${D}/${file_stem}.grpc.pb.h") + list(APPEND ${SRCS} "${grpc_pb_cc}" "${grpc_pb_h}") + add_custom_command( + OUTPUT "${grpc_pb_cc}" "${grpc_pb_h}" + COMMAND + $<TARGET_FILE:protobuf::protoc> ARGS + --plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin> + "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}" + "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" ${protobuf_include_path} + "${filename}" + DEPENDS "${filename}" protobuf::protoc gRPC::grpc_cpp_plugin + COMMENT "Running gRPC C++ protocol buffer compiler on ${filename}" + VERBATIM) + endforeach () + + set_source_files_properties(${${SRCS}} PROPERTIES GENERATED TRUE) + set(${SRCS} + ${${SRCS}} + PARENT_SCOPE) +endfunction () + +include(GNUInstallDirs) + +# Install headers for a C++ proto library. +function (google_cloud_cpp_install_proto_library_headers target) + get_target_property(target_sources ${target} SOURCES) + foreach (header ${target_sources}) + # Skip anything that is not a header file. + if (NOT "${header}" MATCHES "\\.h$") + continue() + endif () + string(REPLACE "${CMAKE_CURRENT_BINARY_DIR}/" "" relative "${header}") + get_filename_component(dir "${relative}" DIRECTORY) + install(FILES "${header}" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${dir}") + endforeach () +endfunction () + +# Install protos for a C++ proto library. +function (google_cloud_cpp_install_proto_library_protos target strip_prefix) + get_target_property(target_protos ${target} PROTO_SOURCES) + foreach (proto ${target_protos}) + # Skip anything that is not a header file. + if (NOT "${proto}" MATCHES "\\.proto$") + continue() + endif () + string(REPLACE "${strip_prefix}/" "" relative "${proto}") + get_filename_component(dir "${relative}" DIRECTORY) + # This is modeled after the Protobuf library, it installs the basic + # protos (think google/protobuf/any.proto) in the include directory for + # C/C++ code. :shrug: + install(FILES "${proto}" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${dir}") + endforeach () +endfunction () + +function (google_cloud_cpp_proto_library libname) + cmake_parse_arguments(_opt "" "" "PROTO_PATH_DIRECTORIES" ${ARGN}) + if (NOT _opt_UNPARSED_ARGUMENTS) + message(SEND_ERROR "Error: google_cloud_cpp_proto_library() called" + " without any proto files") + return() + endif () + + google_cloud_cpp_generate_proto( + proto_sources ${_opt_UNPARSED_ARGUMENTS} PROTO_PATH_DIRECTORIES + ${_opt_PROTO_PATH_DIRECTORIES}) + + add_library(${libname} ${proto_sources}) + set_property(TARGET ${libname} PROPERTY PROTO_SOURCES + ${_opt_UNPARSED_ARGUMENTS}) + target_link_libraries(${libname} PUBLIC gRPC::grpc++ gRPC::grpc + protobuf::libprotobuf) + target_include_directories( + ${libname} + PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}> + $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}> + $<INSTALL_INTERFACE:include>) +endfunction () + +function (google_cloud_cpp_grpcpp_library libname) + cmake_parse_arguments(_opt "" "" "PROTO_PATH_DIRECTORIES" ${ARGN}) + if (NOT _opt_UNPARSED_ARGUMENTS) + message(SEND_ERROR "Error: google_cloud_cpp_proto_library() called" + " without any proto files") + return() + endif () + + google_cloud_cpp_generate_grpcpp( + grpcpp_sources ${_opt_UNPARSED_ARGUMENTS} PROTO_PATH_DIRECTORIES + ${_opt_PROTO_PATH_DIRECTORIES}) + google_cloud_cpp_proto_library( + ${libname} ${_opt_UNPARSED_ARGUMENTS} PROTO_PATH_DIRECTORIES + ${_opt_PROTO_PATH_DIRECTORIES}) + target_sources(${libname} PRIVATE ${grpcpp_sources}) +endfunction () |