使用比平台提供的更新版本的 GCC 需要啥

Posted

技术标签:

【中文标题】使用比平台提供的更新版本的 GCC 需要啥【英文标题】:What is needed to use a newer version of GCC than the platform provides使用比平台提供的更新版本的 GCC 需要什么 【发布时间】:2015-09-14 12:07:36 【问题描述】:

我正在考虑使用比我需要支持的某些平台 (GCC 4.1) 提供的更新版本的 GCC(例如 5.2)的潜力,因为我希望至少具有 C++11 功能,甚至可能是一些 C++14 的东西。我只是提供一个可执行程序,而不是我希望平台用户能够链接的静态或共享库。

我能够编译 GCC 5.2 和 Boost 1.59(我目前使用的唯一一个带有 C++ API 的库)并让它与那些放置在可执行文件旁边的 so 一起工作,并在测试系统上将 $ORIGIN 添加到 RPATH有 4.4。

但我不清楚我还需要什么才能完全做到这一点并确保一切正确/安全。例如我注意到 libc、libm、libpthread 等不是 GCC 构建的一部分,它仍然使用系统版本,与许多其他第三方库(例如 zlib、libpng 等)一样。我是否需要重建和分发所有这些以确保安全?他们是一套标准的规则吗?

还想知道我是否应该静态链接一些东西以及规则是什么?例如仅使用“-static”会失败,因为它会寻找我在该系统上没有的静态 pthread(并且我假设其他系统提供的库)。理想情况下,我希望减小包裹的大小。

【问题讨论】:

【参考方案1】:

但我不清楚我还需要什么才能完全做到这一点并确保一切正确/安全。例如我注意到 libc、libm、libpthread 等不是 GCC 构建的一部分,它仍然使用系统版本,与许多其他第三方库(例如 zlib、libpng 等)一样。我是否需要重建和分发所有这些以确保安全?他们是一套标准的规则吗?

在您的可执行文件和共享库上运行ldd 以确保它从正确的位置加载libstdc++libgcc_s(如果您动态链接它们)。这是运行使用 g++ 构建的应用程序通常所需的仅有的两个依赖项。

通常,您不需要提供您自己的带有C 接口的库版本,除非您的应用程序需要具有不兼容 API 的较新版本。

【讨论】:

它只是重要的接口并且几乎回答了“你需要重新编译和分发 libx 吗?”问题?我担心的是,理论上这样的库可能在内部使用 C++,针对其他一些 GCC 和 libstdc++ 版本进行编译,然后会发生什么? @FireLancer 这本身就是另一个问题。如果您碰巧链接到第 3 方 C++ 仅二进制库,则需要确保您的应用程序和第 3 方库对库接口中存在的类型使用相同的 C++ ABI。见gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html 对不起,也许我不清楚或混淆了自己。我不是指外部 C++ 的库,比如 boost,我知道它们通常需要与编译器匹配。但是,如果具有 C 接口的库在内部使用 C++ 会怎样?如果我对发行版使用不同的 GCC,我是否需要仔细检查、重建和打包它们?例如理论上可以使用 C++ 编写类似于 zlib 的库。 @FireLancer 如果这些第 3 方库链接到系统 libstdc++libgcc_s 您可能会使用自己的版本,我需要阅读 stdlibc++ 符号版本控制和二进制兼容性。但是,这些 3rd 方库也可能依赖于较旧的系统版本的 boost 库,但 boost 不会在版本之间保持稳定的 ABI。在这种情况下,您可以尝试将第 3 方库加载到单独的链接器命名空间中,但这太棘手太快了。 @FireLancer 我现在记得,我用 gcc-4.9 和 C++11 使用 boost::python 构建了我的 python 模块。我的模块在 python 脚本中运行良好,但无法在ipython 下加载。结果 ipython 使用系统 zeromq C++ 库,该库在 ipython 启动时加载,并在系统 libstdc++ 中拉入。当我的 python/C++ 模块被加载时,libstdc++ 已经存在,但它没有提供我的模块预期的符号并且加载会失败。这通过将LD_LIBRARY_PATH 设置为我的libstdc++ 版本来解决ipython 和zeromq 似乎很高兴使用我的libstdc++【参考方案2】:

最近的GCC 编译器有很多依赖。

在某些发行版上,您可以要求它们:在 Debian 或相关发行版上,您可能会使用 aptitude build-dep gcc(如果您的 /etc/apt/sources.list 中有 deb-src:),它将下载系统 gcc 的构建依赖项(这可能与最新的GCC有很多共同的依赖关系。

否则,GCC 源代码包含一个 contrib/download_prerequisites 脚本,应该很方便。

仔细阅读 GCC building procedure。不要忘记在源代码树的外部编译它。您可能希望将--program-suffix=-5-mine 传递给它的configure

当然,您还需要使用新构建的 GCC 构建编译(或交叉编译)代码所需的所有其他软件,包括 binutils、gdb,也许还有一个 C 库

或者使用chroot(或一些容器à la docker)来安装更新的Linux系统...

【讨论】:

我猜投反对票是因为您回答了与所问问题不同的问题。我将问题读作“我是否需要用我的 gcc 重新编译 libc 等并将它们与应用程序一起分发。 好吧,我已经按照他们的指示构建了 GCC,但这并不是唯一的依赖关系,并且如果我不继续重建整个系统(如果我可以我可以/只使用较新的发行版,但客户希望继续使用他们当前的 Linux 发行版)【参考方案3】:

我注意到 libc、libm、libpthread 等不是 GCC 构建的一部分,它仍然使用系统版本,与许多其他第三方库(例如 zlib、libpng 等)一样。我是否需要重建和分发所有这些以确保安全?

没有。如果您在要部署到的系统上构建 GCC,那么 GCC 二进制文件和共享库将取决于 libc、libpthread 等的系统版本。

如果您随后使用该 GCC 编译您的软件,并将新的 libstc++.so.6 与您的软件一起部署(使用 $ORIGIN 以便找到它),那么它仍将使用这些库的系统版本。这正是应该发生的事情以及您想要发生的事情。重建它们将一事无成,只是意味着您有更多的库要与您的软件一起部署。

【讨论】:

【参考方案4】:

按照说明从源代码构建。如果您遇到问题,请修改您的问题。

【讨论】:

就像我说的,我已经成功地从源代码构建了 GCC,但是这样做并不会自然地包含系统上的每个库,所以不确定这是否是获得我可以安全部署的包的全部要求.例如对于 boost 当然不是,来自平台存储库的 boost 共享对象甚至不会链接。 C 库不需要重新构建,除非 ABI 已更改。如果名称修改约定或 ABI 更改,则必须重新构建 C++ 库。再次尝试并报告实际问题。推测潜在的问题是没有成效的。【参考方案5】:

我认为有一种比自己编译 GCC 更简单的方法。 [不幸的是,我在多次从源代码编译后发现了这一点:) ]

例如,在 Ubuntu 中,官方存储库中还没有预编译 GCC 版本的 PPA。

sudo add-apt-repository ppa:ubuntu-toolchain-r/test

sudo apt-get update

sudo apt-get install gcc-5 g++-5
sudo update-alternatives 
sudo update-alternatives --remove-all gcc
sudo update-alternatives --remove-all g++
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 20
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-5 20
sudo update-alternatives --config gcc
sudo update-alternatives --config g++

【讨论】:

以上是关于使用比平台提供的更新版本的 GCC 需要啥的主要内容,如果未能解决你的问题,请参考以下文章

iOS 应用更新 - 将新版本限制为单一平台

gcc新版本号引起的编译错误(命令运行时的外部库输入位置)

检查新版本(更新检查)

安卓手机app如何旧版本覆盖新版本,不用卸载且不删数据?

gcc centos 新版本的安装方法

服务器安装新版本R及Seurat方法