blob: 7ca10ae529819c6dcd0e13a87c9eccf22824a960 [file] [log] [blame]
# ~~~
# 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
#
# https://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 ``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.
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
find_package(ProtobufWithTargets)
# 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 UNKNOWN IMPORTED)
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++ UNKNOWN IMPORTED)
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++14 (soon), but only CMake-3.8 introduced a
# compiler feature to meet that requirement.
set_property(
TARGET gRPC::grpc++
APPEND
PROPERTY INTERFACE_COMPILE_FEATURES cxx_std_14)
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++14")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set_property(
TARGET gRPC::grpc++
APPEND
PROPERTY INTERFACE_COMPILE_OPTIONS "-std=c++14")
else ()
message(
WARNING
"gRPC::grpc++ requires C++14, 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++14 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)