使用带有新 glibc 和 binutils 的 GCC 为具有旧 sysroot 的系统构建软件

Using GCC with new glibc and binutils to build software for system with older sysroot

几个月以来我一直有一个问题,很长一段时间Google都无法得到答案。

背景: 我正在为基于 arm 的控制器交叉编译软件,这些控制器 运行ning linux 分布 ptxdist。完整的 linux 映像是使用针对 glibc-2.13 和 binutils-2.21 构建的交叉 gcc (4.5.2) 构建的。 c++ 标准很旧,所以我构建了一个支持 c++11 (gcc 4.8.5) 的新工具链。它现在是针对 glibc-2.20 和 binutils-2.24 构建的。我想在控制器上为我的应用程序软件使用那个新的编译器(不是完整的图像,只是这个 "main" 二进制文件),它通过包管理系统更新。

软件好像运行。我只需要为二进制文件设置 LD_LIBRARY_PATH 指向 libstdc++.so.0.19 而不是 libstdc++.so.14。不过,它不接受新的 libc,即 libc-2.20 而不是 libc-2.13。

所以二进制使用libstdc++.so.0.19,系统其余部分不变。

问题: 为什么这是有效的? 运行使用此软件可能会带来哪些风险,我是否应该这样做? 例如,二进制文件将来会错过 glibc-2.20 的某些功能,因为它只是在目标机器上获取 glibc-2.13 吗?无法针对 glibc-2.13 构建 gcc-4.8.5。

到目前为止我已经读到它取决于 ABI 内部的变化: Impact on upgrade gcc or binutils

这里说C代码如果从GCC4.1编译到GCC 4.8是兼容的。

谢谢!

glibc 2.14 引入了 memcpy@GLIBC_2.14 符号,因此几乎所有针对 glibc 2.20 编译的软件都无法在 glibc 2.13 上运行,因为那里缺少该符号。理想情况下,您将针对 glibc 2.13 而不是 glibc 2.20 构建新的 GCC。您声称无法针对 glibc 2.13 构建 GCC 4.8.5,但这显然不是一般情况。

一些较新的 C++ 功能将与旧系统 libstdc++ 一起使用,因为它们完全依赖于模板(来自头文件)和 libstdc++ 中新代码的 none。

您还可以研究混合链接模型在 Red Hat Developer Toolset 中的工作原理。它静态链接 libstdc++ 的较新部分,同时依赖于系统 libstdc++ 获取常见的较旧部分。这样,您就可以针对异常 等问题获得适当的互操作性,而无需在目标上安装更新的 libstdc++。

很好 material 可以在这里:

Multiple glibc libraries on a single host

Glibc vs GCC vs binutils compatibility

我最终的解决方案是这样的:

我构建了 GCC 4.8.5 作为交叉编译器。我无法使用较旧的 glibc2.13 构建它,只能使用 2.20 版。这可能是可能的,但在我的情况下它没有用。无论如何,这不是问题,因为我还使用 sysroot-flag 构建了它。编译新软件完全依赖于我的旧系统,包括C Runtime。我没有得到一个新的 C++ 标准,但如果你打开编译器优化,我会体验到更好的二进制压缩和性能。 关于新的 C++ 标准,我可以 link 一个更新的 libstdc++,它与我的交叉编译器一起使用 -l:libstdc++.so.6.0.19 作为 LDDFLAG。因此,除了旧的 libstdc++ 之外,我只需要在我的目标上复制一个额外的 libstdc++。 使用

查看新库使用的符号后

strings libstdc++.so.6.0.19 | grep GLIBC_

您可以观察到它不依赖于任何比 GLIBC_2.4 更新的符号。看起来我永远无法 运行 解决缺少符号的问题。 因此,就我而言,我很幸运地使用了新的 C++11 标准,而没有对系统的其余部分进行任何更改。如果引入了新的符号,您需要按照我的 post 中的上述 link 进行操作,这些内容非常有用。但我永远不会为自己尝试。在我的例子中,使用 GCC 4.9.4,libstdc++.so.6.0.20 得到指向 GLIBC_2.17 的符号。这可能会给我带来麻烦,因为我正在使用 GLIBC_2.13.

进行交叉编译