diff options
Diffstat (limited to 'cmake/FindProtobufTargets.cmake')
-rw-r--r-- | cmake/FindProtobufTargets.cmake | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/cmake/FindProtobufTargets.cmake b/cmake/FindProtobufTargets.cmake new file mode 100644 index 000000000000..db260280d3cd --- /dev/null +++ b/cmake/FindProtobufTargets.cmake @@ -0,0 +1,207 @@ +# ~~~ +# 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: +FindProtobufTargets +------------------- + +A module to use `Protobuf` with less complications. + +Using ``find_package(Protobuf)`` should be simple, but it is not. + +CMake provides a ``FindProtobuf`` module. Unfortunately it does not generate +`protobuf::*` targets until CMake-3.9, and `protobuf::protoc` does not +appear until CMake-3.10. + +The CMake-config files generated by `protobuf` always create these targets, +but on some Linux distributions (e.g. Fedora>=29, and openSUSE-Tumbleweed) there +are system packages for protobuf, but these packages are installed without the +CMake-config files. One must either use the ``FindProtobuf`` module, find the +libraries via `pkg-config`, or find the libraries manually. + +When the CMake-config files are installed they produce the same targets as +recent versions of ``FindProtobuf``. However, they do not produce the +`Protobuf_LIBRARY`, `Protobuf_INCLUDE_DIR`, etc. that are generated by the +module. Furthermore, the `protobuf::protoc` library is not usable when loaded +from the CMake-config files: its ``IMPORTED_LOCATION`` variable is not defined. + +This module is designed to provide a single, uniform, ``find_package()`` +module that always produces the same outputs: + +- It always generates the ``protobuf::*`` targets. +- It always defines ``ProtobufTargets_FOUND`` and ``ProtobufTargets_VERSION``. +- It *prefers* using the CMake config files if they are available. +- It fallsback on the ``FindProtobuf`` module if the config files are not found. +- It populates any missing targets and their properties. + +The following :prop_tgt:`IMPORTED` targets are defined: + +``protobuf::libprotobuf`` + The protobuf library. +``protobuf::libprotobuf-lite`` + The protobuf lite library. +``protobuf::libprotoc`` + The protoc library. +``protobuf::protoc`` + The protoc compiler. + +Example: + +.. code-block:: cmake + + find_package(ProtobufTargets REQUIRED) + add_executable(bar bar.cc) + target_link_libraries(bar PRIVATE protobuf::libprotobuf) + +#]=======================================================================] + +if (protobuf_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "protobuf_USE_STATIC_LIBS = ${protobuf_USE_STATIC_LIBS}" + " ProtobufTargets = ${ProtobufTargets_FOUND}") +endif () + +# Always load thread support, even on Windows. +find_package(Threads REQUIRED) + +# First try to use the ``protobufConfig.cmake`` or ``protobuf-config.cmake`` +# file if it was installed. This is common on systems (or package managers) +# where protobuf was compiled and installed with `CMake`. Note that on Linux +# this *must* be all lowercase ``protobuf``, while on Windows it does not +# matter. +find_package(protobuf CONFIG) + +if (protobuf_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "protobuf_FOUND = ${protobuf_FOUND}" + " protobuf_VERSION = ${protobuf_VERSION}") +endif () + +if (protobuf_FOUND) + set(ProtobufTargets_FOUND 1) + set(ProtobufTargets_VERSION ${protobuf_VERSION}) + if (protobuf_DEBUG) + message( + STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "ProtobufTargets_FOUND = ${ProtobufTargets_FOUND}" + " ProtobufTargets_VERSION = ${ProtobufTargets_VERSION}") + endif () +else() + find_package(Protobuf QUIET) + if (Protobuf_FOUND) + set(ProtobufTargets_FOUND 1) + set(ProtobufTargets_VERSION ${Protobuf_VERSION}) + + if (NOT TARGET protobuf::libprotobuf) + add_library(protobuf::libprotobuf INTERFACE IMPORTED) + set_property(TARGET protobuf::libprotobuf + PROPERTY INTERFACE_INCLUDE_DIRECTORIES + ${Protobuf_INCLUDE_DIR}) + set_property(TARGET protobuf::libprotobuf + APPEND + PROPERTY INTERFACE_LINK_LIBRARIES ${Protobuf_LIBRARY} + Threads::Threads) + endif () + + if (NOT TARGET protobuf::libprotobuf-lite) + add_library(protobuf::libprotobuf-lite INTERFACE IMPORTED) + set_property(TARGET protobuf::libprotobuf-lite + PROPERTY INTERFACE_INCLUDE_DIRECTORIES + ${Protobuf_INCLUDE_DIR}) + set_property(TARGET protobuf::libprotobuf-lite + APPEND + PROPERTY INTERFACE_LINK_LIBRARIES + ${Protobuf_LITE_LIBRARY} Threads::Threads) + endif () + + if (NOT TARGET protobuf::libprotoc) + add_library(protobuf::libprotoc INTERFACE IMPORTED) + set_property(TARGET protobuf::libprotoc + PROPERTY INTERFACE_INCLUDE_DIRECTORIES + ${Protobuf_INCLUDE_DIR}) + set_property(TARGET protobuf::libprotoc + APPEND + PROPERTY INTERFACE_LINK_LIBRARIES + ${Protobuf_PROTOC_LIBRARY} Threads::Threads) + endif () + endif () +endif () + +if (protobuf_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "ProtobufTargets_FOUND = ${ProtobufTargets_FOUND}" + " ProtobufTargets_VERSION = ${ProtobufTargets_VERSION}") +endif () + +# We also should try to find the protobuf C++ plugin for the protocol buffers +# compiler. +if (ProtobufTargets_FOUND AND NOT TARGET protobuf::protoc) + add_executable(protobuf::protoc IMPORTED) + + # Discover the protoc compiler location. + find_program(_protobuf_PROTOC_EXECUTABLE + NAMES protoc + DOC "The Google Protocol Buffers Compiler") + if (protobuf_DEBUG) + message( + STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "ProtobufTargets_FOUND = ${ProtobufTargets_FOUND}" + " ProtobufTargets_VERSION = ${ProtobufTargets_VERSION}" + " EXE = ${_protobuf_PROTOC_EXECUTABLE}") + endif () + set_property(TARGET protobuf::protoc + PROPERTY IMPORTED_LOCATION ${_protobuf_PROTOC_EXECUTABLE}) + set_property( + TARGET protobuf::protoc + PROPERTY IMPORTED_LOCATION_DEBUG ${_protobuf_PROTOC_EXECUTABLE}) + set_property(TARGET protobuf::protoc + PROPERTY IMPORTED_LOCATION_RELEASE + ${_protobuf_PROTOC_EXECUTABLE}) + unset(_protobuf_PROTOC_EXECUTABLE) + + if (protobuf_DEBUG) + get_target_property(_protobuf_PROTOC_EXECUTABLE protobuf::protoc + IMPORTED_LOCATION) + message( + STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "LOCATION=${_protobuf_PROTOC_EXECUTABLE}") + endif () +endif () + +if (protobuf_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "ProtobufTargets_FOUND = ${ProtobufTargets_FOUND}" + " ProtobufTargets_VERSION = ${ProtobufTargets_VERSION}") + if (ProtobufTargets_FOUND) + foreach (_target + protobuf::libprotobuf + protobuf::libprotobuf-lite + protobuf::libprotoc) + if (NOT TARGET ${_target}) + message( + STATUS + "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "target=${_target} is NOT a target") + endif () + endforeach () + unset(_target) + endif () +endif () + +find_package_handle_standard_args(ProtobufTargets + REQUIRED_VARS + ProtobufTargets_FOUND + ProtobufTargets_VERSION) |