CentOS 5.8与gcc 4.4.7链接libstdc++ 6.0.8.这怎么可能
CentOS 5.8 with gcc 4.4.7 links against libstdc++ 6.0.8. How is it possible?
根据gcc ABI策略,gcc 4.4.7应该依赖于libstdc++ 6.0.13。据我所知,编译器版本和libstdc++版本是紧密相关的,不能互换,所以我惊讶地发现了以下事实:
- CentOS 5.8设法有一个gcc44包链接到6.0.8,显然是默认系统(基于gcc-4.1.2)
- 表示libstdc++。所以在编译器目录(/usr/lib/gcc/x86_64-redhat-linux6E/4.4.7,我期望找到libstdc++-6.0.13)不是链接到任何类型的共享对象,而是包含
INPUT ( -lstdc++_nonshared /usr/lib64/libstdc++.so.6 )
的文本文件
这里发生了什么魔法?
专:- 他们怎么能提供一个gcc 4.4.7来链接旧版本的libstdc++?我认为这是不可能的。 这个stdc++_nonshared库是什么?
- 我不知道。so文件可以包含这个文本。谁解析它(我猜是动态链接器),它的规范和结果是什么?
- 这魔法能走多远?我可以使用gcc4.7与libstdc++ 6.0.3?什么是兼容性谱
这里发生了什么魔法?
这主要是ELF符号版本控制的魔力。在这方面我看到的最好的参考是Ulrich Drepper的《如何编写共享库》,特别是第3节。
他们怎么能提供一个gcc 4.4.7来链接旧版本的libstdc++呢?我认为这是不可能的。
libstdc++开发人员非常注意ABI兼容性。这使得查看两个不同版本的libstdc++之间引入的新符号变得相当简单。
查看libstdc++的ABI兼容性页面,您可以看到GCC 4.1的libstdc++有GLIBCXX_3.4.8,而GCC 4.4的股票(FSF发行版)有GLIBCXX_3.4.13。然后可以查看libstdc++版本脚本,以查看在这两个版本之间添加了哪些符号。
查看符号版本的更经验性的方法是使用readelf这样的工具。例如,在我的Ubuntu系统上,readelf --dyn-syms --wide /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | c++filt
显示的输出是这样的(只是几个选定的短行):
223: 000000000006dbe0 2121 FUNC GLOBAL DEFAULT 12 std::ios_base::Init::Init()@@GLIBCXX_3.4
...
226: 00000000002ed920 1 OBJECT GLOBAL DEFAULT 27 std::adopt_lock@@GLIBCXX_3.4.11
注意符号名称后面的符号版本,在@@
后面。
stdc++_nonshared库是什么?
连接上一段的点,stdc++_nonshared是一个静态库,它包含了libstdc++.so.6.0.13中而不是libstdc++.so.6.0.8中的符号。
我不知道。so文件可以包含这个文本。谁解析它(我猜是动态链接器),它的规范和结果是什么?
常规链接器会解析这个,而不是运行时链接器。请参阅binutils文档中的链接器脚本中的INPUT。因此,链接到这个特殊的libstdc++.so.6.0.13将导致链接器动态链接到libstdc++.so.6.0.8,并静态链接到包含额外符号的库。
这样做的缺点是,与仅动态链接到包含所有必要符号的库存libstdc++.so.6.0.13的相同应用程序相比,以这种方式编译的应用程序会稍微臃肿一些。好处是新标准库的特性可以在旧系统的标准安装上使用,而不需要独立软件供应商提供他们自己的libstdc++副本。
这魔法能走多远?我可以使用gcc4.7与libstdc++ 6.0.3?兼容性的范围是什么
现在你知道了魔法是什么,也许你能理解这个版本的GCC 4.4是一个专门为Centos 5制作的特殊版本(好吧,最初是Red Hat 5)。所以也许你可以创建一个GCC 4.7,它只需要libstdc++ 6.0.3的二进制文件,但是它需要大量的工作来修补你的GCC树,把正确的符号放在stdc++ _nonshareda中。您至少可以查看gcc44 RPM的源代码,了解Red Hat在那里是如何做到的。
Red Hat似乎在他们的Red Hat Developer Toolset中延续了这种方法。在撰写本文时,GCC 4.8.1是最新的编译器,它可以为EL5构建二进制文件,这仍然只需要在目标系统上安装libstdc++.so.6.0.8。对于想要用c++ 11编写程序,但又需要能够部署在EL5或EL6上的开发人员来说,这是非常好的。
- 头文件可以在主类中运行.这怎么可能?
- 怎么可能只让设备使用 pjsua2 捕获或播放
- std::lock_guard 怎么可能比 std::mutex::lock() 更快?
- 怎么可能写 f( *this, std::forward<Args>(args)... ) 而 f 只用 F f 声明;
- 在QT C++编辑Qtable模型数据时,我需要得到一个小盒子,我需要显示编辑文本,这怎么可能?
- 在给定相同的输入的情况下,某些代码怎么可能花费更多时间来运行,这似乎只是因为它处于循环中?
- 答案怎么可能是433?
- 八进制文字怎么可能是负数?
- 我们可以在整数类型的双指针中分配2D整数数组的地址吗?怎么可能
- 我怎么可能从尚未定义某些成员方法的类创建实例?(C++)
- 使用 stl 迭代器封装向量是否很好?如果是?怎么可能呢?
- 几个比较怎么可能比一些计算慢
- 我的 Cuda 矢量怎么可能在填充后是空的
- 怎么可能有两个同名的变量——一个是全局变量,另一个是局部变量
- 奇怪的交叉播.这怎么可能
- 一个变量怎么可能既是constexpr又不是constexpr
- 如果方法私有,是否可以从 main 调用该方法?如果不是,怎么可能
- ANSI到Unicode或向后转换:怎么可能?
- std::unique_ptr怎么可能没有大小开销
- CentOS 5.8与gcc 4.4.7链接libstdc++ 6.0.8.这怎么可能