Game test beta suggest

You might also simplify your entire build and distribution toolchain
by using OpenLINA, but I’m not sure if they support audio yet.

This seems to be something rather different from actual portability,
namely a way of running native Linux applications
anywhere. “Installer with integrated VM/emulator”, if you like.

I won’t argue what “actual portability” means, or whether or not a
transparent VM (eg. using Mac OS “classic” or OpenLINA apps) can
provide it. OpenLINA does, however, “simplify your entire build and
distribution toolchain.”

That said, it should work, theoretically, but it’s probably not what
you want for a game, and especially not a small downloadable one.
(Linux kernel and stuff included in the install image…)

I think a “small, downloadable” game is the perfect kind of game to
use OpenLINA. On any x86 system that can’t run Linux binaries
natively, there’s still some overhead in OpenLINA that will prevent
your application from reaching 100% efficiency (in fact, more like 90%
efficiency.) I don’t think a cutting-edge, resource-intensive video
game would be an ideal candidate for the OpenLINA platform. On the
other hand, anything less than that seems to me to be the ideal
candidate (although again, I don’t know how audio is doing on OpenLINA
yet.)

Anyhow, there’s nothing stopping anyone from including an OpenLINA
build in addition to whatever other builds they offer, and since an
OpenLINA build will run on a lot more systems than your average build,
it seems like a good work/reward ratio.On Mon, Dec 15, 2008 at 10:16 AM, David Olofson wrote:

On Monday 15 December 2008, Donny Viszneki wrote:


http://codebad.com/

Actually I’m not even sure if SDL works with OpenLINA yet, so maybe
there is something stopping you from doing this.On Mon, Dec 15, 2008 at 12:00 PM, Donny Viszneki <@Donny_Viszneki> wrote:

Anyhow, there’s nothing stopping anyone from including an OpenLINA
build in addition to whatever other builds they offer, and since an
OpenLINA build will run on a lot more systems than your average build,
it seems like a good work/reward ratio.


http://codebad.com/

Den Mon, 15 Dec 2008 11:15:03 +0000
skrev “Neil White” :

well i have a debian binary, when it comes to releasing for linux
with non sauce i’m not sure to do the whole static linked libraries,
or just wuss out and only have downloads for major dists, ie
debian/ubuntu redhat/fedora and whatever else, dunno, it’s a bloody
nightmare deciding how to distribute sort store etc linux stuff as in
where to store high scores data exe files and all that jazz.

For user-local high scores, you could store them per user somewhere
under $HOME ($HOME/.your-company/game/highscores.dat or something, or
should we use $XDG_CONFIG_HOME as a base now, falling back to
$HOME/.config? Anyone?). This only requires the permissions of the
current user, which you’re pretty much guaranteed to have as they’re
the ones running the game after all =). But, other users on the same
system will have their own instance of the high scores. (Most desktop
systems are probably single-user though.)

For system-wide high scores, somewhere under /var/games would be the
correct place probably. This directory already exists with
write-permission for the games group on many (most?) modern distros, so
any user in the games group would be able to read/write highscores and
such from there. There’s the possibility that someone playing games
are not in the games group I suppose, but eh, that’s a user error ;)…
Also, /var/games is optional according to the Filesystem Hierarchy
Standard, so it’s not guaranteed to be present, and if it’s not you’d
need some way of getting the permissions right for it to work, probably
at install time. Or just disable highscores and tell the user why (“go
fix /var/games if you want highscores”).

As for the executable itself… This’ll take a while =]

Link what you can statically, dynamically link the rest. The only
exception to this rule is, do NOT link glibc statically. It’ll
probably work in the short term, but it’s less compatible with older
and probably newer distros. Linking it dynamically introduces glibc
compatibility issues though since you can’t/shouldn’t distribute glibc
with your game, but let’s not get ahead of ourselves…

SDL is LGPL, so since your game is closed source you should link that
dynamically. That’s not a problem though, just include dynamically
linked libraries with the game! Everything except glibc, that is.
This removes a lot of headaches since you know exactly what library
versions the game is used with and don’t have to worry about
incompatible versions. Basically make your game live in its own little
self-contained bubble in the filesystem.

You have to tell your game where to look for the libraries, though, or
else it’ll just load them from the default locations (/usr/lib etc).
This can be done either by setting LD_LIBRARY_PATH to the path of your
libraries, or by setting the RPATH property of the game’s executable to
point to the path. LD_LIBRARY_PATH has to be set before the game
is run, so you’ll need a wrapper script if you go that route.

By the way, there’s a nice series by Troy Hepfner on gamedev.net that
should be helpful, starting here:

http://www.gamedev.net/reference/programming/features/linuxprogramming1/

It doesn’t seem to talk about glibc compatibility though, which I
thought they did. Maybe I should talk with Troy about an update…

Also doesn’t mention rpath, and I’ve been leaning more and more
towards preferring RPATH over LD_LIBRARY_PATH lately. RPATH works kind
of like LD_LIBRARY_PATH, except you embed the path into the executable
itself (it’s a property of the ELF executable format). But more about
that later…

First a little bit about glibc compatibility though. glibc is the
standard C library on Linux. Simply put, it’s updated all the time, and
your development box might have a newer version of glibc than your
potential customers have. Sometimes this means that your executable
will depend on newer versions of functions and such that are only
available in later glibc versions, meaning your game will not run on
systems with earlier versions.

The easiest way to deal with the problem is to simply ignore it. If
you’re not using the latest bleeding edge for your development,
and with a bit of luck, it won’t be much of a problem. I think most
linux users are good about updating their systems. Automatic package
management helps there =). Depends on the game though, there do also
exist more casual linux users that are less concerned about keeping up
to date, and people who might not want to run the latest thing on older
pcs, etc.

Another way, target a few common distros and versions of those
distros, make sure it works on those, and tell people on anything else
that they’re on their own. Will take care of most people probably.
Checking that stuff works on common distros is probably wise in any
case.

You could also install an older distro that uses an older version of
glibc in a different partition or subdir somewhere and chroot into
that, or even run it in a virtual machine, and use that to do your
builds.

Or, you could cheat =). This is essentially what I do; though I do
use a build environment in a chroot, its version of glibc is not the
oldest possible. It’s essentially just a regular install of gentoo, so
I use whatever glibc is available there (but don’t update it often).
However, I also use this:

http://delirare.com/files/gensymoverride

Just running this agaist all the libraries in /lib and /usr/lib (run
without args for usage info) will generate an include file. It’s
printed to standard output by default, so you should probably pipe that
to a file (you should do this every time you update glibc). This file
can then be force-included on every compilation to make the compiler
link against older glibc symbols wherever possible, even though a newer
glibc is used at link time. In my gentoo-chroot I’ve saved the output
of this to a file, and added an extra gcc configuration that calls a
script with this in stead of the normal gcc:

#!/bin/sh
/path/to/gcc -include /path/to/override.h “$@”

It’s a bit of a hack, but it works =). Using a chroot isn’t strictly
necessary for this btw, you can use it with whatever you normally use
for development and just set the compiler setting for your builds to use
the script that forces the include in stead of the normal gcc.

One thing to watch out for though is that using the script will fail
(compile aborts) if headers tell something to use a function that is
only available in a glibc that’s newer than your minimum. If this
happens, you’ll have to either up your requirements, or use a real
older glibc so that you don’t get that kind of conflict from headers.
I think it was glibc 2.3 that introduced some useful yet compat-
breaking stuff, so I think I’m targetting 2.3 and higher currently
(ie ./gensymoverride GLIBC 2.3.1 ...), which works pretty well. Or I
might have upgraded to 2.3.6 and higher or something, not sure. Should
be safe to use that now, anyway, it’s getting pretty old by now.

If all that is scary, just try the easiest option first. You might
be lucky =). Oh, and you can check glibc requirements with objdump,
like this: objdump -x my_executable | grep GLIBC. It’ll list some
glibc versions, the highest one is your minimum version requirement.

Oh also, if your game is C++, you’ll depend on libstdc++. You should
either link this statically (it’s GPL, but there’s a special exception
that allows static linking even for closed-source stuff), or distribute
it along with your game like the other libraries. Linking libstdc++
statically will also allow you to remove the dependency on
libgcc_s.so.1. libgcc_s is probably present on most systems by now,
but if it isn’t it’s a problem, as you can’t distribute it! Your
game will abort with an error when run if you try. You can get rid
of it by passing -static-libgcc to gcc, but this won’t work if
libstdc++ is dynamically linked. However, libstdc++ should not be
linked statically if you also link dynamically to other libraries that
also depend on the libstdc++ library, or you’ll be unable to catch
exceptions across library boundaries and possibly run into symbol
conflicts (distributing libstdc++ should take care of the latter one,
mostly defeating the point in the process though).

Rule of thumb: Either link every C++ library statically into one
executable, or link every C++ library dynamically. Don’t mix.

To link libstdc++ statically, you need to get its location (it may
vary depending on compiler and stdc++ version), through g++, and append
that as the final part of the link line. Also tell g++ to statically
link libgcc, to get rid of the libgcc_s dependency. You end up
calling g++ twice on one line, like this:

g++ -static-libgcc (… your stuff …) g++ -print-file-name=libstdc++.a

Now, about LD_LIBRARY_PATH and RPATH… Some pros and cons of both:

LD_LIBRARY_PATH:

  • Easy to use, no setup!
  • Requires wrapper script.

Running the game without the wrapper script may fail or bug out in
strange ways if a buggy or incompatible library is already installed on
the system. This is very rare and shouldn’t happen normally, but
despite this I’ve actually got the occasional bug report caused by
people not running a game through the wrapper, so it does happen.

Also, a wrapper script is a script. The dependance on a compatible
shell shouldn’t be a problem in practice, but some file managers (like
the one Gnome uses) asks the user if they really want to execute
scripts if they attempt to execute them. Not really a problem, but
there’s that extra click. Usually you’d have a .desktop file and menu
entries for launching from GUI though, so this is a bit of a moot point,
unless you’re dealing with makeself-type installers, which you really
shouldn’t be doing now that we’ve got better things like MojoSetup =).
Actually webbrowsers not saving executable files as executable is a
much bigger issue there, but I’m rambling, so let’s move on…

RPATH:

  • Completely automatic, no wrapper script needed! Impossible to screw
    up by user :wink:
  • No tools to set rpath of existing binaries(?). Fiddly to set up, you
    need to link the executable right, and possibly some libraries too.

Also, some libraries may have an absolute rpath (starts with a
slash) that interferes with this. This is true whether you use
LD_LIBRARY_PATH or RPATH. None of the libraries you distribute with
your game should have absolute rpaths, or they won’t load properly.
You can check if there’s any rpath in any ELF file (executable/.so) by
doing objdump -x my_executable | grep RPATH.

Using LD_LIBRARY_PATH does work fine though, and as I said it’s easier
to set up. Rpath is ultimately somewhat more robust once set up, but
might be a bit confusing though, so going with LD_LIBRARY_PATH at least
for now might not be a bad idea =)

Anyway, if you’re still reading, let’s get on with it. For
LD_LIBRARY_PATH you can read the series I linked above, here’s how to
use RPATH…

With gcc you set rpath by adding -Wl,-rpath,/some/path to the link
options. On runtime, RPATH is set automatically by the runtime linker,
so you don’t have to worry about it after link time, but setting it
right can be a little bit tricky. Specially if you use autotools to
build, or your link line is passed through lots of scripts.

Problem is you can’t use an absolute rpath because that’d restrict your
game to only one location, and you can’t use a relative rpath because
relative rpaths are relative to the current directory, which could be
anything at all when your game is launched. And setting the rpath on
install time would be messy even if there existed tools that could
modify the rpath without relinking (I’ve been unable to find any for
some reason).

However, there’s hope! The runtime linker supports macros, and the
$ORIGIN macro seems to have been designed for exactly our purposes, as
it resolves to the directory of the executable, whatever it may be.
So, eg setting an rpath of “$ORIGIN/lib” (without the quotes) will look
for libraries in the “lib” subdir where your game’s executable is.
Pretty convenient! Something to keep in mind though is that $ORIGIN
resolves to the real location of the executable, ie after symlinks
have been resolved.

Also, $ORIGIN is a macro for the runtime linker, but it looks exactly
like a shell one. So, if the shell sees that dollar sign unprotected,
it’ll happily go and replace it with something from the environment,
screwing up your runtime linkage. You’ll have to prevent that by
protecting the macro from the shell. Exactly how you do this depends on
your build environment, but you’ll probably need a couple backslashes
for the shell and perhaps a few double $ for Makefiles, ending up with
something like ‘\$$\$$ORIGIN/libs’. Fun!

…ok, that’s a bit exaggerated =). Usually you’ll do fine with much
less. In a Makefile you’ll need at least ‘$$’ (an extra dollar sign
for make, making it $, which is then passed to the shell). In a
SConstruct file here, I’ve got “… ‘$$ORIGIN’ …”. Single quotes help.

Check the rpath with objdump -x my_executable | grep RPATH. You can
also just do ldd my_executable and see if it locates things all right.
ldd goes through the normal runtime link routine, so it’ll pick up on
the rpath and use it like the regular linker. If you’re on a 64-bit
distro and working with 32-bit binaries, you might have to use ldd32 or
somesuch in stead (though really the ldd script should take care of
that little detail for you…).

Oh and also, RPATH doesn’t propagate to affect dlopen’ed libraries in
dynamically loaded libraries (unlike LD_LIBRARY_PATH)! That’s a
horrible sentence, but it’ll hopefully become clear in a second =)

For example, depending on how SDL_mixer is compiled it might dlopen
libvorbisfile, and SDL_ttf can dlopen libfreetype, etc. So, let’s say
you’ve set the rpath of your executable to “$ORIGIN/lib”, your game
uses SDL_mixer with dlopen of libvorbisfile enabled, and one of your
customers installed your game into /opt/games/totally-awesome-game.
…Actually, let’s make that /opt/pong for brevity. That means your
libraries is in /opt/pong/lib, and the executable will look for them
there. However, your bundled version of SDL_mixer
(/opt/pong/lib/libSDL_mixer.so.0) doesn’t know about the rpath after
the initial link, so when it later tries to dlopen libvorbisfile.so.3,
it WON’T look for it in /opt/pong/lib, unless you ALSO set the rpath of
libSDL_mixer.so.0 to the location of libvorbisfile.so.3, where $ORIGIN
is relative to the location of libSDL_mixer.so.0. The rpath of
libraries are also used to verify their own location, so you should put
them both in the same location to avoid some trouble. So, assuming
they are, set the rpath of libSDL_mixer.so.0 to ‘$ORIGIN’. You end up
with something like this for the installed game:

$ cd /opt/pong
$ ls
libs/
my_executable
$ objdump -x my_executable | grep RPATH
RPATH $ORIGIN/lib
$ ldd my_executable
libSDL_mixer-1.2.so.0 => /opt/pong/lib/libSDL_mixer-1.2.so.0
lots of other stuff
conspicuous lack of libvorbisfile.so.3 due to dlopen-ness
$ ls lib
libSDL_mixer-1.2.so.0
libvorbisfile.so.3
libvorbis.so.0
lots of other stuff
$ objdump -x lib/libSDL_mixer-1.2.so.0 | grep RPATH
RPATH $ORIGIN

Actually SDL_mixer is kind of a bad example for this as you can simply
statically link the vorbis stuff into SDL_mixer, or even if you want it
dynamic, tell SDL_mixer to NOT use dlopen for that when configuring.
But hey, at least you’re aware of this potential pitfall now =)

Hope this helps =)

  • Gerry

well Gerry, thats really clarified things :wink:

seriously tho, thanks for your insight, hopefully help alot of other people
as well :wink:

i have seen the thing on gamedev.net but as yet never bothered to try and
implement it.

i think i’ll just go for the major distros binary route and some form of
request form for other distros, this all assumes i ever finish the game of
course :wink: