CMake基础第15节使⽤Protobuf⽣成源⽂件
介绍
这个例⼦展⽰了如何使⽤Protobuf⽣成源⽂件。Protocol Buffers是Google提供的⼀种数据序列化格式。⽤户提供带有数据描述的.proto⽂件。然后使⽤Protobuf编译器,可以将该原始⽂件翻译成包括C++在内的多种语⾔的源代码。
本教程中的⽂件如下:
$ tree
.
├── AddressBook.proto
├──
├── main.cpp
[AddressBook.proto] - 来⾃main protocol buffer⽰例的proto⽂件
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;
}
[] - 包含要运⾏的CMake命令
cmake_minimum_required(VERSION 3.5)
# 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")
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})
target_include_directories(protobuf_example
PUBLIC
${PROTOBUF_INCLUDE_DIRS}
${CMAKE_CURRENT_BINARY_DIR}
)
# link the exe against the libraries
target_link_libraries(protobuf_example
PUBLIC
${PROTOBUF_LIBRARIES}
)
[main.cpp] - protobuf⽰例的源⽂件.
#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 (!pty()) {
person->set_email(email);
}
while (true) {
cout << "Enter a phone number (or leave blank to finish): ";
string number;
getline(cin, number);
if (pty()) {
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") {
ubuntu使用入门教程
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;
}
要求
此⽰例需要安装protocol buffers⼆进制⽂件和库。可以使⽤以下命令将其安装在Ubuntu上。
sudo apt-get install protobuf-compiler libprotobuf-dev
概念
导出变量
由CMake Protobuf包导出并在此⽰例中使⽤的变量包括:
PROTOBUF_FOUND - 如果安装了Protocol Buffers
PROTOBUF_INCLUDE_DIRS - protobuf的头⽂件
PROTOBUF_LIBRARIES - protobuf库
此外,还可以通过查看ake⽂件顶部的内容到定义的更多变量。
⽣成源代码
Protobuf CMake包包含许多帮助函数,以简化代码⽣成。在本例中,我们⽣成的是C++源代码,使⽤以下代码:
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS AddressBook.proto)
这些参数包括:
PROTO_SRCS - 存储.pb.cc⽂件的变量名称
PROTO_HDRS- 存储.pb.h⽂件的变量名称
AddressBook.proto - 从中⽣成代码的.proto⽂件
⽣成⽂件
在调⽤PROTOBUF_GENERATE_CPP函数之后,你将拥有上⾯提到的变量。这些将被标记为⾃定义命令的输出,该命令将调⽤Protobuf编译器来⽣成它们。要⽣成这些⽂件,你应该将它们添加到库或可执⾏⽂件中。
例如:
add_executable(protobuf_example
main.cpp
${PROTO_SRCS}
${PROTO_HDRS})
这将导致在对该可执⾏⽂件⽬标调⽤make时调⽤protocol buf编译器。
对.proto⽂件进⾏更改后,将再次⾃动⽣成关联的源⽂件。但是,如果没有对.proto⽂件进⾏任何更改,并且你重新运⾏make,则不会执⾏任何操作。
构建⽰例
$ 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/
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
<  CMakeFiles  ake  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 ake 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/p 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/0 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 Dependee "/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles/protobuf_example.ake" is newer than depender "/home/matrim/workspace/cmake-examples/03-code-g Dependee "/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles/CMakeDi
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/ma /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/
/usr/bin/c++    -I/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build    -o CMakeFiles/protobuf_example.dir/ -c /home/matrim/workspace/cmake-examples/03-code-generation/pr Linking CXX executable protobuf_example
/usr/bin/cmake -E cmake_link_script CMakeFiles/protobuf_example. --verbose=1
/usr/bin/c++      CMakeFiles/protobuf_example.dir/main.cpp.o CMakeFiles/protobuf_example.dir/  -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 ake 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/p 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/0 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 Dependee "/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/CMakeFiles/protobuf_example.ake" is newer than depender "/home/matrim/workspace/cmake-examples/03-code-g Dependee "/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build/ake" is newer than depender "/
home/matrim/workspace/cmake-examples/03-code-genera 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/ma /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/
/usr/bin/c++    -I/home/matrim/workspace/cmake-examples/03-code-generation/protobuf/build    -o CMakeFiles/protobuf_example.dir/ -c /home/matrim/workspace/cmake-examples/03-code-generation/pr Linking CXX executable protobuf_example
/usr/bin/cmake -E cmake_link_script CMakeFiles/protobuf_example. --verbose=1
/usr/bin/c++      CMakeFiles/protobuf_example.dir/main.cpp.o CMakeFiles/protobuf_example.dir/  -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
    ake  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
    ake  protobuf_example
AddressBook.pb.h  CMakeFiles      Makefile            test.db

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。