# ~~~
# 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:
FindProtobufWithTargets
-------------------

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 ``ProtobufWithTargets_FOUND`` and
  ``ProtobufWithTargets_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 ``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(ProtobufWithTargets 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}"
                   " ProtobufWithTargets = ${ProtobufWithTargets_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 QUIET)

if (protobuf_DEBUG)
    message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
                   "Protobuf_FOUND = ${Protobuf_FOUND}"
                   " Protobuf_VERSION = ${Protobuf_VERSION}")
endif ()

if (NOT Protobuf_FOUND)
    find_package(Protobuf QUIET)
endif ()

if (Protobuf_FOUND)
    set(ProtobufWithTargets_FOUND 1)
    set(ProtobufWithTargets_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 ()

    if (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} ] "
                    "ProtobufWithTargets_FOUND = ${ProtobufWithTargets_FOUND}"
                    " ProtobufWithTargets_VERSION = ${ProtobufWithTargets_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 ()
endif ()

if (protobuf_DEBUG)
    message(
        STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
               "ProtobufWithTargets_FOUND = ${ProtobufWithTargets_FOUND}"
               " ProtobufWithTargets_VERSION = ${ProtobufWithTargets_VERSION}")
endif ()

if (protobuf_DEBUG)
    message(
        STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] "
               "ProtobufWithTargets_FOUND = ${ProtobufWithTargets_FOUND}"
               " ProtobufWithTargets_VERSION = ${ProtobufWithTargets_VERSION}")
    if (ProtobufWithTargets_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(
    ProtobufWithTargets REQUIRED_VARS ProtobufWithTargets_FOUND
                                      ProtobufWithTargets_VERSION)
