Protobuf 3.14.0 和 CMake 的一些小細節
最近在試著用 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 和他所需要的其他東西引入。
參考資料
- github repository: cmake-protobuf-example
- stackoverflow: FatalException thrown by protobuf library on instantiation of message
- stackoverflow: cmake and libpthread
- github issue: libprotobuf fatal error when running output file
- cmake document: FindProtobuf