最近遇到個問題,在鏈接OpenVINO的時候,需要將libinference_engine.so與libinference_engine_legacy.so都鏈接進去,但如果在CMakeLists里設置add_definitions(-D _GLIBCXX_USE_CXX11_ABI=0),就無法正常鏈接:編譯器只會鏈接libinference_engine_legacy.so,而沒有libinference_engine.so,當設置add_definitions(-D _GLIBCXX_USE_CXX11_ABI=1),就不會出現這樣的情況。並且后續會報出符號未定義的錯,如下所示。
my_lib.so: undefined reference to `InferenceEngine::Core::LoadNetwork(InferenceEngine::CNNNetwork, std::string const&, std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<std::string const, std::string> > > const&)' my_lib.so: undefined reference to `InferenceEngine::Data::getName() const' my_lib.so: undefined reference to `InferenceEngine::Core::Core(std::string const&)' my_lib.so: undefined reference to `InferenceEngine::details::InferenceEngineException::InferenceEngineException(std::string const&, int, std::string const&)' my_lib.so: undefined reference to `InferenceEngine::Core::ReadNetwork(std::string const&, std::string const&) const'
這就比較詭異了,必須好好看看這個_GLIBCXX_USE_CXX11_ABI有什么作用。
參考GCC提供的手冊<Dual ABI>,大概的意思就是說。
在GCC5.1發布的同時,為libstdc++添加了新的特性,其中也包括了std::string和std::list的新實現。這個新的實現使得兩者符合了c++11的標准,具體來說是取消了Copy-On-Write。那么,這樣子雖然符合了c++11的標注,舊版不就無法兼容了嗎。為了避免上述混亂,對於舊版而言,GCC5.1添加了__cxx11命名空間,GCC5.1或者說c++11規范下的string和list,實際上是std::__cxx11::string和std::__cxx11::list,所以我們一般的using namespace std就會變成形如using namespace std::__cxx11的樣子。也就是說,有舊版(c++03規范)的libstdc++.so,和新版(c++11規范)的libstdc++.so兩個庫同時存在。
為了避免兩個庫到底選擇哪一個的麻煩,GCC5.1就引入了-D_GLIBCXX_USE_CXX11_ABI來控制編譯器到底鏈接哪一個libstdc++.so,
-D_GLIBCXX_USE_CXX11_ABI=0 鏈接舊版庫
-D_GLIBCXX_USE_CXX11_ABI=1 鏈接新版庫
所以,回到OpenVINO的那個問題,提示符號未定義,我估計就是因為,OpenVINO這個第三方的庫libinference_engine.so,它是使用c++11規范的libstdc++.so,所以我在引用的時候,也必須使用相同規范的libstdc++.so,否則在這個第三方的內部,std::string就必須改成std::__cxx11::string才能使用_GLIBCXX_USE_CXX11_ABI=0。大概就是這樣子,又學習了呢。
原文鏈接:https://blog.csdn.net/github_28260175/article/details/105922130