总算弄好了,网上真的很少protobuf比较新的编译方法,在此记录一下。
用网上的方式去弄,一直都在报各种问题。百思不得其解,以下为个人成功经验总结:
前置工作准备:所有人的linux电脑环境都不一致,建议统一都安装一下以下工具:
sudo apt-get install autoconf
sudo apt-get install automake libtool curl
sudo apt-get install make g++
sudo apt-get install make unzip
方案一:下载最新版本编译(如有墙的原因导致无法正常下载,则参考方案二)
先在线下载源码
git clone https://github.com/protocolbuffers/protobuf.git
a.前提准备工作:git submodule update --init --recursive
b.确定你的起始路径为以下(如果没有则需要自己创建):XXX/protobuf/cmake/build/release
c.复制以下命令并在上述 release文件路径下粘贴,执行(这是一行,排版问题被拆了):
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../../../install/release -Dprotobuf_BUILD_SHARED_LIBS=ON -Dprotobuf_WITH_ZLIB=OFF -Dprotobuf_BUILD_TESTS=OFF ../../..
d.以下为成功编译后的效果图:
e.当前路径下执行
cmake -j8
等待十分钟左右
f.执行
make install
即可安装成功
今年4月测试成功,11月发现无法访问github,单位电脑不方便科学,因此更新了方案2
)==
- 以下我直说一种一定能成功的方法方案二,不对其他版本的错误做特殊说明。(原因是我们用的C语言protobuf-c环境,并且官方不咋更新这个了,只能找了一个曾经稳定的包来做编译。)
PART1 编译源码与验证
1.11 点击链接下载3.21.12版本源码。大概点击tags的第六页左右,有该文件,我会将源文件附件免费上传







1.12 cd protobuf-21.12/
1.13 ./autogen.sh
1.14 ./configure --prefix=/usr/local/protobuf
1.15 make
1.16 sudo make install
1.17 sudo vim /etc/profile
1.18 #添加以下内容:
#(动态库搜索路径) 程序加载运⾏期间查找动态链接库时指定除了系统默认路径之外的其他路径
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/protobuf/lib/
#(静态库搜索路径) 程序编译期间查找动态链接库时指定查找共享库的路径
export LIBRARY_PATH=$LIBRARY_PATH:/usr/local/protobuf/lib/
#执⾏程序搜索路径
export PATH=$PATH:/usr/local/protobuf/bin/
#c程序头⽂件搜索路径
export C_INCLUDE_PATH=$C_INCLUDE_PATH:/usr/local/protobuf/include/
#c++程序头⽂件搜索路径
export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/usr/local/protobuf/include/
#pkg-config 路径
export PKG_CONFIG_PATH=/usr/local/protobuf/lib/pkgconfig/
1.18 source /etc/profile
1.19 protoc --version
执行之后应该看到libprotoc 3.21.12如果出现这个版本信息则安装成功
PART2 撰写测试用例
参考链接:https://zhuanlan.zhihu.com/p/641283776
- 在本地新建一个文件:addressbook.proto并填充内容:
syntax = "proto2";
package tutorial;
message Person {
optional string name = 1;
optional int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
optional string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phones = 4;
}
message AddressBook {
repeated Person people = 1;
}
./usr/local/protobuf/bin/protoc --cpp_out=. addressbook.proto
(这个是绝对路径能保证你绝对不出错,如果你执行protoc --version
得到的不是libprotoc 3.21.12版本,才这样做。如果是,则直接protoc --cpp_out=. addressbook.proto
)
3.编写reader.cpp
#include <iostream>
#include <fstream>
#include <string>
#include "addressbook.pb.h"
using namespace std;
// Iterates though all people in the AddressBook and prints info about them.
void ListPeople(const tutorial::AddressBook& address_book) {
for (int i = 0; i < address_book.people_size(); i++) {
const tutorial::Person& person = address_book.people(i);
cout << "Person ID: " << person.id() << endl;
cout << " Name: " << person.name() << endl;
if (person.has_email()) {
cout << " E-mail address: " << person.email() << endl;
}
for (int j = 0; j < person.phones_size(); j++) {
const tutorial::Person::PhoneNumber& phone_number = person.phones(j);
switch (phone_number.type()) {
case tutorial::Person::MOBILE:
cout << " Mobile phone #: ";
break;
case tutorial::Person::HOME:
cout << " Home phone #: ";
break;
case tutorial::Person::WORK:
cout << " Work phone #: ";
break;
}
cout << phone_number.number() << endl;
}
}
}
// Main function: Reads the entire address book from a file and prints all
// the information inside.
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 (!address_book.ParseFromIstream(&input)) {
cerr << "Failed to parse address book." << endl;
return -1;
}
}
ListPeople(address_book);
// Optional: Delete all global objects allocated by libprotobuf.
google::protobuf::ShutdownProtobufLibrary();
return 0;
}
3.编写writer.cpp
#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_phones();
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_people());
{
// 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;
}
编译:
c++ -std=c++14 writer.cpp addressbook.pb.cc -o writer -lpthread -lprotobuf
c++ -std=c++14 reader.cpp addressbook.pb.cc -o reader -lpthread -lprotobuf
4.测试写出来的东西
测验完毕。
PART 3 拓展-protobuf-C的使用
参考链接吧,这个太简单了
https://blog.youkuaiyun.com/zb313982521/article/details/110341454
以下只介绍我用的源码版本及编译过程即可:
源码版本:https://github.com/protobuf-c/protobuf-c/releases/tag/v1.4.1
点击下面这个就会自动下载了,
注意,这个版本没有autogen文件,我是跟着readme自主编译的:
./configure && make && make install
编译完成自己学着readme做了个测试
make check
这个是敲完
source /etc/profile
后,查看版本信息的情况。
protobuf测试结果:
插曲:我执行student会报错但是去我的安装路径上去找,是找得到的,还不明白为什么,因此用了个手动引入环境变量来规避该问题:
规避后的成功执行效果:
插曲2:
2024年11月再次测试,一般来说装好之后的protoc默认安装路径为
/usr/local/bin
下,如果不会设置环境变量,可以把你的proto文件放在该/usr/local/bin路径下,并执行
protoc-c --c_out=. test.proto
即可得到类似以下的转化成C的proto文件自动代码。
本文章完毕