mirror of
https://github.com/ttroy50/cmake-examples.git
synced 2025-12-18 20:24:35 +03:00
add protobuf example for code generation
This commit is contained in:
24
03-code-generation/protobuf/AddressBook.proto
Normal file
24
03-code-generation/protobuf/AddressBook.proto
Normal file
@@ -0,0 +1,24 @@
|
||||
package tutorial;
|
||||
|
||||
message Person {
|
||||
required string name = 1;
|
||||
required int32 id = 2;
|
||||
optional string email = 3;
|
||||
|
||||
enum PhoneType {
|
||||
MOBILE = 0;
|
||||
HOME = 1;
|
||||
WORK = 2;
|
||||
}
|
||||
|
||||
message PhoneNumber {
|
||||
required string number = 1;
|
||||
optional PhoneType type = 2 [default = HOME];
|
||||
}
|
||||
|
||||
repeated PhoneNumber phone = 4;
|
||||
}
|
||||
|
||||
message AddressBook {
|
||||
repeated Person person = 1;
|
||||
}
|
||||
33
03-code-generation/protobuf/CMakeLists.txt
Normal file
33
03-code-generation/protobuf/CMakeLists.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
# Set the project name
|
||||
project (protobuf_example)
|
||||
|
||||
# find the protobuf compiler and libraries
|
||||
find_package(Protobuf REQUIRED)
|
||||
|
||||
# check if protobuf was found
|
||||
if(PROTOBUF_FOUND)
|
||||
message ("protobuf found")
|
||||
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
else()
|
||||
message (FATAL_ERROR "Cannot find Protobuf")
|
||||
endif()
|
||||
|
||||
# Generate the .h and .cxx files
|
||||
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS AddressBook.proto)
|
||||
|
||||
# Print path to generated files
|
||||
message ("PROTO_SRCS = ${PROTO_SRCS}")
|
||||
message ("PROTO_HDRS = ${PROTO_HDRS}")
|
||||
|
||||
# Add an executable
|
||||
add_executable(protobuf_example
|
||||
main.cpp
|
||||
${PROTO_SRCS}
|
||||
${PROTO_HDRS})
|
||||
|
||||
# link the exe against the libraries
|
||||
target_link_libraries(protobuf_example
|
||||
${PROTOBUF_LIBRARIES})
|
||||
224
03-code-generation/protobuf/README.adoc
Normal file
224
03-code-generation/protobuf/README.adoc
Normal file
@@ -0,0 +1,224 @@
|
||||
= Protobuf Code Generation
|
||||
|
||||
:toc:
|
||||
:toc-placement!:
|
||||
|
||||
toc::[]
|
||||
|
||||
|
||||
[[intro]]
|
||||
Introduction
|
||||
------------
|
||||
|
||||
This example shows how to generate class information using https://github.com/google/protobuf[protobuf].
|
||||
Protocol Buffers is a data serialization format from Google. A user provides a
|
||||
`.proto` file with a description of the data. Then using the protobuf compiler, the proto file
|
||||
can be translated into source code in a number of languages including C++.
|
||||
|
||||
The files in this tutorial are below:
|
||||
|
||||
```
|
||||
$ tree
|
||||
.
|
||||
├── AddressBook.proto
|
||||
├── CMakeLists.txt
|
||||
├── main.cpp
|
||||
```
|
||||
|
||||
* AddressBook.proto - proto file from main protocol buffer https://developers.google.com/protocol-buffers/docs/cpptutorial[example]
|
||||
* CMakeLists.txt - Contains the CMake commands you wish to run
|
||||
* main.cpp - The source file from the protobuf example.
|
||||
|
||||
[[requirements]]
|
||||
Requirements
|
||||
~~~~~~~~~~~~
|
||||
|
||||
This example requires the protocol buffers binary and libraries to be installed.
|
||||
|
||||
This can be installed on Ubuntu using
|
||||
|
||||
```
|
||||
sudo apt-get install protobuf-compiler sudo apt-get install protobuf-compiler
|
||||
```
|
||||
|
||||
[[concepts]]
|
||||
Concepts
|
||||
~~~~~~~~
|
||||
|
||||
[[exported_variables]]
|
||||
Exported Variables
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The variables exported by the CMake protobuf package and used in this example include:
|
||||
|
||||
* `PROTOBUF_FOUND` - If Protocol Buffers is installed
|
||||
* `PROTOBUF_INCLUDE_DIRS` - The protobuf header files
|
||||
* `PROTOBUF_LIBRARIES` - The protobuf library
|
||||
|
||||
More variables are defined and can be found by examining the documentation at the
|
||||
top of your `FindProtobuf.cmake` file.
|
||||
|
||||
[[generating-protobuf]]
|
||||
Generating Source
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
The protobuf CMake package, includes a number of helper functions to make the
|
||||
code generation easier. In this example we are generating C++ source and use
|
||||
the following code:
|
||||
|
||||
[source,cmake]
|
||||
----
|
||||
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS AddressBook.proto)
|
||||
----
|
||||
|
||||
The arguments are:
|
||||
|
||||
* PROTO_SRCS - Name of the variable that will store the .pb.cc files.
|
||||
* PROTO_HDRS- Name of the variable that will store the .pb.h files.
|
||||
* AddressBook.proto - The .proto file to generate code from.
|
||||
|
||||
[[generated-files]]
|
||||
Generated Files
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
After the `PROTOBUF_GENERATE_CPP` function is called, you will have the above
|
||||
mentioned variables available. These will be marked as the output to a custom command
|
||||
which calls the protobuf compiler binary to generate them.
|
||||
|
||||
To then have the files generated you should add them to a library or executable.
|
||||
For example:
|
||||
|
||||
[source,cmake]
|
||||
----
|
||||
add_executable(protobuf_example
|
||||
main.cpp
|
||||
${PROTO_SRCS}
|
||||
${PROTO_HDRS})
|
||||
---
|
||||
|
||||
This will cause the protobuf compiler to be called when you call `make` on that
|
||||
executables target.
|
||||
|
||||
When changes are made to the .proto file, the associated source files will be
|
||||
autogenerated again. However, if no changes are made to the .proto file and you re-run
|
||||
make, then nothing will be done.
|
||||
|
||||
[[building-the-example]]
|
||||
Building the Example
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[source,bash]
|
||||
----
|
||||
$ mkdir build
|
||||
|
||||
$ cd build/
|
||||
|
||||
$ cmake ..
|
||||
-- The C compiler identification is GNU 4.8.4
|
||||
-- The CXX compiler identification is GNU 4.8.4
|
||||
-- Check for working C compiler: /usr/bin/cc
|
||||
-- Check for working C compiler: /usr/bin/cc -- works
|
||||
-- Detecting C compiler ABI info
|
||||
-- Detecting C compiler ABI info - done
|
||||
-- Check for working CXX compiler: /usr/bin/c++
|
||||
-- Check for working CXX compiler: /usr/bin/c++ -- works
|
||||
-- Detecting CXX compiler ABI info
|
||||
-- Detecting CXX compiler ABI info - done
|
||||
-- Looking for include file pthread.h
|
||||
-- Looking for include file pthread.h - found
|
||||
-- Looking for pthread_create
|
||||
-- Looking for pthread_create - not found
|
||||
-- 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
|
||||
-- Found PROTOBUF: /usr/lib/x86_64-linux-gnu/libprotobuf.so
|
||||
protobuf found
|
||||
PROTO_SRCS = /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/AddressBook.pb.cc
|
||||
PROTO_HDRS = /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/AddressBook.pb.h
|
||||
-- Configuring done
|
||||
-- Generating done
|
||||
-- Build files have been written to: /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build
|
||||
|
||||
$ ls
|
||||
CMakeCache.txt CMakeFiles cmake_install.cmake Makefile
|
||||
|
||||
$ make VERBOSE=1
|
||||
/usr/bin/cmake -H/home/matrim/workspace/cmake-examples/03-code-generation/protobuf -B/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build --check-build-system CMakeFiles/Makefile.cmake 0
|
||||
/usr/bin/cmake -E cmake_progress_start /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles/progress.marks
|
||||
make -f CMakeFiles/Makefile2 all
|
||||
make[1]: Entering directory `/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build'
|
||||
make -f CMakeFiles/protobuf_example.dir/build.make CMakeFiles/protobuf_example.dir/depend
|
||||
make[2]: Entering directory `/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build'
|
||||
/usr/bin/cmake -E cmake_progress_report /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles 1
|
||||
[ 33%] Running C++ protocol buffer compiler on AddressBook.proto
|
||||
/usr/bin/protoc --cpp_out /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build -I /home/matrim/workspace/cmake-examples/03-code-generation/protobuf /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/AddressBook.proto
|
||||
cd /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/matrim/workspace/cmake-examples/03-code-generation/protobuf /home/matrim/workspace/cmake-examples/03-code-generation/protobuf /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles/protobuf_example.dir/DependInfo.cmake --color=
|
||||
Dependee "/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles/protobuf_example.dir/DependInfo.cmake" is newer than depender "/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles/protobuf_example.dir/depend.internal".
|
||||
Dependee "/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles/protobuf_example.dir/depend.internal".
|
||||
Scanning dependencies of target protobuf_example
|
||||
make[2]: Leaving directory `/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build'
|
||||
make -f CMakeFiles/protobuf_example.dir/build.make CMakeFiles/protobuf_example.dir/build
|
||||
make[2]: Entering directory `/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build'
|
||||
/usr/bin/cmake -E cmake_progress_report /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles 2
|
||||
[ 66%] Building CXX object CMakeFiles/protobuf_example.dir/main.cpp.o
|
||||
/usr/bin/c++ -I/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build -o CMakeFiles/protobuf_example.dir/main.cpp.o -c /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/main.cpp
|
||||
/usr/bin/cmake -E cmake_progress_report /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles 3
|
||||
[100%] Building CXX object CMakeFiles/protobuf_example.dir/AddressBook.pb.cc.o
|
||||
/usr/bin/c++ -I/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build -o CMakeFiles/protobuf_example.dir/AddressBook.pb.cc.o -c /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/AddressBook.pb.cc
|
||||
Linking CXX executable protobuf_example
|
||||
/usr/bin/cmake -E cmake_link_script CMakeFiles/protobuf_example.dir/link.txt --verbose=1
|
||||
/usr/bin/c++ CMakeFiles/protobuf_example.dir/main.cpp.o CMakeFiles/protobuf_example.dir/AddressBook.pb.cc.o -o protobuf_example -rdynamic -lprotobuf -lpthread
|
||||
make[2]: Leaving directory `/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build'
|
||||
/usr/bin/cmake -E cmake_progress_report /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles 1 2 3
|
||||
[100%] Built target protobuf_example
|
||||
make[1]: Leaving directory `/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build'
|
||||
/usr/bin/cmake -E cmake_progress_start /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles 0
|
||||
$ make VERBOSE=1
|
||||
/usr/bin/cmake -H/home/matrim/workspace/cmake-examples/03-code-generation/protobuf -B/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build --check-build-system CMakeFiles/Makefile.cmake 0
|
||||
/usr/bin/cmake -E cmake_progress_start /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles/progress.marks
|
||||
make -f CMakeFiles/Makefile2 all
|
||||
make[1]: Entering directory `/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build'
|
||||
make -f CMakeFiles/protobuf_example.dir/build.make CMakeFiles/protobuf_example.dir/depend
|
||||
make[2]: Entering directory `/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build'
|
||||
/usr/bin/cmake -E cmake_progress_report /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles 1
|
||||
[ 33%] Running C++ protocol buffer compiler on AddressBook.proto
|
||||
/usr/bin/protoc --cpp_out /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build -I /home/matrim/workspace/cmake-examples/03-code-generation/protobuf /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/AddressBook.proto
|
||||
cd /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/matrim/workspace/cmake-examples/03-code-generation/protobuf /home/matrim/workspace/cmake-examples/03-code-generation/protobuf /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles/protobuf_example.dir/DependInfo.cmake --color=
|
||||
Dependee "/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles/protobuf_example.dir/DependInfo.cmake" is newer than depender "/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles/protobuf_example.dir/depend.internal".
|
||||
Dependee "/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles/protobuf_example.dir/depend.internal".
|
||||
Scanning dependencies of target protobuf_example
|
||||
make[2]: Leaving directory `/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build'
|
||||
make -f CMakeFiles/protobuf_example.dir/build.make CMakeFiles/protobuf_example.dir/build
|
||||
make[2]: Entering directory `/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build'
|
||||
/usr/bin/cmake -E cmake_progress_report /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles 2
|
||||
[ 66%] Building CXX object CMakeFiles/protobuf_example.dir/main.cpp.o
|
||||
/usr/bin/c++ -I/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build -o CMakeFiles/protobuf_example.dir/main.cpp.o -c /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/main.cpp
|
||||
/usr/bin/cmake -E cmake_progress_report /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles 3
|
||||
[100%] Building CXX object CMakeFiles/protobuf_example.dir/AddressBook.pb.cc.o
|
||||
/usr/bin/c++ -I/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build -o CMakeFiles/protobuf_example.dir/AddressBook.pb.cc.o -c /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/AddressBook.pb.cc
|
||||
Linking CXX executable protobuf_example
|
||||
/usr/bin/cmake -E cmake_link_script CMakeFiles/protobuf_example.dir/link.txt --verbose=1
|
||||
/usr/bin/c++ CMakeFiles/protobuf_example.dir/main.cpp.o CMakeFiles/protobuf_example.dir/AddressBook.pb.cc.o -o protobuf_example -rdynamic -lprotobuf -lpthread
|
||||
make[2]: Leaving directory `/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build'
|
||||
/usr/bin/cmake -E cmake_progress_report /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles 1 2 3
|
||||
[100%] Built target protobuf_example
|
||||
make[1]: Leaving directory `/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build'
|
||||
/usr/bin/cmake -E cmake_progress_start /home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles 0
|
||||
|
||||
$ ls
|
||||
AddressBook.pb.cc CMakeCache.txt cmake_install.cmake protobuf_example
|
||||
AddressBook.pb.h CMakeFiles Makefile
|
||||
|
||||
$ ./protobuf_example test.db
|
||||
test.db: File not found. Creating a new file.
|
||||
Enter person ID number: 11
|
||||
Enter name: John Doe
|
||||
Enter email address (blank for none): wolly@sheep.ie
|
||||
Enter a phone number (or leave blank to finish):
|
||||
|
||||
$ ls
|
||||
AddressBook.pb.cc CMakeCache.txt cmake_install.cmake protobuf_example
|
||||
AddressBook.pb.h CMakeFiles Makefile test.db
|
||||
----
|
||||
93
03-code-generation/protobuf/main.cpp
Normal file
93
03-code-generation/protobuf/main.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include "AddressBook.pb.h"
|
||||
using namespace std;
|
||||
|
||||
// This function fills in a Person message based on user input.
|
||||
void PromptForAddress(tutorial::Person* person) {
|
||||
cout << "Enter person ID number: ";
|
||||
int id;
|
||||
cin >> id;
|
||||
person->set_id(id);
|
||||
cin.ignore(256, '\n');
|
||||
|
||||
cout << "Enter name: ";
|
||||
getline(cin, *person->mutable_name());
|
||||
|
||||
cout << "Enter email address (blank for none): ";
|
||||
string email;
|
||||
getline(cin, email);
|
||||
if (!email.empty()) {
|
||||
person->set_email(email);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
cout << "Enter a phone number (or leave blank to finish): ";
|
||||
string number;
|
||||
getline(cin, number);
|
||||
if (number.empty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
tutorial::Person::PhoneNumber* phone_number = person->add_phone();
|
||||
phone_number->set_number(number);
|
||||
|
||||
cout << "Is this a mobile, home, or work phone? ";
|
||||
string type;
|
||||
getline(cin, type);
|
||||
if (type == "mobile") {
|
||||
phone_number->set_type(tutorial::Person::MOBILE);
|
||||
} else if (type == "home") {
|
||||
phone_number->set_type(tutorial::Person::HOME);
|
||||
} else if (type == "work") {
|
||||
phone_number->set_type(tutorial::Person::WORK);
|
||||
} else {
|
||||
cout << "Unknown phone type. Using default." << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Main function: Reads the entire address book from a file,
|
||||
// adds one person based on user input, then writes it back out to the same
|
||||
// file.
|
||||
int main(int argc, char* argv[]) {
|
||||
// Verify that the version of the library that we linked against is
|
||||
// compatible with the version of the headers we compiled against.
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
if (argc != 2) {
|
||||
cerr << "Usage: " << argv[0] << " ADDRESS_BOOK_FILE" << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
tutorial::AddressBook address_book;
|
||||
|
||||
{
|
||||
// Read the existing address book.
|
||||
fstream input(argv[1], ios::in | ios::binary);
|
||||
if (!input) {
|
||||
cout << argv[1] << ": File not found. Creating a new file." << endl;
|
||||
} else if (!address_book.ParseFromIstream(&input)) {
|
||||
cerr << "Failed to parse address book." << endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Add an address.
|
||||
PromptForAddress(address_book.add_person());
|
||||
|
||||
{
|
||||
// Write the new address book back to disk.
|
||||
fstream output(argv[1], ios::out | ios::trunc | ios::binary);
|
||||
if (!address_book.SerializeToOstream(&output)) {
|
||||
cerr << "Failed to write address book." << endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Optional: Delete all global objects allocated by libprotobuf.
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user