1 概述
当你的项目打算从低版本的GCC
(如GCC4
)升级后,你可能会遇到GCC undefined references with abi:cxx11
之类的问题,究其原因是GCC5.1
开始,STL
标准库中的std::string
和一些标准库被新的方法实现,但由于其std::basic_string
影响较大,因此很多库都会或多或少受影响。如果你需要使用的库恰好是GCC4
编译的,那么,除了使用新版本GCC
重新编译库之外,只能通过GLIBCXX_USE_CXX11_ABI
的方式解决了。
2 使用重新编译的方式解决
以源码方式使用新版本GCC重新编译动态库,并使用新的动态库,这种方式最优。
3 强制使用CXX11编译
我们可以在编译期指定GLIBCXX_USE_CXX11_ABI
宏,让编译器强制使用C++11所使用的接口。
3.1 CMAKE
对于CMAKE来说,我们需要在CMakeList.txt
添加:
add_compile_definitions(_GLIBCXX_USE_CXX11_ABI=0)
或者在调用cmake命令时传入:
cmake -DCMAKE_CXX_FLAGS='-D_GLIBCXX_USE_CXX11_ABI=0' path/to/your/project
3.2 Makefile
对于Makefile来说,我们同样也是在合适的地方添加宏,最终的效果是:
g++ $^ -std=c++14 -D_GLIBCXX_USE_CXX11_ABI=0 $(INCLUDE) $(LIB) -o $@
3.3 局限性
但是该方法只能说是权宜之计,因为其有一个很明显的局限性,如果你的程序同时使用了多个动态库,这些动态库如果都是使用GCC4编译的那没有什么问题,但如果这些动态库中存在有使用高版本编译的动态库时,则可能会出现新的问题。
2023/10/17 补充
检查符号是否正确
当使用一个动态链接库时,我们可能会发现明明成功引用但仍然报出
undefined reference
异常,这个时候就需要小心不同的GCC版本编译的符号名称是否一致的问题了。有效的解决方式是使用:
nm -D *.so | grep 符号
来确定符号的全称,然后将符号全称拷贝下来,使用
c++fit
命令解析,看和头文件是否一致。c++filt *
如果不一致那么可能就需要你针对实际情况进行解决了。