Generate grpc files for a library target in CMAKE - c++

In the following project structure(from my previous question):
root/
├─ CMakeLists.txt
├─ protocol/
│ ├─ msg.proto
│ ├─ myrpc.proto
│ ├─ CMakeLists.txt
├─ app/
│ ├─ main.cpp
│ ├─ CMakeLists.txt
I could generate the protobuf files and add them as dependency into the app target. Now I am trying to generate grpc files inside the same library.
Something is not right with the grpc generation function, which is based on this answer and blog post;as the following error message is printed:
-- Configuring done
-- Generating done
-- Build files have been written to: /media/davids91/Work/rafko/src/main/cxx/build
[ 1%] Running grpc protocol buffer compiler on /usr/local/bin/grpc_cpp_plugin
/usr/local/bin/grpc_cpp_plugin: File does not reside within any path specified using --proto_path (or -I). You must specify a --proto_path which encompasses this file. Note that the proto_path must be an exact prefix of the .proto file names -- protoc is too dumb to figure out when two paths (e.g. absolute and relative) are equivalent (it's harder than you think).
make[2]: * [protocol/CMakeFiles/protocol.dir/build.make:138: /media/usr/local/bin/grpc_cpp_plugin.grpc.pb.h] Error 1
make[1]: * [CMakeFiles/Makefile2:276: protocol/CMakeFiles/protocol.dir/all] Error 2
make: * [Makefile:103: all] Error 2
I can see that the install folder looks correct, as that is where the grpc library was installed from source.
root CMakeLists.txt:
cmake_minimum_required(VERSION 3.18.4)
project(
root
VERSION 0.1
LANGUAGES CXX
)
add_subdirectory(protocol)
add_subdirectory(app)
protocol CMakeLists.txt:
add_library(protocol)
target_include_directories(protocol
PUBLIC
.
${CMAKE_CURRENT_BINARY_DIR}
${Protobuf_INCLUDE_DIRS}
)
find_package(Protobuf REQUIRED)
find_package(gRPC CONFIG REQUIRED)
target_link_libraries(protocol ${Protobuf_LIBRARIES})
get_target_property(grpc_cpp_plugin_location gRPC::grpc_cpp_plugin LOCATION)
protobuf_generate( TARGET protocol LANGUAGE CPP PROTOS msg.proto )
protobuf_generate(
TARGET
protocol
LANGUAGE
grpc
PROTOS
myrpc.proto
PLUGIN
"protoc-gen-grpc=${grpc_cpp_plugin_location}"
)
app CMakeLists.txt:
add_library(app)
target_link_libraries(app PUBLIC protocol)
target_include_directories(app PUBLIC .)
target_sources(app
PRIVATE
main.cpp
)
What might be missing from this solution to generate out the grpc files based on the plugins?

After some experimenting and closely looking at the example here I figured it out!
I updated protocol CMakeLists.txt:
changed
find_package(Protobuf REQUIRED)
to
find_package(Protobuf CONFIG REQUIRED)
I figure it tells CMake that the proto files are being procesed at configuration time, but any deeper explanation is welcome!

Related

How to include library from sibling directory in CMakeLists.txt for compilation

I am working on a C project as of recently and want to learn how to use CMake properly.
The project consists of the following directory structure (as of now):
.
└── system
├── collections
│ ├── bin
│ ├── build
│ ├── includes
│ └── src
└── private
└── corelib
├── bin
├── build
├── includes
└── src
Every directory including 'bin' sub-directories is a separate library. They contain a CMakeLists.txt each.
The plan is to link the libraries in such a way that, during development, no manual recompilation of 'corelib' should be required to receive updated code from it, while also ensuring that dependencies would be resolved once all libraries get compiled as SHARED libraries and put in a place such as 'usr/local/lib' or similar.
I have a dependency of library 'corelib' in library 'collections'.
Trying to resolve said dependency, I have come up with the following CMakeLists.txt in 'collections':
cmake_minimum_required(VERSION 3.0.0)
project(collections VERSION 0.1.0 LANGUAGES C)
set(LIBRARY_OUTPUT_PATH ../bin)
add_subdirectory(../private/corelib ${LIBRARY_OUTPUT_PATH})
include_directories(./includes)
aux_source_directory(./src SOURCES)
add_library(collections SHARED ${SOURCES} main.c)
However, this does not produce the result I am looking for, as I get the following output on build:
[main] Building folder: collections
[build] Starting build
[proc] Executing command: /usr/bin/cmake --build /home/codeuntu/Repositories/netcore-c/src/system/collections/build --config Debug --target all -j 6 --
[build] gmake[1]: *** No rule to make target '../bin/all', needed by 'all'. Stop.
[build] gmake[1]: *** Waiting for unfinished jobs....
[build] Consolidate compiler generated dependencies of target collections
[build] [ 50%] Built target collections
[build] gmake: *** [Makefile:91: all] Error 2
[build] Build finished with exit code 2
It seems this is the wrong way to go about it. Any help is greatly appreciated.
This is the CMakeLists.txt for 'corelib':
cmake_minimum_required(VERSION 3.0.0)
project(corelib VERSION 0.1.0 LANGUAGES C)
include_directories(./includes)
aux_source_directory(./src SOURCES)
set(LIBRARY_OUTPUT_PATH ../bin)
add_library(corelib SHARED ${SOURCES} main.c)
Binary directory has to be a subdirectory of current dir, it can't be above ../bin. Use:
add_subdirectory(../private/corelib some_unique_name)
Overall, let's fix some issues. A more advanced CMake might look like this:
# system/CmakeLists.txt
add_subdirectory(private EXCLUDE_FROM_ALL)
add_subdirectory(collections)
# system/collections/CMakeLists.txt
cmake_minimum_required(VERSION 3.11)
project(collections VERSION 0.1.0 LANGUAGES C)
file(GLOB_RECURSE srcs *.c *.h)
add_library(collections ${srcs})
# Use only target_* intefaces
target_include_directories(collections PUBLIC
./includes
)
target_link_libraries(collections PRIVATE
corelib
)
# system/private/CMakeLists.txt
add_subdirectory(corelib)
# system/private/corelib/CMakeLists.txt
cmake_minimum_required(VERSION 3.11)
project(corelib VERSION 0.1.0 LANGUAGES C)
file(GLOB_RECURSE srcs *.c *.h)
add_library(corelib ${srcs})
target_include_directorieS(corelib PUBLIC ./includes)
# system/CMakePresets.json
{
... see documentation ...
"configurePresets": [
{
...
"cacheVariables": {
"BUILD_SHARED_LIBS": "1",
"ARCHIVE_OUTPUT_DIRECTORY": "${binaryDir}/bin",
"LIBRARY_OUTPUT_DIRECTORY": "${binaryDir}/bin",
"RUNTIME_OUTPUT_DIRECTORY": "${binaryDir}/bin"
}
}
I.e. overall, I do not think every project inside system wants to compile his own separate instance of corelib, rather one corelib should be shared. Just add corelib once, from anywhere. Note that it doesn't have to be in order - you can target_link_libraries on targets before they are defined.

CMake No such file or directory

I have a problem building my Qt5 project via cmake.
I run the command cmake .. && make from the directory build and I receive the following error:
/usr/bin/ld: cannot find -lengine-lib
collect2: error: ld returned 1 exit status
make[2]: *** [src/CMakeFiles/blacklist-engine-cli.dir/build.make:102: src/blacklist-engine-cli] Error 1
make[1]: *** [CMakeFiles/Makefile2:117: src/CMakeFiles/blacklist-engine-cli.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
I have searched this topic briefly, however when I ran this project without Qt5Sql, using only Qt5Core I have no problem at all building the project. In order to build the project without Qt5Sql I just have to remove the db folder, and delete lines referring to that in my other CMakeLists.txt files. My question is:
Why does it work if I want to include only Qt5Core, and why does it not work when I also include Qt5Sql? What am I doing wrong including Qt5Sql?
Please do not include answers related to QtCreator, or Qt installation errors. I have checked my Qt installation folder, and I have Qt5Core and Qt5Sql on the same directory level installed.
I am using Ubuntu 20.04, cmake version 3.16.3, Qt version 5.12.8
ls /usr/lib/x86_64-linux-gnu/cmake
Qt5 Qt5Core Qt5Gui Qt5OpenGL Qt5PrintSupport Qt5Test Qt5Xml
Qt5Concurrent Qt5DBus Qt5Network Qt5OpenGLExtensions Qt5Sql Qt5Widgets
I have the following structure in my project:
root
├── CMakeModules
│ └── Qt.cmake
├── build
├── src
│ ├── db
│ │ ├── dbmanager.cpp
│ │ ├── dbmanager.h
│ │ └── CMakeLists.txt
│ ├── engine
│ │ ├── scanner.cpp
│ │ ├── scanner.h
│ │ └── CMakeLists.txt
│ ├── CMakeLists.txt
│ └── main.cpp
└── CMakeLists.txt
CMakeLists.txt:
cmake_minimum_required(VERSION 3.0)
project(blacklist-engine)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMakeModules)
add_subdirectory(src)
CMakeModules/Qt.cmake:
set(CMAKE_AUTOMOC ON)
find_package(Qt5 REQUIRED COMPONENTS Core Sql)
src/CMakeLists.txt:
include(Qt)
add_subdirectory(
db
engine
)
add_executable(blacklist-engine-cli main.cpp)
target_link_libraries(
blacklist-engine-cli
Qt5::Core
Qt5::Sql
engine-lib
db-lib
)
src/main.cpp:
#include <QtCore>
#include "db/dbmanager.h"
#include "engine/scanner.h"
...
src/db/CMakeLists.txt (updated):
set (db-lib-source
dbmanager.h
dbmanager.cpp
)
add_library(db-lib ${db-lib-source})
target_link_libraries(
db-lib
Qt5::Sql
)
src/db/dbmanager.h:
#include <QtSql/QSqlDatabase>
...
src/db/dbmanager.cpp:
#include "dbmanager.h"
#include <QtSql/QSqlQuery>
...
src/engine/CMakeLists.txt:
set(engine-lib-source
scanner.h
scanner.cpp
)
add_library(engine-lib ${engine-lib-source})
src/engine/scanner.h:
#include <QtCore>
...
src/engine/scanner.cpp:
#include "scanner.h"
...
The reason for the error is because engine-lib is never built, and its CMake file is never even processed. The offending line in your CMake file is this one:
add_subdirectory(
db
engine
)
When using add_subdirectory in this manner, the second argument becomes the binary directory for the generated content related to db. As a result, you may notice that CMake placed some build artifacts in your src/engine directory, which is probably not what you want.
To fix this, you must call add_subdirectory consecutive times for including multiple sub-directories.
add_subdirectory(db)
add_subdirectory(engine)

Build zLib with CMake

I'm trying to build Zlib and quazip automatic with the rest of my project. I want to do it in a similar way as I add googletest to my project.
zLib and Quazip shall be linked static to my App.
I want to to this because of CI/ CD reasons and if somebody else wants to build the project he do not have to worry about those dependencies (especially under windows)...
Download it at configure time with CMake ExternalProject_Add
add it on target level
My structure is like the following:
project/
├── CMakelists.txt (1)
├── sources/
│ ├── APP/
│ │ ├── CMakeLists.txt (2)
│ │ ├── thirdparty/
│ │ │ ├── CMakeLists.txt (3)
│ │ │ ├── zlib
│ │ │ │ ├── CMakeLists.txt.in
│ │ │ ├── quazip
│ │ │ │ ├── CMakeLists.txt.in
│ │ │ │ ├── CMakeListsBuild.txt.in
Thats complicated enough but let me show you what I do where...
(1) CMakeLists.txt
Noting special just adding all the packages together like APP
(2) CMakeLists.txt
cmake_minimum_required(VERSION 3.15.2)
project(Project VERSION 0.0.1)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
#Add the needed Qt Components
find_package(Qt5 COMPONENTS
Core
Network
REQUIRED)
add_subdirectory(thirdparty)
SET(INCLUDES
...
)
SET(SOURCES
...
)
target_compile_options(${PROJECT_NAME} PUBLIC
...
)
target_compile_definitions(${PROJECT_NAME} PUBLIC
QUAZIP_STATIC )
target_include_directories(${PROJECT_NAME} PRIVATE
OtherIncludes
"${QUAZIP_INCLUDE_DIR}"
)
target_link_libraries(${PROJECT_NAME}
Qt5::Network
Qt5::Core
SomeOtherDep
quazip_static <---- adding static targets here
zlibstatic <---- adding static targets here
)
(3) CMakeLists.txt
# Download and unpack at configure time
configure_file(zlib/CMakeLists.txt.in zlib-download/CMakeLists.txt)
execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/zlib-download"
)
execute_process(COMMAND "${CMAKE_COMMAND}" --build .
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/zlib-download"
)
add_subdirectory("${CMAKE_BINARY_DIR}/zlib-src"
"${CMAKE_BINARY_DIR}/zlib-build"
)
# Download and unpack at configure time
configure_file(quazip/CMakeLists.txt.in quazip-download/CMakeLists.txt)
execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/quazip-download"
)
execute_process(COMMAND "${CMAKE_COMMAND}" --build .
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/quazip-download"
)
configure_file(quazip/CMakeListsBuild.txt.in ${CMAKE_BINARY_DIR}/quazip-src/CMakeLists.txt COPYONLY)
add_subdirectory("${CMAKE_BINARY_DIR}/quazip-src"
"${CMAKE_BINARY_DIR}/quazip-build"
)
set(QUAZIP_INCLUDE_DIR
"${CMAKE_BINARY_DIR}/quazip-src/quazip" PARENT_SCOPE)
The two CMakeLists.txt.in have nearly the same Content...
cmake_minimum_required(VERSION 2.8.2)
include(ExternalProject)
project(quazip-download NONE)
ExternalProject_Add(quazip
GIT_REPOSITORY git://github.com/stachenov/quazip.git
GIT_TAG v0.8.1
SOURCE_DIR "${CMAKE_BINARY_DIR}/quazip-src"
BINARY_DIR "${CMAKE_BINARY_DIR}/quazip-build"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)
cmake_minimum_required(VERSION 2.8.2)
include(ExternalProject)
project(zlib-download NONE)
ExternalProject_Add(zlib
GIT_REPOSITORY git://github.com/madler/zlib.git
GIT_TAG v1.2.11
SOURCE_DIR "${CMAKE_BINARY_DIR}/zlib-src"
BINARY_DIR "${CMAKE_BINARY_DIR}/zlib-build"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)
Then there is the last CMakeListsBuild.txt.in in the quazip folder. I'm just editing the original one and feed the zlib dependencies directly in. It looks like this:
cmake_minimum_required(VERSION 2.6)
project(QuaZip)
...
EVERYTHING ORIGINAL
...
# Use system zlib on unix and Qt ZLIB on Windows
# will be set from outside ZLIB_LIBRARIES ZLIB_INCLUDE_DIRS
--------------------ADDED BY ME REMOVED find_packages...
set(ZLIB_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/zlib-src
${CMAKE_BINARY_DIR}/zlib-build)
if(UNIX)
set(ZLIB_LIBRARIES
"${CMAKE_BINARY_DIR}/zlib-build/libz.a")
elseif(MINGW)
set(ZLIB_LIBRARIES
"${CMAKE_BINARY_DIR}/zlib-build/libzlibstatic.a")
endif()
...
EVERYTHING ORIGINAL
...
Question
Downloading and building the static lib of zlib works but I get the following error while compiling under linux.
/home/linuxmint/someDirectory/build/zlib-src/test/example.c:8:10: fatal error: zlib.h: No such file or directory
#include "zlib.h"
^~~~~~~~
compilation terminated.
zlib-build/CMakeFiles/example.dir/build.make:75: recipe for target 'zlib-build/CMakeFiles/example.dir/test/example.o' failed
make[2]: *** [zlib-build/CMakeFiles/example.dir/test/example.o] Error 1
CMakeFiles/Makefile2:1355: recipe for target 'zlib-build/CMakeFiles/example.dir/all' failed
make[1]: *** [zlib-build/CMakeFiles/example.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
This is the strange part I dont understand. If I have a look in the CMakeLists of zlib. (LINK)
They add everything of of the source and binary folder to the include with this:
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR})
So I don't understand why the example of zlib (and everything else which need zlib.h) can't be build...
Perhabs somebody has a hint...
Thanks...
Edit
If I install the headers with apt building works... But why ;) Since nowhere find_package is called...
Thanks to #squarekittles who pointed me in the right direction.
In the CMakeLists.txt of zlib the include dir is specified as ${CMAKE_SOURCE_DIR}. This is of course the wrong directory...
I added a additional CMakeLists.txt.in for zlib which will replace the original one. It's all the same only two lines are different:
...
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
^~~~~~~~~~~~~ Added in
#============================================================================
# zlib
#============================================================================
set(ZLIB_PUBLIC_HDRS
${CMAKE_CURRENT_BINARY_DIR}/zconf.h
${CMAKE_CURRENT_SOURCE_DIR}/zlib.h
) ^~~~~~~~~~~~~ Added in
...
Now the examples compile...
Also I needed to add the headers of zlib to my project did it by editing CMakeLists.txt (3)
...
configure_file(zlib/CMakeListsBuild.txt.in ${CMAKE_BINARY_DIR}/zlib-src/CMakeLists.txt COPYONLY) <--- Replacing CMakeLists.txt for zlib
...
set(QUAZIP_INCLUDE_DIR
"${CMAKE_BINARY_DIR}/quazip-src/quazip"
${ZLIB_INCLUDE_DIR} PARENT_SCOPE)
^~~~~~~~~~~~ Added in
...

cmake mutliple targets - one header only target and another an executable

Based on this stackoverflow answer to a similar question (Cmake include header only target from header only target), I am creating a header only library and trying to use it in an executable.
My folder structure is below:
├── CMakeLists.txt // root folder CMake file
├── srcs // this is the hdr only library
│   ├── src1.hpp
│   ├── CMakeLists.txt
│   ├── src2.hpp
│   └── src3.hpp
│   └── ...
└── test // this is the executable project
├── CMakeLists.txt
└── main.cpp
Root level CMakeLists.txt
cmake_minimum_required(VERSION 3.13)
project (MyProj CXX)
add_subdirectory(srcs)
add_subdirectory(test)
src level CMakeLists.txt (for header only library)
add_library(MyLib INTERFACE)
target_sources(MyLib INTERFACE
"${CMAKE_CURRENT_SOURCE_DIR}/src1.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src2.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src3.hpp"
)
target_include_directories(MyLib
INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
add_subdirectory(plugins)
CMake file for executable test project
add_executable(MyTest main.cpp)
target_sources(MyTest
PRIVATE main.cpp
)
target_include_directories(MyTest PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
target_link_libraries(MyTest PUBLIC MyLib)
Though this configures cmake without warnings/error, running the make fails, indicating that the executable project is unable to find the header file(s) from library.
/.../nettu2/test/main.cpp:6:10: fatal error: src1.hpp: No such
file or directory #include "src1.hpp"
^~~~~~~~~~~~~~~~ compilation terminated. test/CMakeFiles/MyTest.dir/build.make:62: recipe for target
'test/CMakeFiles/MyTest.dir/main.cpp.o' failed make[2]: *
[test/CMakeFiles/MyTest.dir/main.cpp.o] Error 1
CMakeFiles/Makefile2:126: recipe for target
'test/CMakeFiles/MyTest.dir/all' failed make[1]: *
[test/CMakeFiles/MyTest.dir/all] Error 2 Makefile:129: recipe for
target 'all' failed make: *** [all] Error 2
I am sure that I am missing some crucial but trivial thing here, but yet unable to figure out, what is going wrong here. How can I get this build working?
You have a minor mistake in this line:
target_include_directories(MyLib
INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
The include directory you specify for MyLib expands to the build directory corresponding to srcs, i.e. it results in an invocation like
clang++ /path/to/build/test/test.cpp -I /path/to/build/srcs ...
but you want to pass the actual source directory to the preprocessor. To fix this, try
target_include_directories(MyLib
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

Unable to use locally installed Protocol Buffers inside ROS

I have installed Protocol Buffers locally. Below is the directory structure of ROS package:
.
├── CMakeLists.txt
├── package.xml
├── include
│   ├── addressbook.pb.cc
│   ├── addressbook.pb.h
│   └── addressbook.proto
├── lib
│   └── protobuf-3.5.0
└── src
└── main.cpp
Protocol Buffers was installed locally by using ./configure --prefix=$PWD inside lib/protobuf-3.5.0 directory.
While compiling the ROS package using catkin_make, it seems referring to an old installation of Protocol Buffers and showing version incompatibility errors.
[ 0%] Building CXX object local_protobuf_ros_example/CMakeFiles/addressbook_protobuf.dir/include/addressbook.pb.cc.o
In file included from /home/bgplvm/ros_ws/src/local_protobuf_ros_example/include/addressbook.pb.cc:4:0:
/home/bgplvm/ros_ws/src/local_protobuf_ros_example/include/addressbook.pb.h:12:2: error: #error This file was generated by a newer version of protoc which is
#error This file was generated by a newer version of protoc which is
^
/home/bgplvm/ros_ws/src/local_protobuf_ros_example/include/addressbook.pb.h:13:2: error: #error incompatible with your Protocol Buffer headers. Please update
#error incompatible with your Protocol Buffer headers. Please update
^
/home/bgplvm/ros_ws/src/local_protobuf_ros_example/include/addressbook.pb.h:14:2: error: #error your headers.
#error your headers.
^
In file included from /home/bgplvm/ros_ws/src/local_protobuf_ros_example/include/addressbook.pb.cc:4:0:
/home/bgplvm/ros_ws/src/local_protobuf_ros_example/include/addressbook.pb.h:23:35: fatal error: google/protobuf/arena.h: No such file or directory
#include <google/protobuf/arena.h>
^
compilation terminated.
Although, I put message(STATUS "Using Protocol Buffers ${Protobuf_VERSION}") statement inside CMakeLists.txt and found that it is using Protocol Buffers 3.5.0. See below the CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.3)
project(local_protobuf_ros_example)
find_package(catkin REQUIRED COMPONENTS roscpp)
set(PROTOBUF_FOLDER ${PROJECT_SOURCE_DIR}/lib/protobuf-3.5.0)
set(CMAKE_PREFIX_PATH
${CMAKE_PREFIX_PATH}
"${PROTOBUF_FOLDER}/cmake/build/release/lib/x86_64-linux-gnu/cmake/protobuf"
)
find_package(Protobuf CONFIG REQUIRED)
message(STATUS "Using Protocol Buffers ${Protobuf_VERSION}")
catkin_package()
include_directories(include ${catkin_INCLUDE_DIRS} ${PROTOBUF_INCLUDE_DIRS})
add_library(addressbook_protobuf include/addressbook.pb.cc)
add_executable(main src/main.cpp)
target_link_libraries(main ${catkin_LIBRARIES} addressbook_protobuf ${PROTOBUF_LIBRARIES})
What is missing here? Since I am referring to the local installation, it should work without showing errors. Isn't it?
Your set of CMAKE_PREFIX_PATH is incorrect. It should point to the prefix in which protobuf was installed, not the location of the cmake config file for the package.
So try changing:
set(CMAKE_PREFIX_PATH
${CMAKE_PREFIX_PATH}
${PROTOBUF_FOLDER}/cmake/build/release/lib/x86_64-linux-gnu/cmake/protobuf
)
To this:
set(CMAKE_PREFIX_PATH
${CMAKE_PREFIX_PATH}
${PROTOBUF_FOLDER}
)
That is, assuming ${PROTOBUF_FOLDER} points to the same location given to the --prefix argument of ./configure --prefix=<INSTALL_PREFIX>
See the search paths documentation for find_package here. (about half way down the page)
I believe if you were on Windows what you had would have worked as <prefix>/ is one of the search paths for that platform. But on Unix based OS'es you have these as the search paths (per the documentation on above link):
<prefix>/(lib/<arch>|lib|share)/cmake/<name>*/
<prefix>/(lib/<arch>|lib|share)/<name>*/
<prefix>/(lib/<arch>|lib|share)/<name>*/(cmake|CMake)/
You also have to be careful about case sensitivity here. Note that in the above paths the last path element they search is <name>*. From what I can see in your question it looks like protobuf installs itself under the name of
'protobuf', but your find_package call is asking for 'Protobuf'. So, try also changing your call to:
find_package(protobuf CONFIG REQUIRED)
And finally, as far as I can tell, protobuf doesn't install CMake configs when doing a build via ./configure .... To get the CMake configs installed I had to build via CMake by doing:
cd protobuf-3.5/cmake
cmake -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR> .
make
make install
I found a workaround to use locally installed Protocol Buffers.
I just need to set following two variables to locally installed Protocol Buffers:
Protobuf_INCLUDE_DIRS
Protobuf_LIBRARIES
Please see the CMakeLists.txt below:
cmake_minimum_required(VERSION 2.8.3)
project(local_protobuf_ros_example)
find_package(catkin REQUIRED COMPONENTS roscpp)
set(PROTOBUF_FOLDER ${PROJECT_SOURCE_DIR}/lib/protobuf-3.5.0)
set(Protobuf_INCLUDE_DIRS ${PROTOBUF_FOLDER}/include)
set(Protobuf_LIBRARIES ${PROTOBUF_FOLDER}/lib/libprotobuf.so)
catkin_package()
include_directories(include ${catkin_INCLUDE_DIRS} ${Protobuf_INCLUDE_DIRS})
add_library(addressbook_protobuf include/addressbook.pb.cc)
add_executable(main src/main.cpp)
target_link_libraries(main ${catkin_LIBRARIES} addressbook_protobuf ${Protobuf_LIBRARIES})
It works as of now. However, I am not sure, if it is a good practice or not. Anyone having a better solution is most welcome.