Protobuf 3.14.0 和 CMake 的一些小細節

·

1 min read

最近在試著用 CMake 去編一個的 Protobuf 3.14.0 的專案,在準備的過程遇到一些問題。

甚麼問題

一開始我是直接拿一個 repository 來改,對他追加版本 (當然,環境也有裝 protobuf 3.14.0 , CMAKE_PREFIX 等路徑環境變數也有設置好) ,確保 Cmake 連結的是 3.14.0 的版本後:

FIND_PACKAGE(Protobuf 3.14.0 REQUIRED)

便編譯成功了。

但是在執行時,卻直接跳出 Exception:

[libprotobuf FATAL google/protobuf/generated_message_util.cc:785] CHECK failed: (scc->visit_status.load(std::memory_order_relaxed)) == (SCCInfoBase::kRunning): terminate called after throwing an instance of ‘google::protobuf::FatalException’  
    what(): CHECK failed: (scc->visit_status.load(std::memory_order_relaxed)) == (SCCInfoBase::kRunning):   
Aborted

處理方式

根據一些 Google 和檢查 Cmake 的一些生成的檔案,這是因為沒有 link pthread 造成的。並且,追加

set(THREADS_PREFER_PTHREAD_FLAG ON)  
find_package(Threads REQUIRED)  
target_link_libraries(main Threads::Threads)

確實也可以解決問題,讓程式正常執行。

可是,這樣似乎又有點詭異,理論上來說 FindProtobuf 應該要負責也把連結 pthread 這個機制處理好,而不是交由使用者去另外連結 pthread。

最後,我找到這個 Issue,把這行

TARGET_LINK_LIBRARIES(main proto ${PROTOBUF_LIBRARY})

把它改成

TARGET_LINK_LIBRARIES(main proto ${PROTOBUF_LIBRARIES})

就好了。

官方文件上,其實對這兩個變數也只有模糊(幾乎沒有)的說明:

  • PROTOBUF_LIBRARIES — The protobuf libraries
  • PROTOBUF_LIBRARY — The protobuf library

或許就只是因為 library 是單數,所以是只有 protobuf 本身,而 libraries 是完整的把 protobuf 和他所需要的其他東西引入。

參考資料