Reputation: 35
I Written a very simple program in protobuf without services at all but when i run the code it throws erros like Example::Note::~Note() all information are given below please tell me where i'm making mistake.
syntax = "proto3";
package Example;
message Note {
int32 id = 1;
string title = 2;
string description = 3;
}
i use protoc --cpp_out=. example.proto
command to generate auto generated files
#include "example.pb.h"
#include <iostream>
int main(int argc, char const *argv[])
{
Example::Note note;
note.set_id(1);
note.set_title("This is Title");
note.set_description("This is Description");
std::cout << "Note Information: " << note.DebugString() << std::endl;
return 0;
}
cmake_minimum_required(VERSION 3.14)
project(EXAMPLE LANGUAGES CXX)
# Find Protobuf installation
# Looks for protobuf-config.cmake file installed by Protobuf's cmake installation.
set(protobuf_MODULE_COMPATIBLE TRUE)
find_package(Protobuf CONFIG REQUIRED)
message(STATUS "Using protobuf ${Protobuf_VERSION}")
set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)
set(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)
# Find gRPC installation
# Looks for gRPCConfig.cmake file installed by gRPC's cmake installation.
find_package(gRPC CONFIG REQUIRED)
message(STATUS "Using gRPC ${gRPC_VERSION}")
set(_GRPC_GRPCPP gRPC::grpc++)
set(_REFLECTION gRPC::grpc++_reflection)
set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_cpp_plugin>)
add_executable(Example
main.cpp
)
target_link_libraries(Example
Threads::Threads
${_REFLECTION}
${_GRPC_GRPCPP}
${_PROTOBUF_LIBPROTOBUF}
)
.
.
.
-- Build files have been written to: /home/react-vision/dev/workingWithProtobuff/simpleExample/build
[ 50%] Building CXX object CMakeFiles/Example.dir/main.cpp.o
[100%] Linking CXX executable Example
/usr/bin/ld: CMakeFiles/Example.dir/main.cpp.o: in function `main':
main.cpp:(.text+0xf4): undefined reference to `Example::Note::~Note()'
/usr/bin/ld: main.cpp:(.text+0x12f): undefined reference to `Example::Note::~Note()'
/usr/bin/ld: CMakeFiles/Example.dir/main.cpp.o: in function `Example::Note::Note()':
main.cpp:(.text._ZN7Example4NoteC2Ev[_ZN7Example4NoteC5Ev]+0x22): undefined reference to `Example::Note::Note(google::protobuf::Arena*, bool)'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/Example.dir/build.make:153: Example] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/Example.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
Upvotes: 1
Views: 1993
Reputation: 19916
The following CMakeLists.txt is enough for your example.proto
and main.cpp
file. It does not use gRPC because that wasn't relevant to testing.
cmake_minimum_required(VERSION 3.23)
project(example)
find_package(Protobuf REQUIRED)
protobuf_generate_cpp(example_srcs example_hdrs example.proto)
add_executable(main main.cpp ${example_srcs} ${example_hdrs})
target_include_directories(main PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
target_link_libraries(main PRIVATE protobuf::libprotobuf)
Below is a line-by-line explanation of this build and why it works.
Let's go line by line:
cmake_minimum_required(VERSION 3.23)
This must always be the first line of your top-level CMakeLists.txt file. It tells CMake which policies to enable. This is to ensure backwards compatibility, but not forwards compatibility, i.e. CMake will not emulate older versions, but will simply toggle back to old behaviors in certain cases. In particular, it will not stop you from using features that are too new for the stated minimum version, so you must always test your build with the version listed here. I wrote this answer using 3.23, but it will probably work with older versions.
project(example)
With very few exceptions, this will be the second line for your CMakeLists.txt. You can pick any project name you want. I chose example
here because, well, this is an example. This command is what kicks off CMake's compiler detection routines. It is invalid to do most things before that has happened.
find_package(Protobuf REQUIRED)
This project uses protobuf so we use find_package
to access CMake's first-party protobuf support (see documentation here). Because the project cannot possibly work without protobuf, we add the REQUIRED
argument.
protobuf_generate_cpp(example_srcs example_hdrs example.proto)
Now we call a function provided by the find_package(Protobuf ...)
module. This wraps a call to the protobuf compiler and defines two variables, example_srcs
and example_hdrs
(the names are arbitrary), to hold the files generated from example.proto
. This isn't well-documented, but the generated files are placed in ${CMAKE_CURRENT_BINARY_DIR}
.
add_executable(main main.cpp ${example_srcs} ${example_hdrs})
Now we create an executable target from your source file (main.cpp
) and the aforementioned generated source files.
target_include_directories(main PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
The source files for main
need to see the generated sources, so we add ${CMAKE_CURRENT_BINARY_DIR}
to the list of include directories.
target_link_libraries(main PRIVATE protobuf::libprotobuf)
Finally, the application needs to link to the protobuf library, so we link to the imported protobuf::libprotobuf
target. This, too, was created by the find_package(Protobuf ...)
command.
To adjust this build to use Protobuf's own CMake support and to skip CMake's module, you will need to make the following changes:
CONFIG
to find_package
.protobuf_generate_cpp
with protobuf_generate
.This is what the build would look like:
cmake_minimum_required(VERSION 3.23)
project(example)
find_package(Protobuf CONFIG REQUIRED)
add_executable(main main.cpp)
protobuf_generate(TARGET main PROTOS example.proto)
target_include_directories(main PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
target_link_libraries(main PRIVATE protobuf::libprotobuf)
The CONFIG
argument tells CMake to ignore any find modules that match (including its own first-party modules). Then the new command protobuf_generate
replaces protobuf_generate_cpp
. Now instead of populating source variables, you give it the target for which you're generating sources. The PROTOS
argument is the list of protobuf files to compile.
Because it takes the target as an argument, it must follow add_exectuable
, rather than precede it.
Here's how I built protobuf from sources to test this:
$ git clone --recursive [email protected]:protocolbuffers/protobuf.git
$ cmake -G Ninja -S protobuf -B _build/protobuf -DCMAKE_BUILD_TYPE=Release -Dprotobuf_BUILD_TESTS=NO -DCMAKE_INSTALL_PREFIX=$PWD/_local
$ cmake --build _build/protobuf/ --target install
Now I can compile the program in this example:
alex@alex-ubuntu:~/test$ cmake -G Ninja -S . -B _build/project -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$PWD/_local
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found ZLIB: /usr/lib/x86_64-linux-gnu/libz.so (found version "1.2.11")
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: /home/alex/test/_build/project
alex@alex-ubuntu:~/test$ cmake --build _build/project/ --verbose
[1/4] cd /home/alex/test/_build/project && /home/alex/test/_local/bin/protoc-3.21.0.2 --cpp_out :/home/alex/test/_build/project -I /home/alex/test /home/alex/test/example.proto
[2/4] /usr/bin/c++ -I/home/alex/test/_build/project -isystem /home/alex/test/_local/include -O3 -DNDEBUG -MD -MT CMakeFiles/main.dir/main.cpp.o -MF CMakeFiles/main.dir/main.cpp.o.d -o CMakeFiles/main.dir/main.cpp.o -c /home/alex/test/main.cpp
[3/4] /usr/bin/c++ -I/home/alex/test/_build/project -isystem /home/alex/test/_local/include -O3 -DNDEBUG -MD -MT CMakeFiles/main.dir/example.pb.cc.o -MF CMakeFiles/main.dir/example.pb.cc.o.d -o CMakeFiles/main.dir/example.pb.cc.o -c /home/alex/test/_build/project/example.pb.cc
[4/4] : && /usr/bin/c++ -O3 -DNDEBUG CMakeFiles/main.dir/main.cpp.o CMakeFiles/main.dir/example.pb.cc.o -o main ../../_local/lib/libprotobuf.a -lpthread /usr/lib/x86_64-linux-gnu/libz.so && :
alex@alex-ubuntu:~/test$ ./_build/project/main
Note Information: id: 1
title: "This is Title"
description: "This is Description"
Upvotes: 3