1. <i id="s6b2k"><small id="s6b2k"></small></i>
    <b id="s6b2k"><bdo id="s6b2k"></bdo></b>
  2. <wbr id="s6b2k"></wbr>

    Protobuf在Cmake中的正確使用方法詳解_其它綜合

    來源:腳本之家  責任編輯:小易  

    Protobuf是google開發的一個序列化和反序列化的協議庫,我們可以自己設計傳遞數據的格式,通過.proto文件定義我們的要傳遞的數據格式。例如,在深度學習中常用的ONNX交換模型就是使用.proto編寫的。我們可以通過多種前端(MNN、NCNN、TVM的前端)去讀取這個.onnx這個模型,但是首先你要安裝protobuf。

    在之前的博文中已經簡單介紹了onnx,其中onnx.proto就代表了onnx模型的基本數據結構。一般來說,protobuf經常搭配Cmake使用,Cmake有官方的modules,可以通過簡單的幾個命令protobuf_generate_cpp來生成對應的.pb.cc.pb.h

    簡單的例子:

    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_cpp(PROTO_srcS PROTO_HDRS EXPORT_MACRO DLL_EXPORT foo.proto)
    protobuf_generate_python(PROTO_PY foo.proto)
    add_executable(bar bar.cc ${PROTO_srcS} ${PROTO_HDRS})
    target_link_libraries(bar ${Protobuf_LIBRARIES})

    但是這個例子太簡單了,如果我們的.proto文件只有一個或者說都只在一個目錄里,那用這個命令沒什么毛病...

    但如果是這種情況,我們的文件目錄如下:

    ├── CMakeLists.txt
    ├── README.md
    ├── meta
    │  └── proto
    │    ├── CMakeLists.txt
    │    └── common
    │      ├── bar
    │      │  ├── CMakeLists.txt
    │      │  └── bar.proto
    │      └── foo
    │        ├── CMakeLists.txt
    │        └── foo.proto
    └── src
      ├── CMakeLists.txt
      ├── c_proto.cc
      └── c_proto.hh

    其中foo.proto文件如下:

    message foo_msg 
    {
     optional string name = 1;
    }

    bar.proto的文件如下:

    import "common/foo/foo.proto";
     
    message bar_msg 
    {
     optional foo_msg foo = 1;
     optional string name = 2;
    }

    如上,bar文件引用foo,而且這兩個不在一個目錄,如果直接使用protobuf_generate_cpp來生成,直接會報錯。(這個例子取自Yu的一篇博文

    也想過把他倆放到同一個目錄...然后bar.proto中import的代碼就要修改,雖然這樣可以,但顯然是不適合大型的項目。

    而這個大型項目顯然就是mediapipe...折磨了我好久。

    關于mediapipe的詳細介紹在另一篇文章。mediapipe中使用了大量的ProtoBuf技術來表示圖結構,而且mediapipe原生并不是采用cmake來構建項目,而是使用google自家研發的bazel,這個項目構建系統我就不評價了,而現在我需要使用Cmake來對其進行構建。

    這也是噩夢的開始,mediapipe的.proto文件很多,核心的framework的目錄下存在很多的.proto文件,根目錄和子目錄都有.proto文件:

    而且每個proto文件之間存在引用的順序,framework根目錄下的calculator.proto文件:

    // mediapipe/framework/calculator.proto
    syntax = "proto3";
    
    package mediapipe;
    
    import public "mediapipe/framework/calculator_options.proto";
    
    import "google/protobuf/any.proto";
    import "mediapipe/framework/mediapipe_options.proto";
    import "mediapipe/framework/packet_factory.proto";
    import "mediapipe/framework/packet_generator.proto";
    import "mediapipe/framework/status_handler.proto";
    import "mediapipe/framework/stream_handler.proto";

    每個.proto文件都import了其他目錄下的文件,這里的import類似于C++中的include,但是這里的import又可以相互引用,例如上述的status_handler.proto也引用了mediapipe_options.proto

    如果直接對上述所有的.proto文件直接使用protobuf_generate_cpp命令,會直接報錯,因為這些文件不在一個目錄,而且import的相對目錄也無法分析。另外,不同目錄內的.cc文件會引用相應目錄生成的.pb.h文件,我們需要生成的.pb.cc.pb.h在原始的目錄中,這樣才可以正常引用,要不然需要修改其他源代碼的include地址,比較麻煩。

    CLion中Cmake來編譯proto生成的.pb.cc.pb.h不在原始目錄,而是集中在cmake-build-debug(release)中,我們額外需要將其中生成的.pb.cc.pb.h文件移動到原始地址(Clion的情況是這樣)。

    正確修改cmake

    對于這種情況,比較合適的做法是直接使用命令進行生成。

    首先找到所有需要編譯的.proto文件:

    file(GLOB protobuf_files
        mediapipe/framework/*.proto
        mediapipe/framework/tool/*.proto
        mediapipe/framework/deps/*.proto
        mediapipe/framework/testdata/*.proto
        mediapipe/framework/formats/*.proto
        mediapipe/framework/formats/annotation/*.proto
        mediapipe/framework/formats/motion/*.proto
        mediapipe/framework/formats/object_detection/*.proto
        mediapipe/framework/stream_handler/*.proto
        mediapipe/util/*.proto
        mediapipe/calculators/internal/*.proto
        )

    接下來,定義相關的目錄地址,PROTO_META_BASE_DIR為編譯之后生成文件的目錄。PROTO_FLAGS很重要,指定編譯.proto文件時的總的尋找路徑,.proto中的import命令根據根據這個地址去連接其他的.proto文件:

    SET(PROTO_META_BASE_DIR ${CMAKE_CURRENT_BINARY_DIR})
    LIST(APPEND PROTO_FLAGS -I${CMAKE_CURRENT_SOURCE_DIR})

    設置好之后,通過FOREACH去循環之前的.proto文件,依次編譯每個文件,然后將生成的.pb.cc.pb.h移動回原始的目錄,至此就可以正常工作了。

    FOREACH(FIL ${protobuf_files})
    
      GET_FILENAME_COMPONENT(FIL_WE ${FIL} NAME_WE)
    
      string(REGEX REPLACE ".+/(.+)\\..*" "\\1" FILE_NAME ${FIL})
      string(REGEX REPLACE "(.+)\\${FILE_NAME}.*" "\\1" FILE_PATH ${FIL})
    
      string(REGEX MATCH "(/mediapipe/framework.*|/mediapipe/util.*|/mediapipe/calculators/internal/)" OUT_PATH ${FILE_PATH})
    
      set(PROTO_srcS "${CMAKE_CURRENT_BINARY_DIR}${OUT_PATH}${FIL_WE}.pb.cc")
      set(PROTO_HDRS "${CMAKE_CURRENT_BINARY_DIR}${OUT_PATH}${FIL_WE}.pb.h")
    
      EXECUTE_PROCESS(
          COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} ${PROTO_FLAGS} --cpp_out=${PROTO_META_BASE_DIR} ${FIL}
      )
      message("Copying " ${PROTO_srcS} " to " ${FILE_PATH})
    
      file(COPY ${PROTO_srcS} DESTINATION ${FILE_PATH})
      file(COPY ${PROTO_HDRS} DESTINATION ${FILE_PATH})
    
    ENDFOREACH()

    參考鏈接

    http://blog.argcv.com/articles/3884.c
    https://www.v2ex.com/t/602363
    https://stackoverflow.com/questions/29720410/no-member-found-when-use-cmake-construct-proto/29817843

    到此這篇關于Protobuf在Cmake中的正確使用方法的文章就介紹到這了,更多相關Protobuf使用Cmake內容請搜索真格學網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持真格學網!

    您可能感興趣的文章:Protobuf的簡要介紹及使用詳解詳解Google Protobuf簡明教程

  3. 本文相關:
  4. postman使用詳解
  5. 有關微信的小程序和小游戲的區別
  6. intellij idea2020永久破解,親測可用!!!
  7. ai經典書單 人工智能入門該讀哪些書?
  8. vim中tagbar配置以及打字時隱藏鼠標的方法
  9. 超好用:免費的圖床
  10. deepin20安裝開發環境的超詳細教程
  11. appium的使用與入門(這款神器你值得擁有)
  12. 基于laravel + vue + element 實現 人力資源系統(考勤應用 )
  13. 做一個優秀程序員應該知道的15件事
  14. cmake怎么編譯protobuf
  15. 怎么在抓包工具中使用protobuf 插件
  16. 怎么在c#中使用protobuf3
  17. 如何在Go中使用Protobuf
  18. 如何在CentOS6.5下編譯64位的Hadoop2.x
  19. cmake 編譯得到的文件在哪
  20. 如何在xcode中使用protobuf
  21. 手機鋰電池的正確使用方法
  22. 如何在unity中使用protobuf工具生成cs類
  23. 如何在Linux環境下在CodeBlock中安裝使用Google Pr...
  24. 網站首頁網頁制作腳本下載服務器操作系統網站運營平面設計媒體動畫電腦基礎硬件教程網絡安全javascriptasp.netphp編程ajax相關正則表達式asp編程jsp編程編程10000問css/htmlflex腳本加解密web2.0xml/rss網頁編輯器相關技巧安全相關網頁播放器其它綜合dart首頁其它綜合protobuf的簡要介紹及使用詳解詳解google protobuf簡明教程postman使用詳解有關微信的小程序和小游戲的區別intellij idea2020永久破解,親測可用!!!ai經典書單 人工智能入門該讀哪些書?vim中tagbar配置以及打字時隱藏鼠標的方法超好用:免費的圖床deepin20安裝開發環境的超詳細教程appium的使用與入門(這款神器你值得擁有)基于laravel + vue + element 實現 人力資源系統(考勤應用 )做一個優秀程序員應該知道的15件事最新idea2021注冊碼永久激活(激活intellij idea2020永久破解,親測idea激活碼最新獲取方法(idea20最新idea2020激活碼超詳細教程(設刪除svn三種方法delsvn(windows+最新intellij idea 2020.2永久激關于最新idea2020.2.1,2.2,3以上intellij idea 2020最新注冊碼(親c/s和b/s兩種架構的概念、區別和qqwry.dat的數據結構圖文解釋微信小程序(微信應用號)開發工具0.9版安裝整理的比較全的一句話后門代碼(方面大家查比較經典技術普及帖 以你剛才在淘寶上買了jetpack開發中使用camerax完成拍照和拍視最新webstorm2020.2注冊碼永久激活(激活到webstorm 11.0.4安裝圖文教程編程知識點(1)關鍵詞之存儲類型詳解ansible批量管理服務
    免責聲明 - 關于我們 - 聯系我們 - 廣告聯系 - 友情鏈接 - 幫助中心 - 頻道導航
    Copyright © 2017 www.yu113.com All Rights Reserved
    战天txt全集下载