Jump to content

  • Log In with Google      Sign In   
  • Create Account


Compiling GLIBC on Linux. Oh golly gosh!


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
16 replies to this topic

#1 bencelot   Members   -  Reputation: 204

Like
0Likes
Like

Posted 04 February 2011 - 12:44 AM

I'm trying to compile my game on Linux. It works find on my Ubuntu system, but when I send the compiled binary off to my buddy with Centos it won't run. It complains saying:


/lib64/libc.so.6: version `GLIBC_2.7' not found
/lib64/libc.so.6: version `GLIBC_2.11' not found
/usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.9' not found
/usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.11' not found

I've googled around the place and it seems that because I compiled on my new computer it's not going to work on his old computer. Whereas if I'd compiled on an old computer it would've worked fine on both. Crazy old Linux! He only has GLIBC_2.5 on his Centos machine, whereas I have 2.11. What I'd like though is for my binary to run on as many installations as possible. I really don't want to have to set up a whole new installation with an old version of GLIBC just to recompile it again. So first of all, can I force my project to compile at the lowest level of GLIBC possible? Or at the very least, how do I remove these symbols (from running: objdump -T MYGAME):

GLIBC_2.4 __stack_chk_fail
GLIBC_2.7 __isoc99_sscanf
GLIBC_2.11 __longjmp_chk
GLIBCXX_3.4.11 _ZNKSt5ctypeIcE13_M_widen_initEv
GLIBCXX_3.4.9 _ZNSo9_M_insertIbEERSoT_
GLIBCXX_3.4.9 _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l
GLIBCXX_3.4.9 _ZNSo9_M_insertImEERSoT_
GLIBCXX_3.4.9 _ZNSo9_M_insertIdEERSoT_
GLIBCXX_3.4.9 _ZNSi10_M_extractIfEERSiRT_


My understanding is that if I remove these symbols from my code/project then it'll run fine on my buddies computer. Of course ideally, if there's a way to support even lower than that this would be awesome. So what's the best course of action here? Is there some compiler option to automatically support the oldest versions of GLIBC and GLIBCXX? Or maybe I have to manually go through and weed all these symbols out (also probably through some compiler options).. or maybe I need to statically link against libc.so.6 and libstdc++.so.6?

Anyway, any help would be greatly appreciated :D
Cheers,
Ben.

Sponsor:

#2 Seaßourne   Members   -  Reputation: 104

Like
0Likes
Like

Posted 04 February 2011 - 02:25 AM

Not every Linux distro is the same. Hence the reason why every distro has their own package manager and it's own set up packaged versions.

#3 Wooh   Members   -  Reputation: 544

Like
0Likes
Like

Posted 04 February 2011 - 02:29 AM

On Linux it's often much easier to just give the source code to the user so he can compile it himself.

#4 Katie   Members   -  Reputation: 1281

Like
9Likes
Like

Posted 04 February 2011 - 02:59 AM

"I really don't want to have to set up a whole new installation with an old version of GLIBC just to recompile it again"

That's not how you do this. You do this with what is called a "chroot".

A chroot (pronounced "chuh-root") is a unix environment INSIDE another unix environment. It's not virtualisation or emulation, it's much more lightweight than that. You simply build a file tree containing a build environment -- typically it will be just the basic minimum packages to do the build, and including *specific* versions of libraries to link against. You then copy your source (or partially built system) into it, and perform the final link.

Here's a document which talks about setting up a chroot;

http://wiki.blender.org/index.php/Dev:Doc/Setting_Up_a_Chroot_Build_Environment_under_Linux

It's actually about how to build blender, but it's got the general stuff in it. Basically chroot starts a new shell and will execute commands, but after setting an environment where / is actually somewhere else. The shell (and its children processes) aren't allowed to peek outside their particular part of the file system.

So you set up a new directory somewhere, and it'll have its OWN /etc, /bin and so on. Of course, it's not a full operating system, so you don't actually get an /etc/passwd in there. What you do then is copy packages somewhere in that tree and then have chroot execute a shell script which installs them. It'll install them into its /bin directory. Then you chroot a script which does your build inside it, then you copy out the completed build.

Building the chroot for the first time can be a little expensive, but you can keep it lying around for when you need it. Many software development teams check the completed chroots themselves into their revision management systems, or keep pristine copies of them on fileservers so they can be just cloned onto build servers when needed. Another reason for doing this is that it makes your build independent of your development environment. You don't need to worry about installing games or whatever on your machine, because even if they upgrade (say) your opengl libraries, you KNOW the version in the chroot is the one you actually want to build against. You don't have to stop doing local builds either -- you can still do that which means all the symbols and source are easy to get at and so on.

Also, you can then (reasonably trivially) build cross-distribution software. For example, I routinely build red-hat RPMs for various version of redhat on my Ubuntu desktop. Why? Well the chroots are fresh -- so I can install anything I want in them, it doesn't have to be the distro on my desktop. So I've got a RedHat 5.6 chroot, and a RedHat 6.0 chroot and also a Suse Enterprise chroot and I can build things in there that will run on those different distros.


There are two things you'll encounter. One is you'll need to find a sufficiently low version of glibc in order to install it in the chroot. Good news is you often get away with just nicking the file itself from somewhere and overlaying that onto a package install.

The next thing is what'll probably get you. The reason that your program is demanding those symbols to dynamically link at runtime is that they're part of a feature in glibc that you're using in your app which only appears in later versions of the library. That's why they're there. It's not Linux being crazy, it's a safety precaution to stop you running apps which need features which aren't present in the local version of glibc. In other words, even if you forced this to work, your app is going to crash. Eventually it'll call an ioctl not supported by the kernel or look-up a glibc entrypoint which doesn't exist or something.

This is how, for example, you get new API calls safely added to glibc. They have an internal versioning system which says "this'll only work on THIS version or higher". Windows, by the way, does exactly the same thing only instead of complaining about missing symbols like that it pops up a message box saying something like "This program cannot be run because there are parts of its environment missing" but crucially doesn't tell you which version of the c runtime will be sufficient to run it...

You *can* solve this by finding out what's dragging those symbols in and programming around that. The STL is particularly fond of this, but other things will do it as well. If you can locate them and it's something you have an alternative for then you can simply use the alternative. I've fixed compilation errors in this way before -- ISTR one was something like an STL linked list operation needed the feature but the equivalent for vectors didn't so I rewrote the one container which was causing the problem to used a vector, took the performance hit for vector resizing (which was small enough not to worry) and now my app "just worked" on the target systems.

#5 phresnel   Members   -  Reputation: 949

Like
0Likes
Like

Posted 04 February 2011 - 07:44 AM

every distro has their own package manager


Uhm ...

There are only two "mainstream" packaging systems, debs and rpms. And in many cases, carefully stuffed packages install on many distros that understand the package in question. The last deb I've personally distributed e.g. would install on at least Ubuntus 10.x, Debians 5.x, Mint and gNewSense (others not tested).



O.P.: Maybe ELF Statifier could be of interest to you, though it completely circumvents the whole idea behind package managers. An extravagant idea could also be to setup a virtualbox-image :D

#6 SimonForsman   Crossbones+   -  Reputation: 5752

Like
0Likes
Like

Posted 04 February 2011 - 08:23 AM

Here you go:
http://ldn.linuxfoundation.org/lsb/build-lsb-compliant-application

If you intend to do cross distribution binary only applications the LSB is your best friend.
I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!

#7 Bregma   Crossbones+   -  Reputation: 4747

Like
0Likes
Like

Posted 04 February 2011 - 08:35 AM

A third alternative you could consider is to build your game statically.

You get this exact same problem on Microsoft Windows. Often times application vendors work around simply by shipping all the runtimes with their app (eg. MSVCRT.DLL and friends).
Stephen M. Webb
Professional Free Software Developer

#8 bencelot   Members   -  Reputation: 204

Like
0Likes
Like

Posted 04 February 2011 - 10:18 AM

Thanks for all the suggestions guys :D

Katie, thx for that massive reply. I think I might set up a chroot environment. Can you reccomend a good distrbution to target the lowest level possible (for maximum compatibility)?
--------------------------Check out my free, top-down multiplayer shooter: Subvein

#9 outRider   Members   -  Reputation: 852

Like
0Likes
Like

Posted 04 February 2011 - 10:48 AM

Centos, RHEL, SLES and some other distros intended for 'enterprise' type machines have relatively old (aka 'stable') versions of most software compared to something like Ubuntu so you have to be aware of that if you intend to distribute binaries.

#10 Steve132   Members   -  Reputation: 433

Like
0Likes
Like

Posted 04 February 2011 - 11:12 AM

So, I could be wrong here, but did you try checking to see whether he is running a 32-bit install? Its obvious that you are running a 64-bit install...is it possible he has a 32?

#11 bencelot   Members   -  Reputation: 204

Like
0Likes
Like

Posted 04 February 2011 - 07:55 PM

He has 64 bit. But that's another good point.. obviously I want my game to be playable on both 32 and 64 bit installations. What's the best way to deal with this? Is it possible to create 1 binary that will work on both? Or do I need to build 2 separate binaries?
--------------------------Check out my free, top-down multiplayer shooter: Subvein

#12 valderman   Members   -  Reputation: 512

Like
0Likes
Like

Posted 05 February 2011 - 05:24 AM

He has 64 bit. But that's another good point.. obviously I want my game to be playable on both 32 and 64 bit installations. What's the best way to deal with this? Is it possible to create 1 binary that will work on both? Or do I need to build 2 separate binaries?

Create an LSB-compliant 32-bit binary, make sure your program depends on the proper 32-bit packages. Unless you're going to use 2+ gigs of RAM, there's no point in also creating a 64-bit binary.

#13 bencelot   Members   -  Reputation: 204

Like
0Likes
Like

Posted 05 February 2011 - 08:35 PM

Hmm ok. So can I create 32 bit chroot environment and compile within that? Any suggestions? Or do I need to add some compiler flag to make it 32bit (I'm on a 64bit machine).
--------------------------Check out my free, top-down multiplayer shooter: Subvein

#14 Zoner   Members   -  Reputation: 232

Like
1Likes
Like

Posted 06 February 2011 - 10:53 PM


He has 64 bit. But that's another good point.. obviously I want my game to be playable on both 32 and 64 bit installations. What's the best way to deal with this? Is it possible to create 1 binary that will work on both? Or do I need to build 2 separate binaries?

Create an LSB-compliant 32-bit binary, make sure your program depends on the proper 32-bit packages. Unless you're going to use 2+ gigs of RAM, there's no point in also creating a 64-bit binary.


Except all those additional juicy registers and a better ABI, and SSE2 minspec. No reason at all :)

#15 demonkoryu   Members   -  Reputation: 976

Like
1Likes
Like

Posted 07 February 2011 - 02:23 AM

Except all those additional juicy registers and a better ABI, and SSE2 minspec. No reason at all :)




More registers are fine, but the performance benefit is mitigated by the fact that the larger memory footprint of 64-bit code leads to more cache trashing. In effect, performance of 64-bit code can be worse than 32-bit code.

#16 Katie   Members   -  Reputation: 1281

Like
0Likes
Like

Posted 07 February 2011 - 04:56 AM

You'll want to say things like "-m32" and "-arch i386" in your build flags.

#17 valderman   Members   -  Reputation: 512

Like
1Likes
Like

Posted 07 February 2011 - 05:32 AM



He has 64 bit. But that's another good point.. obviously I want my game to be playable on both 32 and 64 bit installations. What's the best way to deal with this? Is it possible to create 1 binary that will work on both? Or do I need to build 2 separate binaries?

Create an LSB-compliant 32-bit binary, make sure your program depends on the proper 32-bit packages. Unless you're going to use 2+ gigs of RAM, there's no point in also creating a 64-bit binary.


Except all those additional juicy registers and a better ABI, and SSE2 minspec. No reason at all :)

Then it's better to just compile a second binary with -msse2. As demonkoryu says, more registers and fancier instructions do nothing for you if you hit RAM all the time. Add in the porting issues you get for using a low-level language and maintaining two binaries suddenly seems a lot less attractive.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS