|
转载自:
C++ ABI探究和兼容性问题
ABI(Application Binary Interface)
应用程序二进制接口,描述了应用程序和操作系统之间,一个应用和它的库之间,或者应用的组成部分之间的低接口。
编程语言实现的 ABI 是一种可以使单独编译的模块协同工作的低级细节的规范。如果没有一个稳定的 ABI,就必须使用同一编译器的同一版本编译程序的所有部分。
C ABI
Oracle Solaris ABI 也是 C ABI,因为 C 是标准的 UNIX 实现语言。此外,C ABI 还指定:
预定义类型(char、int、float 等)的大小和布局
复合类型(array 和 struct)的布局
编程人员定义的名称的外部(链接器可见)拼写
机器码函数调用序列
堆栈布局
寄存器使用
C++ ABI
C++ ABI 包括 C ABI,并进行了相应的扩展。
名称改编算法是 ABI 的一部分,因为它定义编译器必须如何生成程序实体的外部引用和定义。如果两个编译器或编译器版本未以相同方式对同等声明进行改编,则包含两个编译器编译的内容的程序将无法正确链接。
C++ 还提供了一种方法,用于指定可从 C 代码访问名称,因此不应改编名称。(个人理解是导出为C可用库的时候)
ABI的不稳定性
新的或更改的语言特性可能需要对 ABI 进行更改,而不仅仅是扩展。如C++03,11,14标准。
ABI 中的任何不同之处都意味着来自不同编译器的对象文件将无法链接,或者如果可以链接,它们也不会正确运行。C++ 编程人员已习惯于每当更新编译器时,就重新编译所有内容。
兼容性问题
库的厂商往往不希望使用者看到库的源代码,所以一般是以二进制的方式提供,这样的话当你的编译器型号和版本与编译库所用的编译器型号和版本不同时,就会产生不兼容。
查看已编译的库的版本
readelf -p .comment <lib-name>
objdump -s --section=.comment <lib-name>
1
2
库使用的编译器版本过低
例如:
收到一个库使用GCC 4.8 编译,而当前我们的编译器是GCC 7.4 或其他高版本。得到如下错误:
undefined reference to std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&&#39;
1
在编译时,加入-D_GLIBCXX_USE_CXX11_ABI=0宏定义即可解决。
库使用的编译器版本过低
例如:
我们收到了一些为Linux编译的库(.a)(可能是用GCC 6.x编译的)。
我们正在使用GCC 4.8,我们得到的类型错误:尝试链接时对std::__cxx11::basic_string的未定义引用。
通常,这可以通过确保所有单元都使用相同的_GLIBCXX_USE_CXX11_ABI标志进行编译来修复。
但是,如果我理解正确,这是由GCC 5.1引入的。
>有没有办法使这个工作与GCC 4.8或我们是否需要让人们用不同的_GLIBCXX_USE_CXX11_ABI重新编译库?
>我想如果我们能够切换到GCC> = 5.1,我们可以做到这一点吗?
使用高版本GCC
可以将C 11 ABI与gcc 4.8.2一起使用,但这是一个危险的做法;如果可能要求您的供应商提供使用C 03 ABI(-D_GLIBCXX_USE_CXX11_ABI = 0)编译的库或升级到GCC 5或更高版本,会是更好的做法。
使用GCC 4.8
您需要下载并安装gcc 5,以便您可以使用其libstdc头文件和库,然后直接使用gcc 4.8来使用它们自己的优先级。另外,因为gcc 4.8缺少gcc 5附带的libstdc所需的一些内在函数,所以你需要破解它们的用法。
例如,要编译包含< string>的简单单文件应用程序:
/usr/local/gcc-4.8.2/bin/g++ \
-std=c++11 \
-D_GLIBCXX_USE_CXX11_ABI=1 \
-D&#39;__is_trivially_copyable(...)=0&#39; \
-D&#39;__is_trivially_constructible(...)=0&#39; \
-D&#39;__is_trivially_assignable(...)=0&#39; \
-nostdinc++ \
-isystem /usr/local/gcc-5.4.0/include/c++/5.4.0/ \
-isystem /usr/local/gcc-5.4.0/include/c++/5.4.0/x86_64-unknown-linux-gnu \
-L /usr/local/gcc-5.4.0/lib64
a.cpp
1
2
3
4
5
6
7
8
9
10
11
这很危险,因为gcc 5.4 libstdc不适用于gcc 4.8,重新定义使用的内在函数(__is_trivially_copyable等)可能会改变结构的布局或导致程序与供应商库之间的二进制不兼容。
为了运行生成的可执行文件,您还需要确保动态链接器找到兼容的libstdc,例如将/usr/local/gcc-5.4.0/lib64添加到/etc/ld.so.conf,或者使用-Wl,-rpath /usr/local/gcc-5.4.0/lib64。
参考
https://stackoverflow.com/questions/45417707/glibcxx-use-cxx11-abi-gcc-4-8-and-abi-compatibility
技术资源 | Oracle 中国
————————————————
版权声明:本文为CSDN博主「灰蜗牛不会飞」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:C++ ABI探究和兼容性问题_灰蜗牛不会飞的博客-CSDN博客 |
|