Finding Protobuf package with CMake

2.2k Views Asked by At

I cannot seem to get CMake to consistently find my protobuf package. I would like to include the protobuf source and build it as part of my project. I'm using protobuf 3.15.8 and protobuf-c 1.3.3 (useful as a control example).

This is the directory setup for the example:

- CMakeLists.txt
- deps/
       - CMakeLists.txt
       - protobuf/            # The protobuf 3.15.8 repository
       - protobuf-c/          # The protobuf-c 1.3.3 repository
- target/
         - CMakeLists.txt

Root CMakeLists.txt:

cmake_minimum_required(VERSION 3.15)
project(PROTOBUF_IMPORT_FAIL)
add_subdirectory(deps)
add_subdirectory(target)

deps/CMakeLists.txt:

add_subdirectory(protobuf/cmake)
set(Protobuf_LIBRARIES "${CMAKE_CURRENT_BINARY_DIR}/protobuf/cmake/lib")
set(Protobuf_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/protobuf/src")
set(Protobuf_PROTOC_LIBRARY "${CMAKE_CURRENT_BINARY_DIR}/protobuf/cmake/libprotoc.a")
add_subdirectory(protobuf-c/build-cmake)

target/CMakeLists.txt:

set(Protobuf_LIBRARIES "${CMAKE_CURRENT_BINARY_DIR}/../deps/protobuf/cmake/lib")
set(Protobuf_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}../deps/protobuf/src")
message("This is the problem!")
FIND_PACKAGE(Protobuf REQUIRED)

Once everything is set up I can then try to run cmake:

mkdir build
cd build
cmake ..

Unfortunately, that eventually gives me the following error:

CMake Error at /usr/local/Cellar/cmake/3.23.0/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
  Could NOT find Protobuf (missing: Protobuf_INCLUDE_DIR)
Call Stack (most recent call first):
  /usr/local/Cellar/cmake/3.23.0/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:594 (_FPHSA_FAILURE_MESSAGE)
  /usr/local/Cellar/cmake/3.23.0/share/cmake/Modules/FindProtobuf.cmake:650 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
  target/CMakeLists.txt:7 (FIND_PACKAGE)

In case it's helpful, here's some of the environment information:

$ uname -a
Darwin coop-mac 21.4.0 Darwin Kernel Version 21.4.0: Fri Mar 18 00:45:05 PDT 2022; root:xnu-8020.101.4~15/RELEASE_X86_64 x86_64
$ cmake --version
cmake version 3.23.0

protobuf-c also tries to find the protobuf package, but it's actually successful. Why does searching for it from the target not find it and how do I fix it?

2

There are 2 best solutions below

0
On

find_package is used to find installed libraries. An installed library is normally found by a script shipped with cmake (so called find-modules) or because the library provides a config script (like protobuf-config.cmake or profobuf-targets.cmake). The latter is generated once the library is build and installed. This is possibly why your second configure step is successfull.

You don't want to link against the installed library, but build the library by yourself. So all you need to do is add the subfolders using add_subdirectory (don't add the cmake subfolder, it's deprecated according to protobuf). After that you can link protobuf against your target using target_link_libraries without using find_package.

0
On

I faced exact problem recently: two sub modules call find_package(Protobuf) and one of them fails (in the 1st run) due to "missing: Protobuf_INCLUDE_DIR".

After enabled cmake trace, I found something warnings:

  • Warnings from 1st find_package(Protobuf):
cmake-3.28/Modules/FindProtobuf.cmake(559):  find_path(Protobuf_INCLUDE_DIR google/protobuf/service.h PATHS ${Protobuf_SRC_ROOT_FOLDER}/src )
/root/bin/cmake/share/cmake-3.28/Modules/FindProtobuf.cmake(563):  mark_as_advanced(Protobuf_INCLUDE_DIR )
CMake Warning (dev) at /root/bin/cmake/share/cmake-3.28/Modules/FindProtobuf.cmake:563 (mark_as_advanced):
  Policy CMP0102 is not set: The variable named "Protobuf_INCLUDE_DIR" is not
  in the cache.  This results in an empty cache entry which is no longer
  created when policy CMP0102 is set to NEW.  Run "cmake --help-policy
  CMP0102" for policy details.  Use the cmake_policy command to set the
  policy and suppress this warning.
Call Stack (most recent call first):
  3rdparty/sentencepiece/src/CMakeLists.txt:75 (find_package)
This warning is for project developers.  Use -Wno-dev to suppress it.
  • Warnings from 2nd find_package(Protobuf):
cmake-3.28/Modules/FindProtobuf.cmake(559):  find_path(Protobuf_INCLUDE_DIR google/protobuf/service.h PATHS ${Protobuf_SRC_ROOT_FOLDER}/src )
CMake Warning (dev) at /root/bin/cmake/share/cmake-3.28/Modules/FindProtobuf.cmake:559 (find_path):
  Policy CMP0126 is not set: set(CACHE) does not remove a normal variable of
  the same name.  Run "cmake --help-policy CMP0126" for policy details.  Use
  the cmake_policy command to set the policy and suppress this warning.

  For compatibility with older versions of CMake, normal variable
  "Protobuf_INCLUDE_DIR" will be removed from the current scope.
Call Stack (most recent call first):
  3rdparty/deprecated/sami/lightseq/CMakeLists.txt:36 (find_package)
This warning is for project developers.  Use -Wno-dev to suppress it.

""Protobuf_INCLUDE_DIR" will be removed from the current scope." warning from the 2nd run is suspicious.

Solution

Set all Protobuf_* variables as cache variables, like:

set(Protobuf_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}../deps/protobuf/src" CACHE INTERNAL "Protobuf Include Dir")