CMake編譯遇到這種ABI不兼容問題不要慌

最近,在Linux下使用CMake編譯程序的時候遇到一個問題,特此做一個記錄。

事情是這樣的,我編譯的程序使用了2個第三方庫,在寫好CMakeLists後,啓動編譯,然後就報鏈接錯誤,一直報一堆找不到定義。

類似這樣的一堆:

‘***** std::__cxx11 *******’未定義的引用

我仔細檢查代碼和CMakeLists,各種修改嘗試無果。最後,在同事和搜索引擎的幫助下終於找到問題所在了。

問題出在我使用的GCC和第三方庫編譯的時候使用的GCC版本差異太大,兩者的ABI不兼容。

參考GCC提供的手冊<Dual ABI>,事情就清晰了。

在GCC5.1發佈的libstdc++中,添加了新的特性,其中包括了std::string和std::list的新實現。新的實現使得兩者都符合了C++11的標準。但是,爲了與現存代碼兼容,libstdc++保留了老的實現,與新實現並存。具體怎麼實現的呢?相比於老的實現,GCC5.1添加了__cxx11命名空間,在新的實現中的string和list,實際上是std::__cxx11::string和std::__cxx11::list。新舊ABI不兼容。

那麼,問題怎麼解決呢?

也很簡單,就是統一你的程序和第三方庫使用的實現版本。如果你有第三方庫源碼,那統一重新編譯下就行。如果第三方庫是已經編譯好的那也沒關係,GCC爲我們提供了一個選擇新舊實現的宏定義-D_GLIBCXX_USE_CXX11_ABI

-D_GLIBCXX_USE_CXX11_ABI=0 表示使用舊的實現
-D_GLIBCXX_USE_CXX11_ABI=1 表示使用新的實現

按需添加到CMakeLists中就可以了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章