美文网首页
Linux环境下Clion整合Protobuf小结

Linux环境下Clion整合Protobuf小结

作者: chjxidian | 来源:发表于2020-08-25 22:30 被阅读0次

    一、安装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=<HOST_NAME> CC=<YOUR_COMPILER_PATH>/<COMPILER_GCC> CXX=<YOUR_COMPILER_PATH>/<COMPILER_G++> --disable-protoc --prefix=<TARGET_INSTALL_PATH>

    • 例如:
    # 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({PROTOBUF_INCLUDE_DIRS}) 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_SRCS}{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> <HDRS> [<ARGN>...])

    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> [<ARGN>...])

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

    6. C语言兼容

    # 执行指令:
    ./configure && make && make install
    # 或者执行指令:
    ./autogen.sh && ./configure && make && make install
    
    • 生成C文件和头文件
    protoc --c_out=. example.proto
    

    参考文献:


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

    相关文章

      网友评论

          本文标题:Linux环境下Clion整合Protobuf小结

          本文链接:https://www.haomeiwen.com/subject/kbltsktx.html