1

I'm building on Ubuntu 20.04 and my program executed on RedHat 8 just fine until I included <cmath> and used std::pow(double, double). Now I get the following error on RedHat 8:

/lib64/libm.so.6: version `GLIBC_2.29' not found (required by /MyOwnLib.so)

What is so special about std::pow that it requires GLIBC 2.29? This function is very old. Can I somehow force the compiler on Ubuntu to "link" an older version?

D.R.
  • 20,268
  • 21
  • 102
  • 205
  • Maybe ship your own libstdc++ with the application? This sometimes breaks things if the system has a newer version of it, so ideally you want a script that plugs it in only if the system version doesn't work. – HolyBlackCat Aug 29 '23 at 13:30
  • 1
    Gcc ABI is [forward compatible](https://stackoverflow.com/a/2802835/4165552), which means you can do the opposite: compile your program on RedHat8 and run it on Ubuntu. – pptaszni Aug 29 '23 at 13:35

3 Answers3

2

There's nothing special. There's surprising little coordination between gcc, glibc and the linker people, despite them all being "GNU". To tell gcc that pow is not new, you can use asm (".symver pow, pow@GLIBC_2.2.5");. This will tell gcc that pow was available since glibc version 2.2.5, so gcc won't tell the linker that glibc 2.29 is needed. pow has been around for way longer of course, but 2.2.5 introduced this versioning scheme.

The downside is that you miss out on the optimized version of pow from glibc 2.29, but that it intentional. That optimized version is missing from your RedHat 8 machine.

And just to be complete: this is pow from libm, which is the math part of glibc. It is not std::pow(double, double) from C++. That tells us that std::pow(double, double) is a thin inline wrapper for pow, as expected.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • nm -D libm.so.6 | fgrep "@@GLIBC" will give you the list of versioned math symbols. Note that the " .6" soname versioning is not used by glibc since they used started using their own versioning mechanism. – MSalters Aug 29 '23 at 14:43
  • Thanks, that's a great reply. Thank you. – D.R. Aug 29 '23 at 15:46
0

C++ is not ABI stable: when you build something on your machine it will work on your machine only. This is because the binary produced is specific to your architecture.

In this case it seems that there is a mismatch of the C standard library (libc).

If you want to don't depend from the system implementation of the standard C++ you can try to statically link to the standard library.

If you use gcc or clang try -static compiler option.

The solution to your problem would be compile your program to the target platform.

Elvis Dukaj
  • 7,142
  • 12
  • 43
  • 85
  • This first assumption is wrong, very wrong. I've written C++ code that has run on 50 million different machines. The binary produced was "specific" to the Win32 architecture. The real problem is that `glibc` and `stdlibc++` have no SDK against which you can build. Can't specify `-Lglibc=2.29`. – MSalters Aug 29 '23 at 14:10
  • An easy counter example: try to build using a very recent of C++ on Windows on an older version of Windows where the runtime is not that recent. That won't work! You should distribute also the vc runtime to be safe. – Elvis Dukaj Aug 30 '23 at 10:00
  • That's "not to be safe". You should *always* include the VC++ or G++ runtime , because neither is part of Windows. However, because both the VC++ and G++ runtimes are independent from the OS, you can link them statically. – MSalters Aug 31 '23 at 09:34
0

UPDATE: @MSalters answer is even better, switch to that.

A colleague of mine pointed out that I can use std::powf instead which is available in GLIBC 2.28 and does not require GLIBC 2.29. Not really a solution, but my solution, so I will mark it as accepted answer.

For somebody who can't do that look at the comment of @pptaszni to my original question: probably use an older Linux to compile on.

D.R.
  • 20,268
  • 21
  • 102
  • 205