grpc can't find protobuf library

ghz 1years ago ⋅ 10038 views

Question

I went over the grpc installation and finished building and installation.

Now when I try to:

find_package(gRPC CONFIG REQUIRED)

I get

CMake Error at CMakeLists.txt:15 (find_package):
  Found package configuration file:

    /usr/lib64/cmake/grpc/gRPCConfig.cmake

  but it set gRPC_FOUND to FALSE so package "gRPC" is considered to be NOT
  FOUND.  Reason given by package:

  The following imported targets are referenced, but are missing:
  protobuf::libprotobuf protobuf::libprotoc

Event though

find_package(Protobuf REQUIRED)

Works just fine.

I read I'm supposed to run cmake ../.. -DBUILD_DEPS=ON -DBUILD_SHARED_LIBS=ON to solve this. However that results in:

CMake Error at cmake/abseil-cpp.cmake:38 (find_package):
  Could not find a package configuration file provided by "absl" with any of
  the following names:

    abslConfig.cmake
    absl-config.cmake

  Add the installation prefix of "absl" to CMAKE_PREFIX_PATH or set
  "absl_DIR" to a directory containing one of the above files.  If "absl"
  provides a separate development package or SDK, be sure it has been
  installed.
Call Stack (most recent call first):
  CMakeLists.txt:191 (include)


-- Configuring incomplete, errors occurred!
See also "/home/ray/CLionProjects/grpc/grpc/CMakeFiles/CMakeOutput.log".
See also "/home/ray/CLionProjects/grpc/grpc/CMakeFiles/CMakeError.log".

Content of /usr/lib64/cmake/grpc/gRPCConfig.cmake

# Module path
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/modules)

# Depend packages






# Targets
include(${CMAKE_CURRENT_LIST_DIR}/gRPCTargets.cmake)

Answer

The problem is actually with the project you use via find_package() and with its package file (/usr/lib64/cmake/grpc/gRPCConfig.cmake in your case). The error message

The following imported targets are referenced, but are missing:

means, that the package file references IMPORTED targets but they are never defined.

The usual reason for that problem is following:

  1. During its own build, the project uses find_package() for some other packages. This find_package() call defines IMPORTED targets, which are used in the project for link.

  2. Its package file includes the script(s), which is created by install(EXPORT) command and filled according to install(TARGETS ... EXPORT ...) command. This included script uses IMPORTED targets, but doesn't define them.

  3. The project's package file forgets to use find_package, or, better, find_dependency for define the IMPORTED target for the included scripts.

If you don't want to fix the (other) project's package file, then the most direct solution is to add missed find_package into your own project:

# Hack: This will define IMPORTED targets, needed for gRPC project, but not defined by it.
find_package(Protobuf REQUIRED)
# Now perform the original 'find_package' call.
find_package(gRPC CONFIG REQUIRED)

Actually, gRPCConfig.cmake package file was intended to contain the call find_package(Protobuf). Its template cmake/gRPCConfig.cmake.in is following:

# Module path
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/modules)

# Depend packages
@_gRPC_FIND_ZLIB@
@_gRPC_FIND_PROTOBUF@
@_gRPC_FIND_SSL@
@_gRPC_FIND_CARES@
@_gRPC_FIND_ABSL@

# Targets
include(${CMAKE_CURRENT_LIST_DIR}/gRPCTargets.cmake)

and on substitution the variable _gRPC_FIND_PROTOBUF should emit the following code:

if(NOT Protobuf_FOUND AND NOT PROTOBUF_FOUND)
  find_package(Protobuf ${gRPC_PROTOBUF_PACKAGE_TYPE})
endif()

(the variable should be set in cmake/protobuf.cmake).

But something goes wrong, and the resulted /usr/lib64/cmake/grpc/gRPCConfig.cmake contains the empty variable's substitution:

# Module path
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/modules)

# Depend packages






# Targets
include(${CMAKE_CURRENT_LIST_DIR}/gRPCTargets.cmake)