如何将 GCC 约束到特定的运行时环境

how to constrain gcc to a certain runtime environment

提问人:MB. 提问时间:10/14/2023 最后编辑:MB. 更新时间:10/15/2023 访问量:59

问:

我们有一个 CI 管道,可以构建一堆项目。其中一个项目使用了高级 C++ 功能(C++20),因此我们将 gcc 版本升级到了 gcc-9。

但是,我们有一些目标嵌入式系统运行 debian buster,并且没有更高的 libc 版本。为 buster 映像构建的映像不依赖于 C++20,它们的 Makefile 专门指定 std=c++17。

所有这些项目以前都运行良好,但是现在我们收到如下错误:

./project: /usr/lib/arm-linux-gnueabihf/libstdc++.so.6: version `GLIBCXX_3.4.30' not found (required by ./project)
./project: /usr/lib/arm-linux-gnueabihf/libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by ./project)
./project: /usr/lib/arm-linux-gnueabihf/libstdc++.so.6: version `GLIBCXX_3.4.26' not found (required by ./project)

当我调查这些符号时,我发现 g++ “不必要地”链接到真正不应该(据我所知)需要更新版本的东西的新版本:

objdump -T project | egrep "GLIBC_2.3[2-6]"
00000000      DF *UND*  00000000  GLIBC_2.33  lstat
00000000      DF *UND*  00000000  GLIBC_2.34  pthread_once
00000000      DF *UND*  00000000  GLIBC_2.36  arc4random
00000000      DF *UND*  00000000  GLIBC_2.34  pthread_detach
00000000      DF *UND*  00000000  GLIBC_2.34  pthread_join
00000000      DF *UND*  00000000  GLIBC_2.34  pthread_setspecific
00000000  w   DF *UND*  00000000  GLIBC_2.34  __pthread_key_create
00000000      DF *UND*  00000000  GLIBC_2.33  fstat64
00000000      DO *UND*  00000000  GLIBC_2.32  __libc_single_threaded
00000000      DF *UND*  00000000  GLIBC_2.34  pthread_key_create
00000000      DF *UND*  00000000  GLIBC_2.34  pthread_key_delete
00000000      DF *UND*  00000000  GLIBC_2.34  pthread_getspecific
00000000      DF *UND*  00000000  GLIBC_2.34  pthread_create
00000000      DF *UND*  00000000  GLIBC_2.34  __libc_start_main

当然,我不需要在我的边缘设备上进行 buster->bookworm 升级,这样我就可以获得新的和改进的bad_array_thrower?!

有没有办法通知 gcc 不要轻率地使用较新的符号,除非它们实现新功能?

再说一遍:正在构建的项目不使用 c++20,它们在 gcc-8 上编译和运行良好。只是新的工具链使得无法在现场设备中构建。


编辑:很明显:我完全理解工具链不会混合和匹配。我只想能够在 buster 系统上使用 C++20 功能,而无需将其升级到 bullseye+(因为 gcc-8 是 buster 上可用的最高包)。

C GCC G++ libc

评论

0赞 Retired Ninja 10/14/2023
我将安装两个版本的 gcc,并使用与每个目标匹配的版本。
0赞 MB. 10/14/2023
不幸的是,gcc-8 和 gcc-10 之间似乎有一条密封线。前者不会安装在靶心上,后者不会安装在 buster 上。:|我真的开始认为我需要维护两个单独的构建映像,这是一个非常烦人的熵来源。
0赞 TrentP 10/14/2023
GCC、glibc 和 stdlibc++ 都是工具链的一部分。像 toolchains.bootlin.com 这样的东西将所有这些部分构建在一起以形成一个工具链。之后,您不一定能混合和匹配组件。您可以一次安装多个工具链。那里没有魔法。因此,请使用较旧的工具链,使二进制文件与 buster 兼容。甚至可以使用 crosstool 来制作 gcc 9 + 较旧的 glibc 工具链,这样您至少可以对 buster 兼容的二进制文件使用相同的 gcc 版本。
0赞 MB. 10/14/2023
所以你要确认的是:gcc 不允许在 buster 上有任何新的 C++20 功能 - 没有两种方法。即使该功能不依赖于任何新的 libc impl。

答:

1赞 Employed Russian 10/15/2023 #1

TL;DR:与 GLIBC 不同,在任何操作系统上使用较新版本都是微不足道的,Buster 不会阻止您使用 2.36 版本。libsdtdc++.so.6libstdc++.so.6

所以你要确认的是:gcc 不允许在 buster 上有任何新的 C++20 功能 - 没有两种方法。

完全不正确:您可以在 Buster 上使用已编译的二进制文件,但您必须为此类二进制文件提供适当的版本。gcc-10libstdc++

与 GLIBC 不同,将二进制文件指向替代文件是微不足道的——只需在目标系统上的某个位置复制工具链,并设置二进制文件,以便二进制文件在运行时使用备用文件。libstdc++.so.6libstdc++.so.6-rpathlibstdc++.so.6

事实上,2.36 版可能向后兼容,您可以将系统版本 () 替换为更新的版本,并且事情将继续工作。libstdc++.so.6/usr/lib/arm-linux-gnueabihf/libstdc++.so.6

评论

0赞 MB. 10/17/2023
这很有趣。我会试一试。这在某处有官方记录吗?喜欢一个既定的目标?那么 gcc 与奇怪的 libc 内容的链接呢?对此有何评论?