Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A way of using new libs on older systems #1

Open
pseregiet opened this issue Feb 6, 2022 · 8 comments
Open

A way of using new libs on older systems #1

pseregiet opened this issue Feb 6, 2022 · 8 comments

Comments

@pseregiet
Copy link

Hi. I've read your blog post and saw this program. It got me thinking, are we doomed to using old GCC if we want to make portable binaries ? I would think that GCC is getting better and better with each version and it probably generates (even if marginally) better code so I think that sucks. I thought I would try something else.

I've installed Ubuntu LTS 16 and 18 and copied my game to it with the following libs from my current Arch installation:

$ ls stdlibs/ -lh
total 5.4M
-rwxr-xr-x 1 oxi oxi 217K Feb  6 17:55 ld-linux-x86-64.so.2
-rwxr-xr-x 1 oxi oxi 2.1M Feb  6 17:51 libc.so.6
-rwxr-xr-x 1 oxi oxi  23K Feb  6 17:51 libdl.so.2
-rwxr-xr-x 1 oxi oxi 1.3M Feb  6 17:51 libm.so.6
-rwxr-xr-x 1 oxi oxi 151K Feb  6 17:51 libpthread.so.0
-rwxr-xr-x 1 oxi oxi  39K Feb  6 17:56 librt-2.33.so
lrwxrwxrwx 1 oxi oxi   15 Feb  6 17:57 librt.so -> ./librt-2.33.so
lrwxrwxrwx 1 oxi oxi   10 Feb  6 17:57 librt.so.1 -> ./librt.so
lrwxrwxrwx 1 oxi oxi   18 Feb  6 19:02 libSDL2-2.0.so -> ./libSDL2-2.0.so.0
lrwxrwxrwx 1 oxi oxi   23 Feb  6 19:01 libSDL2-2.0.so.0 -> ./libSDL2-2.0.so.0.18.2
-rwxr-xr-x 1 oxi oxi 1.7M Feb  6 19:01 libSDL2-2.0.so.0.18.2

Yes, even the dynamic linker. It is called instead of using the system linker like this

export LD_LIBRARY_PATH=./stdlibs/:$LD_LIBRARY_PATH
./stdlibs/ld-linux-x86-64.so.2 ./game.bin

And it just works(tm). What do you think of this approach ? Do you see anything that could go wrong with this ? I can see one thing already that is a pain with this. It's very hard to connect renderdoc to it since selecting the shell script will cause renderdoc to hook wrong PID and fail. I managed to run renderdoc with such setup only after replacing the system installed linker with my own copy (which was quite funny when for a while ls and cp stopped working when I moved the original file, but I managed :P)

@DanielGibson
Copy link
Owner

Hi,

Hi. I've read your blog post and saw this program. It got me thinking, are we doomed to using old GCC if we want to make portable binaries ? I would think that GCC is getting better and better with each version and it probably generates (even if marginally) better code so I think that sucks. I thought I would try something else.

No, we're not - in fact the blog post shows how to use newer GCC versions and still produce portable binaries (when I wrote it GCC 5.4 was reasonably new and the build chroot was using a debian version that shipped GCC 4.7).

And it just works(tm). What do you think of this approach ?

This is not a viable solution - you should always use the system libc (which shouldn't be a problem, newer GCC versions can still use older versions of glibc), and furthermore this will fail when used on a Linux system that has newer versions of the involved system libs (esp. glibc, ld.so, libstdc++). Because then other system libs your game will be using (like libGL) will depend on those newer versions of glibc or libstdc++, but due to your LD_LIBRARY_PATH they'll try to use the "old" versions you're shipping and the game won't start (or at least won't be able to load libGL or libpulse or whatever other system lib is affected).

See also https://blog.gibson.sh/2017/11/26/creating-portable-linux-binaries/#but-what-if-i-need-a-more-recent-compiler

@DanielGibson
Copy link
Owner

However, I should probably update my wrapper to support GCC (or rather libgcc and libstdc++) versions newer than 7.2

@pseregiet
Copy link
Author

Right. I forgot to add that I wanted to use these libraries only if the system ones are detected to be older. If libraries/binaries build with old version of libc are supposed to still work with newer version of them why would this be a problem ? my program does not link to libgcc or libstdc++ as it's written in C, maybe that's why I didn't have any issues if these libraries are problematic in that sense.

Also what base distribution would you recommend for compiling ? Still debian 7 ? Also do you have any idea how the integration with steam works ? Do they require you to link with their version of libc and such ?

@DanielGibson
Copy link
Owner

Right. I forgot to add that I wanted to use these libraries only if the system ones are detected to be older.

then it's less of a problem, but still, don't ship glibc, link against an old enough version of it so it (for example by first building a modern GCC version in an old build chroot, and then use that GCC version in that build chroot to build your application)

my program does not link to libgcc or libstdc++ as it's written in C

might still use libgcc

Also what base distribution would you recommend for compiling ? Still debian 7 ?

Haven't looked into this in a while (still using my debian 7 based build chroot); but as the blog post is more than four years old now, a newer distro like debian 9 ("Stretch") should be fine.

Also do you have any idea how the integration with steam works ? Do they require you to link with their version of libc and such ?

You should link against a libc that's at least as old as their version (whichever version that is)

@DanielGibson
Copy link
Owner

Also keep in mind that there's nothing wrong with using a different GCC version for day-to-day development than you're using for release builds.
So you could build your release builds with GCC5 or whatever, and still use GCC12 during development to get better diagnostics (compiler warnings) or tools like ASan, UBSan etc

Of course that has the disadvantage that you might not get as advanced optimizations in release builds as you'd get from a newer compiler, but if you care about that you should do benchmarks to check how much of a difference it really makes, i.e. if it's worth the hassle of building a new compiler in an old chroot/VM/.., using this wrapper, etc

@pseregiet
Copy link
Author

pseregiet commented Feb 6, 2022

Also keep in mind that there's nothing wrong with using a different GCC version for day-to-day development than you're using for release builds.

That is my intention.

Of course that has the disadvantage that you might not get as advanced optimizations in release builds as you'd get from a newer compiler

That was my whole concern. It might turn out to be negligible (probably will) but it's still kind of sad that that's how things have to be done.

@DanielGibson
Copy link
Owner

DanielGibson commented Feb 6, 2022

I agree that it sucks that we need this kind of wrapper (and a build chroot/VM) and can't just tell GCC which version of glibc to target, for example.

And while it's probably feasible to statically link libgcc (might be relevant for you?), linking libstdc++ statically is a bad idea - would be nice if there was a clean solution for that as well, like statically linked libstdc++ using different symbol versions than the dynamic lib that might be on the system.
Also, this whole thing of new and delete being global functions in C++, which means that if you overwrite them you also overwrite them for all C++-using libs you might be linking, is bad, but that's a different rant.

Or at least there should be a mechanism kinda like RPATH or LD_LIBRARY_PATH, that automatically prefers the newer lib (between system lib and the one in the given path); basically what my wrapper does should be available in a generic way on operating-system-level.

Anyway, I just updated wrapper.c to support the libs of GCC up to 11.1 (with preparations for 12, which isn't released yet)

@pseregiet
Copy link
Author

Awesome, thanks :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants