I would like to build a C++ application which can be launched on all Linux systems having libc >= 2.31. On my build system (Ubuntu), I have libc 2.34. Here is my (empty) application:
int main() {
return 0;
}
I built it with g++ -o app app.cpp and according to the following result, I understand that my application requires libc >= 2.34 to run. Is my understanding correct ?
$ nm -D app
w __cxa_finalize@GLIBC_2.2.5
w __gmon_start__
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U __libc_start_main@GLIBC_2.34
How build my application for libc <= 2.31 ? I tried to add "__asm__ (".symver __libc_start_main, __libc_start_main@GLIBC_2.2.5");" (based on my understanding of this post) before my main method but it does not change anything.
HolyBlackCat and this guy have already said to just use Docker https://news.ycombinator.com/item?id=32479545
If you still want to pursue the space saving solution of telling new GCC to use the old __libc_start_main, then asm(".symver",...) isn't enough because that only takes effect in the current file being compiled. __libc_start_main isn't called from your code, but in glibc's _start() (files like /usr/lib/x86_64-linux-gnu/crt1.o). The call graph is like this
_start
__libc_start_main
main
You could tell the linker to use an old version of crt1.o or whatever, but that's impractical. Here's a solution that overrides __libc_start_main to call the old version. It requires extra link flags and assumes the old __libc_start_main has the same signature as the new one, which I'm not sure of.
// g++ a.cpp -Wl,--wrap=__libc_start_main
#include <stdio.h>
extern "C"
{
__asm__(".symver __libc_start_main_old,__libc_start_main@GLIBC_2.2.5");
int __libc_start_main_old(int (*main) (int, char **, char **),
int argc,
char **argv,
__typeof (main) init,
void (*fini) (void),
void (*rtld_fini) (void),
void *stack_end);
int __wrap___libc_start_main(int (*main) (int, char **, char **),
int argc,
char **argv,
__typeof (main) init,
void (*fini) (void),
void (*rtld_fini) (void),
void *stack_end)
{
return __libc_start_main_old(main,argc,argv,init,fini,rtld_fini,stack_end);
}
}
int main(int argc,char**argv)
{
printf("test\n");
return 0;
}
Docker image ubuntu:20.04 has libc 2:31 installed. You could compile your application there:
$ docker run --rm -v $PWD:/work -w /work ubuntu:20.04 bash -c 'apt-get update && apt-get -y install g++ && g++ -o app app.cpp'
$ docker run --rm -v $PWD:/work -w /work ubuntu:20.04 ./app
$ ./app
$ nm -D app
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w __cxa_finalize@GLIBC_2.2.5
w __gmon_start__
U __libc_start_main@GLIBC_2.2.5
You could link your application statically, remove all dependencies on standard library.
You could distribute your application with libc library together.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With