如何设置用于交叉编译的 C++ 工具链?

问题描述

我有一个目标系统 Astra Linux Smolensk,它可以访问非常过时的软件包,其中包括 GCC 6。它不支持 C++17,这是一些非常有用的 3rd 方库和语言功能所必需的。在某些时候,我正在考虑使用 20 个标准中的概念的可能性。但是没有简单的方法可以实现。
基本上,我看到了两种方式:

  1. 自己编译需要的 GCC 版本,并有一个自定义版本的 Astra Linux 用于构建附加包(这不是一个好的选择,因为我们对系统修改有限制)。我即将尝试此选项,但这不是本问题的主题
  2. 使用工具链在 Ubuntu 上与最新的 GCC 交叉编译。

那么,我需要什么才能为自定义版本的 Linux 创建工具链?我唯一确定的是 Linux Core 版本。我可以使用现有的 Linux 工具链还是必须导出系统库并创建自定义工具链?


Here 我发现了一些似乎有用的工具。例如:

buildroot
buildroot 是一个完整的构建系统,基于 Linux 内核配置系统,支持广泛的目标架构。它生成准备写入闪存的根文件系统映像。除了拥有大量可以编译到映像中的包之外,它还生成一个交叉工具链来从源代码构建这些包。即使您不想将 buildroot 用于根文件系统,它也是生成工具链的有用工具。 buildroot 支持 uClibc-ng、glibc 和 musl。

我想知道它是否满足我的需求,我可以使用带有这些生成的工具链的最新 GCC 编译器。


我发现了类似的问题:
How to build C++17 application in old linux distro with old stdlib and libc?
https://askubuntu.com/questions/162465/are-gcc-versions-tied-to-kernel-versions
How can I link to a specific glibc version?


需要澄清一下: 该项目严重依赖来自目标 linux 包存储库的许多 3rd 方依赖项。此外,我使用可以隐式和显式加载的动态 .so 模块。

解决方法

如今有了 docker 和基于容器的现代 CI/CD 管道,我们不像过去那样经常依赖进程编译。

在 musl 的帮助下,我们甚至可以创建具有静态链接的通用 Linux 二进制文件:我们使用所有静态库而不是动态库。然后我们发送一个可执行文件。

根据musl的doc,它需要

Linux 内核 >=2.6.39

这是一个在 2011 年左右发布的非常旧的版本,因此即使是旧的 Linux 发行版也可以运行我们的二进制文件。

Musl 在很多项目中被广泛使用,尤其是在 Rust 项目中,为了方便用户,我们为用户提供了 Musl 构建。

请注意,在使用 Musl 时我们可能需要修复我们的代码库,与 GNU libc 有非常细微的差异,我们应该注意这一点。