# ~~~ # 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. # ~~~ #[=======================================================================[.rst: FindgRPC -------- Locate and configure the gRPC library. The following variables can be set and are optional: ``gRPC_DEBUG`` Show debug messages. ``gRPC_USE_STATIC_LIBS`` Set to ON to force the use of the static libraries. Default is OFF. Defines the following variables: ``gRPC_FOUND`` Found the gRPC library ``gRPC_VERSION`` Version of package found. The following :prop_tgt:`IMPORTED` targets are also defined: ``gRPC::grpc++`` The gRPC C++ library. ``gRPC::grpc`` The gRPC C core library. ``gRPC::cpp_plugin`` The C++ plugin for the Protobuf protoc compiler. The following cache variables are also available to set or use: Example: .. code-block:: cmake find_package(gRPC REQUIRED) add_executable(bar bar.cc) target_link_libraries(bar PRIVATE gRPC::grpc++) #]=======================================================================] if (gRPC_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "gRPC_USE_STATIC_LIBS = ${gRPC_USE_STATIC_LIBS}" " gRPC_FOUND = ${gRPC_FOUND}") endif () # gRPC always requires Thread support. find_package(Threads REQUIRED) # Load the module to find protobuf with proper targets. Do not use # `find_package()` because we (have to) install this module in non-standard # locations. include(${CMAKE_CURRENT_LIST_DIR}/FindProtobufTargets.cmake) # The gRPC::grpc_cpp_plugin target is sometimes defined, but without a # IMPORTED_LOCATION function (_grpc_fix_grpc_cpp_plugin_target) # The target may already exist, do not create it again if it does. if (NOT TARGET gRPC::grpc_cpp_plugin) add_executable(gRPC::grpc_cpp_plugin IMPORTED) endif () get_target_property(_gRPC_CPP_PLUGIN_EXECUTABLE gRPC::grpc_cpp_plugin IMPORTED_LOCATION) if (gRPC_DEBUG) message( STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "LOCATION=${_gRPC_CPP_PLUGIN_EXECUTABLE}") endif () # Even if the target exists, gRPC CMake support files do not define the # executable for the imported target (at least they do not in v1.19.1), so # we need to define it ourselves. if (NOT _gRPC_CPP_PLUGIN_EXECUTABLE) find_program(_gRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin DOC "The gRPC C++ plugin for protoc") mark_as_advanced(_gRPC_CPP_PLUGIN_EXECUTABLE) if (_gRPC_CPP_PLUGIN_EXECUTABLE) set_property( TARGET gRPC::grpc_cpp_plugin PROPERTY IMPORTED_LOCATION ${_gRPC_CPP_PLUGIN_EXECUTABLE}) else () set(gRPC_FOUND "grpc_cpp_plugin-NOTFOUND") endif () endif () endfunction () # The gRPC::* targets sometimes lack the right definitions to compile cleanly on # WIN32 function (_grpc_fix_grpc_target_definitions) # Including gRPC headers without this definition results in a build error. if (WIN32) set_property(TARGET gRPC::grpc APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS _WIN32_WINNT=0x600) set_property(TARGET gRPC::grpc++ APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS _WIN32_WINNT=0x600) endif () endfunction () # First try to use the `gRPCConfig.cmake` or `grpc-config.cmake` file if it was # installed. This is common on systems (or package managers) where gRPC was # compiled and installed with `CMake`. find_package(gRPC NO_MODULE QUIET) if (gRPC_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "NO_MODULE result gRPC_FOUND = ${gRPC_FOUND}") endif () if (gRPC_FOUND) _grpc_fix_grpc_cpp_plugin_target() _grpc_fix_grpc_target_definitions() return() endif () include(SelectLibraryConfigurations) # Internal function: search for normal library as well as a debug one if the # debug one is specified also include debug/optimized keywords in *_LIBRARIES # variable function (_gRPC_find_library name filename) if (${name}_LIBRARY) # Use result recorded by a previous call. return() else () find_library(${name}_LIBRARY_RELEASE NAMES ${filename}) mark_as_advanced(${name}_LIBRARY_RELEASE) find_library(${name}_LIBRARY_DEBUG NAMES ${filename}d ${filename}) mark_as_advanced(${name}_LIBRARY_DEBUG) select_library_configurations(${name}) if (gRPC_DEBUG) message( STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "${name} ${filename} RELEASE=${${name}_LIBRARY}" " DEBUG=${${name}_LIBRARY_DEBUG} DEFAULT=${${name}_LIBRARY}" ) endif () set(${name}_LIBRARY "${${name}_LIBRARY}" PARENT_SCOPE) endif () endfunction () # # Main # # Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES if (_gRPC_USE_STATIC_LIBS) set(_gRPC_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) if (WIN32) set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) else () set(CMAKE_FIND_LIBRARY_SUFFIXES .a) endif () endif () _grpc_find_library(_gRPC_grpc grpc) _grpc_find_library(_gRPC_grpc++ grpc++) if (NOT _gRPC_INCLUDE_DIR) find_path(_gRPC_INCLUDE_DIR grpcpp/grpcpp.h) mark_as_advanced(_gRPC_INCLUDE_DIR) endif () if (gRPC_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " " _gRPC_grpc_LIBRARY = ${_gRPC_grpc_LIBRARY}") message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " " _gRPC_grpc++_LIBRARY = ${_gRPC_grpc++_LIBRARY}") message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " " _gRPC_INCLUDE_DIR = ${_gRPC_INCLUDE_DIR}") endif () if (_gRPC_grpc_LIBRARY) if (NOT TARGET gRPC::grpc) add_library(gRPC::grpc IMPORTED UNKNOWN) set_target_properties( gRPC::grpc PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_gRPC_INCLUDE_DIR}") if (EXISTS "${_gRPC_grpc_LIBRARY}") set_target_properties(gRPC::grpc PROPERTIES IMPORTED_LOCATION "${_gRPC_grpc_LIBRARY}") endif () if (EXISTS "${_gRPC_grpc_LIBRARY_RELEASE}") set_property(TARGET gRPC::grpc APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) set_target_properties( gRPC::grpc PROPERTIES IMPORTED_LOCATION_RELEASE "${_gRPC_grpc_LIBRARY_RELEASE}") endif () if (EXISTS "${_gRPC_grpc_LIBRARY_DEBUG}") set_property(TARGET gRPC::grpc APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) set_target_properties( gRPC::grpc PROPERTIES IMPORTED_LOCATION_DEBUG "${_gRPC_grpc_LIBRARY_DEBUG}") endif () set_property( TARGET gRPC::grpc APPEND PROPERTY INTERFACE_LINK_LIBRARIES protobuf::libprotobuf Threads::Threads) endif () endif () if (_gRPC_grpc++_LIBRARY) if (NOT TARGET gRPC::grpc++) add_library(gRPC::grpc++ IMPORTED UNKNOWN) set_target_properties( gRPC::grpc++ PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_gRPC++_INCLUDE_DIR}") if (EXISTS "${_gRPC_grpc++_LIBRARY}") set_target_properties( gRPC::grpc++ PROPERTIES IMPORTED_LOCATION "${_gRPC_grpc++_LIBRARY}") endif () if (EXISTS "${_gRPC_grpc++_LIBRARY_RELEASE}") set_property(TARGET gRPC::grpc++ APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) set_target_properties( gRPC::grpc++ PROPERTIES IMPORTED_LOCATION_RELEASE "${_gRPC_grpc++_LIBRARY_RELEASE}") endif () if (EXISTS "${_gRPC_grpc++_LIBRARY_DEBUG}") set_property(TARGET gRPC::grpc++ APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) set_target_properties( gRPC::grpc++ PROPERTIES IMPORTED_LOCATION_DEBUG "${_gRPC_grpc++_LIBRARY_DEBUG}") endif () set_property( TARGET gRPC::grpc++ APPEND PROPERTY INTERFACE_LINK_LIBRARIES gRPC::grpc protobuf::libprotobuf Threads::Threads) if (CMAKE_VERSION VERSION_GREATER 3.8) # gRPC++ requires C++11, but only CMake-3.8 introduced a target # compiler feature to meet that requirement. set_property(TARGET gRPC::grpc++ APPEND PROPERTY INTERFACE_COMPILE_FEATURES cxx_std_11) elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # CMake 3.5 is still alive and kicking in some older distros, use # the compiler-specific versions in these cases. set_property(TARGET gRPC::grpc++ APPEND PROPERTY INTERFACE_COMPILE_OPTIONS "-std=c++11") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") set_property(TARGET gRPC::grpc++ APPEND PROPERTY INTERFACE_COMPILE_OPTIONS "-std=c++11") else () message( WARNING "gRPC::grpc++ requires C++11, but this module" " (${CMAKE_CURRENT_LIST_FILE})" " cannot enable it for the library target in your CMake and" " compiler versions. You need to enable C++11 in the" " CMakeLists.txt for your project. Consider filing a bug" " so we can fix this problem.") endif () endif () endif () # Restore original find library prefixes if (_gRPC_USE_STATIC_LIBS) set(CMAKE_FIND_LIBRARY_PREFIXES "${_gRPC_ORIG_FIND_LIBRARY_PREFIXES}") endif () file( WRITE "${CMAKE_BINARY_DIR}/get_gRPC_version.cc" [====[ #include <grpcpp/grpcpp.h> #include <iostream> int main() { std::cout << grpc::Version(); // no newline to simplify CMake module return 0; } ]====]) try_run( _gRPC_GET_VERSION_STATUS _gRPC_GET_VERSION_COMPILE_STATUS "${CMAKE_BINARY_DIR}" "${CMAKE_BINARY_DIR}/get_gRPC_version.cc" LINK_LIBRARIES gRPC::grpc++ gRPC::grpc COMPILE_OUTPUT_VARIABLE _gRPC_GET_VERSION_COMPILE_OUTPUT RUN_OUTPUT_VARIABLE gRPC_VERSION) file(REMOVE "${CMAKE_BINARY_DIR}/get_gRPC_version.cc") _grpc_fix_grpc_cpp_plugin_target() if (gRPC_DEBUG) foreach ( _var _gRPC_CPP_PLUGIN_EXECUTABLE _gRPC_VERSION_RAW _gRPC_GET_VERSION_STATUS _gRPC_GET_VERSION_COMPILE_STATUS _gRPC_GET_VERSION_COMPILE_OUTPUT _gRPC_grpc_LIBRARY _gRPC_grpc++_LIBRARY _gRPC_INCLUDE_DIR) message( STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "${_var} = ${${_var}}") endforeach () unset(_var) endif () include(FindPackageHandleStandardArgs) find_package_handle_standard_args(gRPC REQUIRED_VARS _gRPC_grpc_LIBRARY _gRPC_INCLUDE_DIR VERSION_VAR gRPC_VERSION)