This is probably the longest thread about the topic, I'll add also my two cents. Please, correct me for everything I did wrong.
There's a program readelf and anyone can list any versioned glibc symbols in executables, so, o, a files with the following command
readelf -Ws {file} | grep GLIBC
you will see the lines ending with something like ".... pthread_mutex_destroy@GLIBC_2.2.5 (2)"
GLIBC_2.2.5 из the version (set) (abi) that was chosen by the linker, the number in parenthesis is the version of this symbol. So @GLIBC_2.8 (2) will mean that the later abi list was chosen (2.8) but actual version of the symbol is the same
The compiler (fpc in our case) don't use such versioned symbols, it's the linker who sees pthread_mutex_destroy and having glibc on this system with particular latest abi, chooses the @ ending.
We in pascal have already a feature to limit this. So if you declare the imported function like
pthread_mutex_destroy... external clib name 'pthread_mutex_destroy@GLIBC_2.2.5'
the linker will be content to follow. Only the abi set like here (2.2.5) should exist in the glibc version in the system.
Also note that if experimenting with linking particular versions there are some states when the symbol with invalid name might exist in compiled units, but linker doesn't care (for example with the declaration is implementation-only and not used inside the implementation section)
In classic c as long as I remember there's no syntax to use a different imported name for a function, but at least for gcc recently one can use symver macro. I successfully tested this preparing a special sqlite versions for static linking.
__asm__(".symver pthread_mutexattr_init,pthread_mutexattr_init@GLIBC_2.2.5");
This is great (as long as correct set of functions are chosen) so for the units the end developer has in control, the changes can be made to compile on newer system for executable to work on older ones.
But there are also fpc and lazarus that might use glibc directly or indirectly. Create a simple lazarus form project and readelf it. You will get probably dozens of versioned glibc functions.
Also one of such cases if one creates absolutely new "simple program" having nothing in it and compiling into 200k executable. You readelf it, you won't find any glibc dependencies. But add dynlibs to uses section and you will get dlopen and several other dl... functions with version information (probably 2.34 for recent linux versions, since this glibc version is notable in that they merged different so modules to reside in the single libc so they have to do version increase for plenty of related functions). But the glibc binding is unexpected, the dl unit having dlopen declaration uses "dl" lib. Here we have an indirect consequence, it's probably the smart linker of recent versions who knows (or resolved with symbol chaining) that here it maps dl* function to newly reappeared ones in glibc. I also tried to make a vanilla case with a very simple program with a single simple dlopen import declaration pointing to dl (libdl) lib but the linker still took versioned glibc function for the imported symbol
So fpc (and probably lazarus also) formally distance themselves from the c runtime in most of basic cases (probably threads is another exception) but has no full control about it. But in case with acknowledge that investigation of basic glibc usage in fpc/lazaraus is possible then the capping might look like this
{$ifdef ...}
glibc_ver_cap = '@GLIBC_2.2.5'
{$else}
glibc_ver_cap = ...
....
glibc_ver_cap = '';
{$endif}
pthread_mutex_destroy... external clib name 'pthread_mutex_destroy' + glibc_ver_cap;
But the road is probably difficult. I suspect for example for dl* functions that prior to some version before 2.34 there were no dl* symbols in glibc and everyone linked against libdl. So in some cases the name manipulating might involve not only the name of the imported symbol but also the name of the lib.
Probably compiling on a "minimum" system is still the golden rule for us. The minor issue here is that dealing with this I had to install rpm-based set on a CentOS 7 based system and ended up repacking fpc installer with the instructions found here in forum and elsewhere at the web. Probably the suggestion here is for future fpc installer not to use [ rpmlib(payloadiszstd) ] compression for easier installig in earlier linux versions.