0

We have a CI pipeline that builds a bunch of projects. One of the projects uses advanced C++ features (C++20) and so we've upgraded our gcc version to gcc-9.

However, we have some target embedded systems that run debian buster and do not have the later libc versions. The images that are being built for the buster image do not rely on C++20 and their Makefiles specifically specify std=c++17.

All of these projects worked fine as-is before, however now we are getting errors like this:

./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)

When I investigate these symbols, I find that g++ is "unnecessarily" linking to newew versions of things that really shouldn't (as far as I can tell) require newer version:

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

Surely, I don't need to do a buster->bookworm upgrade on my edge devices so that I can get a new and improved bad_array_thrower?!

Is there a way to inform gcc to not frivolously make use of newer symbols unless they implement new features?

Once again: the projects that are being built do not use c++20 and they compile and run fine on gcc-8. It's just the new toolchain that makes it impossible to build for in the field devices.


Edit: Just so it's clear: I fully understand that toolchains do not mix and match. I would just like to be able to use C++20 features on a buster system without upgrading it to bullseye+ (because gcc-8 is the highest available package on buster).

4
  • I'd have both versions of gcc installed and use the version that matches each target. Commented Oct 13, 2023 at 20:09
  • Unfortunately, there seems to be a hermetic line between gcc-8 and gcc-10. The former won't install on bullseye, and the latter won't install on buster. :| I'm really starting to think I need to maintain two separate build images, which is such an annoying source of entropy. Commented Oct 13, 2023 at 20:10
  • gcc, glibc, and stdlibc++ are all part of the toolchain. Something like toolchains.bootlin.com builds all these parts together to make a toolchain. You can't necessarily mix and match the components afterward. You can install multiple toolchains at once. There's no magic there. So get an older toolchain that makes binaries compatible with buster. It might even be possible to get crosstool to make you a gcc 9 + older glibc toolchain so you can at least use the same gcc version for your buster compatible binaries. Commented Oct 13, 2023 at 20:42
  • So what you're confirming is: gcc doesn't allow for any new C++20 feature on buster - no two ways about it. Even if the feature doesn't rely on any new libc impl. Commented Oct 14, 2023 at 1:13

1 Answer 1

1

TL;DR: unlike with GLIBC, it is trivial to use newer version of libsdtdc++.so.6 on any OS, and Buster doesn't prevent you from using libstdc++.so.6 version 2.36.

So what you're confirming is: gcc doesn't allow for any new C++20 feature on buster - no two ways about it.

That is not at all correct: you can use gcc-10 compiled binaries on Buster, but you must provide an appropriate version of libstdc++ for such binaries.

Unlike with GLIBC, pointing binaries to an alternate libstdc++.so.6 is trivial -- just make a copy of toolchain's libstdc++.so.6 somewhere on the target system, and set -rpath so the binary uses the alternate libstdc++.so.6 at runtime.

Indeed libstdc++.so.6 version 2.36 might be backwards compatible enough that you could replace the system version (/usr/lib/arm-linux-gnueabihf/libstdc++.so.6) with the updated one, and things will continue working.

Sign up to request clarification or add additional context in comments.

1 Comment

That's interesting. I will give that a try. Is this officially documented somewhere? Like a stated goal? And what about gcc's links to weird libc stuff? Any comment on that?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.