_GLIBCXX_USE_CXX11_ABI
有什么作用
最近遇到个问题,在链接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
。大概就是这样子,又学习了呢。