Linux环境下Clion整合Protobuf小结

一、安装Protobuf环境

#安装依赖项目
sudo apt-get install autoconf automake libtool curl make g++ unzip
#下载最新源码
git clone https://github.com/google/protobuf.git
#进入目录
cd protobuf
#更新源
git submodule update --init --recursive
#生成依赖项目
./autogen.sh
#配置
./configure
#编译
make
#编译确认
make check
#安装
sudo make install
 # refresh shared library cache(刷新共享库配置)
sudo ldconfig
#查看版本
protoc --version

二、工程整合

1. 新建***.proto文件

proto文件
/*****PbTest.proto******/

syntax = "proto3";   //设定proto版本,不同版本语法不一样

package tutorial;

message Person {
  string name = 1;
  int32 id = 2;   //整型
  string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {  //定义类,也可以另起到外部message
    string number = 1;
    PhoneType type = 2;
  }

  repeated PhoneNumber phones = 4;  //关键字repeated代表不定长链表,对标list类
}

message AddressBook {
   Person people = 1;  //类嵌套
}

2. 开始转换

  • 进入proto文件所在目录执行:protoc --cpp_out=. PbTest.proto

语法: protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/XXXX.proto
案例: protoc --cpp_out=. XXXX.proto

  • 会在当前目录生成两个文件,如下图:
    生成***.cc和***.h文件

3. 文件加入工程

加入工程目录
  • 配置makelist文件:
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

...

include(FindProtobuf)
find_package(Protobuf REQUIRED)
include_directories(${PROTOBUF_INCLUDE_DIR})

target_link_libraries(
        ${PROTOBUF_LIBRARY}
)

4. 编译运行

  • 代码中引用:
    TuneParamsModel para;
    para.set_cad(5);

    /******************Stream***********************/
    // fstream out("out.txt", ios::out | ios::trunc);
    ofstream out("out.txt", ios::out | ios::trunc);
    para.SerializeToOstream(&out);
    out.close();
    TuneParamsModel ret;
    ifstream src ("out.txt", ios::in);
    ret.ParsePartialFromIstream(&src);
    src.close();
    /*******************Array***********************/
    size_t len =  para.ByteSizeLong();
    char buf[len];
    para.SerializeToArray( buf,len);

    TuneParamsModel ret;
    ifstream src ("out.txt");
    if (! src.is_open())
    { cout << "Error opening file"; exit (1); }
    while (! src.eof() ) {
        src.read (buf, len);
    }
    ret.ParseFromArray(buf, len);

    printf("Value Compare Result: %d", ret.cad() == para.cad());
    /*******************File***********************/
    TuneParamsModel _ret;
    ifstream _src ("protoBufferTest", ios::in);
    _ret.ParsePartialFromIstream(&_src);
    _src.close();
  • 编译并执行:
    enjoy it...

三、常见故障处理

1. 提示如下错误:

CMakeFiles/MedianMachine.dir/frame/MyProto.pb.cc.o: In function InitDefaultsscc_info_MyProto_MyProto_2eproto()': /media/chj/Code/MassHunter/MedianMachine/frame/MyProto.pb.cc:29: undefined reference togoogle::protobuf::internal::VerifyVersion(int, int, char const)'
CMakeFiles/MedianMachine.dir/frame/MyProto.pb.cc.o: In function InitDefaultsscc_info_MyType_MyProto_2eproto()': /media/chj/Code/MassHunter/MedianMachine/frame/MyProto.pb.cc:47: undefined reference togoogle::protobuf::internal::VerifyVersion(int, int, char const
)'
CMakeFiles/MedianMachine.dir/frame/MyProto.pb.cc.o: In function test::MyProto_MessageType_descriptor()': /media/chj/Code/MassHunter/MedianMachine/frame/MyProto.pb.cc:123: undefined reference togoogle::protobuf::internal::AssignDescriptors(google::protobuf::internal::DescriptorTable const, bool)'
CMakeFiles/MedianMachine.dir/frame/MyProto.pb.cc.o: In function test::MyType::_InternalParse(char const*, google::protobuf::internal::ParseContext*)': /media/chj/Code/MassHunter/MedianMachine/frame/MyProto.pb.cc:231: undefined reference togoogle::protobuf::internal::UnknownFieldParse(unsigned long, google::protobuf::UnknownFieldSet
, char const, google::protobuf::internal::ParseContext)'
CMakeFiles/MedianMachine.dir/frame/MyProto.pb.cc.o: In function `test::MyType::_InternalSerialize(unsigned char, google::protobuf::io::EpsCopyOutputStream) const':

...

CMakeFiles/MedianMachine.dir/frame/MyProto.pb.cc.o:(.data.rel.ro._ZTIN4test6MyTypeE[_ZTIN4test6MyTypeE]+0x10): undefined reference to `typeinfo for google::protobuf::Message'
collect2: error: ld returned 1 exit status
CMakeFiles/MedianMachine.dir/build.make:233: recipe for target 'MedianMachine' failed
make[3]: *** [MedianMachine] Error 1
CMakeFiles/Makefile2:75: recipe for target 'CMakeFiles/MedianMachine.dir/all' failed
make[2]: *** [CMakeFiles/MedianMachine.dir/all] Error 2
CMakeFiles/Makefile2:82: recipe for target 'CMakeFiles/MedianMachine.dir/rule' failed
make[1]: *** [CMakeFiles/MedianMachine.dir/rule] Error 2
Makefile:118: recipe for target 'MedianMachine' failed
make: *** [MedianMachine] Error 2

  • 原因分析:工程配置原因

  • 处理方法:编辑makelist文件,添加如下项目:

include(FindProtobuf)
find_package(Protobuf REQUIRED)
include_directories(${PROTOBUF_INCLUDE_DIR})

...

target_link_libraries(

...

    ${PROTOBUF_LIBRARY}
)

2. 定制化编译与安装

  • protobuf 默认安装在 /usr/local 目录

  • 你可以通过 ./configure --prefix=路径 指令修改安装目录

  • 为了避免安装乱象,可以安装在/usr/local/protobuf目录下

./configure --prefix=/usr/local/protobuf
make
make check
make install
  • 到此步还没有完成,在/etc/profile 或者用户目录 ~/.bash_profile 添加下面内容:
####### add protobuf lib path ########
#(动态库搜索路径) 程序加载运行期间查找动态链接库时指定除了系统默认路径之外的其他路径
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/
######################################
  • 如果出现找不到符号和链接错误请记得加上链接选项 -lprotobuf, 并确认你的静态库路径是否生效了 echo $LIBRARY_PATH`

3. 版本升级

  • 卸载之前版本:
sudo apt-get --purge remove libprotobuf-dev
sudo apt-get --purge remove protobuf-compiler
  • 重新编译安装新版本,步骤同《定制化编译与安装》

  • 期间如果出现:
    E: Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)

  • 原因:
    非正常停止apt-get install *

  • 解决方法:

sudo apt-get --fix-broken install

4.交叉编译

  • 编译定制化指令格式:

./configure --host= CC=/ CXX=/ --disable-protoc --prefix=

  • 例如:
# aarch64-linux-gnu平台
./configure --host=aarch64-linux-gnu CC=/usr/local/gcc-arm-x86_64-aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc CXX=/usr/local/gcc-arm-x86_64-aarch64-linux-gnu/bin/aarch64-linux-gnu-g++ --disable-protoc --prefix=/usr/local/protobuf-aarch64-linux-gnu
# arm-none-linux-gnueabihf 平台
./configure --host=arm-none-linux-gnueabihf CC=/usr/local/gcc-arm-x86_64-arm-none-linux-gnueabihf/bin/arm-none-linux-gnueabihf-gcc CXX=/usr/local/gcc-arm-x86_64-arm-none-linux-gnueabihf/bin/arm-none-linux-gnueabihf-g++ --disable-protoc --prefix=/usr/local/protobuf-arm-none-linux-gnueabihf
# 32位arm-linux-gnueabi平台
./configure --host=arm-linux-gnueabi CC=/usr/local/gcc-linaro-arm-linux-gnueabihf-4.7/bin/arm-linux-gnueabihf-gcc CXX=/usr/local/gcc-linaro-arm-linux-gnueabihf-4.7/bin/arm-linux-gnueabihf-g++ --disable-protoc --prefix=/usr/local/protobuf-arm-linux-gnueabi
  • 重复《定制化编译与安装》的步骤
  • 编辑工程 MakeList.txt 文件
#  host: arm-none-linux-gnueabihf 
# protobuf 路径配置
SET(PROTOBUF_FOUND                /usr/local/protobuf-arm-none-linux-gnueabihf/)
# protobuf 库路径配置
SET(PROTOBUF_LIBRARY              /usr/local/protobuf-arm-none-linux-gnueabihf/lib/libprotobuf.so)
# protobuf 头文件配置
SET(PROTOBUF_INCLUDE_DIR          /usr/local/protobuf-arm-none-linux-gnueabihf/include/)
# protobuf 执行文件配置
SET(PROTOBUF_PROTOC_EXECUTABLE    /usr/local/protobuf-arm-none-linux-gnueabihf/bin/protoc)

# host: aarch64-linux-gnu
SET(PROTOBUF_FOUND                /usr/local/protobuf-aarch64-linux-gnu/)
SET(PROTOBUF_LIBRARY              /usr/local/protobuf-aarch64-linux-gnu/lib/libprotobuf.so)
SET(PROTOBUF_INCLUDE_DIR          /usr/local/protobuf-aarch64-linux-gnu/include/)
SET(PROTOBUF_PROTOC_EXECUTABLE    /usr/local/protobuf-aarch64-linux-gnu/bin/protoc)

5. protobuf 系统帮助

  • 输入指令:
cmake --help-module FindProtobuf

Locate and configure the Google Protocol Buffers library.

The following variables can be set and are optional:

PROTOBUF_SRC_ROOT_FOLDER
When compiling with MSVC, if this cache variable is set
the protobuf-default VS project build locations
(vsprojects/Debug and vsprojects/Release
or vsprojects/x64/Debug and vsprojects/x64/Release)
will be searched for libraries and binaries.
PROTOBUF_IMPORT_DIRS
List of additional directories to be searched for
imported .proto files.

Defines the following variables:

PROTOBUF_FOUND
Found the Google Protocol Buffers library
(libprotobuf & header files)
PROTOBUF_INCLUDE_DIRS
Include directories for Google Protocol Buffers
PROTOBUF_LIBRARIES
The protobuf libraries
PROTOBUF_PROTOC_LIBRARIES
The protoc libraries
PROTOBUF_LITE_LIBRARIES
The protobuf-lite libraries

The following cache variables are also available to set or use:

PROTOBUF_LIBRARY
The protobuf library
PROTOBUF_PROTOC_LIBRARY
The protoc library
PROTOBUF_INCLUDE_DIR
The include directory for protocol buffers
PROTOBUF_PROTOC_EXECUTABLE
The protoc compiler
PROTOBUF_LIBRARY_DEBUG
The protobuf library (debug)
PROTOBUF_PROTOC_LIBRARY_DEBUG
The protoc library (debug)
PROTOBUF_LITE_LIBRARY
The protobuf lite library
PROTOBUF_LITE_LIBRARY_DEBUG
The protobuf lite library (debug)

Example:

find_package(Protobuf REQUIRED)
include_directories({CMAKE_CURRENT_BINARY_DIR})
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS foo.proto)
protobuf_generate_python(PROTO_PY foo.proto)
add_executable(bar bar.cc {PROTO_HDRS})
target_link_libraries(bar ${PROTOBUF_LIBRARIES})

.. note::
The protobuf_generate_cpp and protobuf_generate_python
functions and add_executable() or add_library()
calls only work properly within the same directory.

.. command:: protobuf_generate_cpp

Add custom commands to process .proto files to C++::

protobuf_generate_cpp ( [...])

SRCS
Variable to define with autogenerated source files
HDRS
Variable to define with autogenerated header files
ARGN
.proto files

.. command:: protobuf_generate_python

Add custom commands to process .proto files to Python::

protobuf_generate_python ( [...])

PY
Variable to define with autogenerated Python files
ARGN
.proto filess

6. C语言兼容

  • github下载源码: https://github.com/protobuf-c/protobuf-c
  • 编译:
# 执行指令:
./configure && make && make install
# 或者执行指令:
./autogen.sh && ./configure && make && make install
  • 生成C文件和头文件
protoc --c_out=. example.proto
  • 配置libprotobuf-c环境变量
    仿照前面CPP配置环境变量方法
  • 程序中引用:
    参考此案例: https://github.com/protobuf-c/protobuf-c/wiki/Examples

参考文献:


C语言使用Demo
MakeList文件故障处理
文件流处理
纯C语言实现方案
应用案例
交叉编译protobuf
入门手册
类型说明
参考手册
常用序列化函数
C语言使用案例
C语言源码仓库

你可能感兴趣的:(Linux环境下Clion整合Protobuf小结)