Next: Coding guidelines, Previous: Core algorithm, Up: Hacker's guide [Contents][Index]
In addition to all the common
Autoconf switches
such as --prefix
, Liquid War 6 has some custom switches:
--disable-console
: allows you to turn on/off console support.
Normally this is detected automatically but in case you really want
to disable it on platforms which support it, you can. This will cause
the program no to link against libreadline
, among other things.
--disable-gtk
: allows you to turn on/off gtk support.
Normally this is detected automatically but in case you really want
to disable it on platforms which support it, you can. This will cause
the program not to link against GTK libs.
--disable-cunit
: allows you to turn on/off
CUnit
support.
Normally this is detected automatically but in case you really want
to disable it on platforms which support it, you can. This will cause
the program not to link against CUnit libs.
--enable-optimize
: will turn on optimizations. This will
turn on compiler options such as -fomit-frame-pointer
but also disable some code in the program. Indeed, most of
the advanced memory checking in the game - which ensures it
does not leak - will be turned of. This will certainly speed up
things, however, it’s not recommended to turn this on until
program is not stable enough so that memory leaks and other
problems can be declared ’impossible’. Turn this on if you
really have some speed problem, otherwise it’s safer to use
the full-featured ’slow’ version of the game.
--enable-paranoid
: will turn on very picky and pedantic
checks in the code, try this when you suspect a serious memory
bug, a race condition whatsoever, and want to track it down.
Useless for players.
--enable-headless
: will allow compilation without any
graphics backend. The game is unplayable in that state but one
can still wish to compile what is compilable, for testing purposes.
--enable-silent
: will allow compilation without any
sound backend. The game won’t play any music in that state but one
can still wish to compile what is compilable, for testing purposes.
--enable-allinone
: will stuff all the internal libraries
into one big executable.
Very convenient for profiling. The major drawback is that
you need to have all the optional libraries installed
to compile all the optional modules. Another side effect is that
with this option there’s no more dynamic loading of binary modules,
so if your platform has a strange or buggy support for .so
files, this option can help.
--enable-fullstatic
: will build a totally static
binary, that is using the --static
option
for gcc
and the -all-static
option
for libtool
. Currently broken, this option could
in the future allow for building binaries that run
pretty much everywhere, without requiring any dependency
but a Kernel.
--enable-gprof
: will enable profiling informations.
This will activate --enable-allinone
, else you would
only track the time spent in functions
in the main liquidwar6
executable, and exclude lots
of interesting code contained in dynamic libraries.
--enable-instrument
: will instrument functions for
profiling. This will turn on the -finstrument-functions
switch when compiling, so that the hooks
__cyg_profile_func_enter
and __cyg_profile_func_exit
are called automatically. Then you can link against tools like
cprof or
FunctionCheck.
--enable-profiler
: will enable
Google Performance Tools
support. Basically, this means linking against libtcmalloc
and libprofiler
. You could activate those by using
LD_PRELOAD
or by using your own LDFLAGS
but
using this option will also make the game tell you if
CPUPROFILE
or HEAPPROFILE
are set
when it starts. The pprof -gv
output is very handy.
Note that on some systems pprof
is renamed google-pprof
.
--enable-gcov
: will enable coverage informations,
to use with gcov
and lcov.
This is for developpers only. It will activate --enable-allinone
,
else there would be some link errors when opening dynamic libraries.
The obtained information is available online:
coverage.
and
GNU global.
--enable-valgrind
: will enable some CFLAGS
options which are suitable for the use of
Valgrind, to track
down memory leaks and other common programming errors.
Use for debugging only, usually together with
--enable-allinone
.
Liquid War 6 does have a ./debian
in both main and extra maps packages,
so it’s “debianized”.
To build the main .deb
package, untar the main source tarball, then:
make dist cd pkg cp ../liquidwar6-X.Y.Z.tar.gz . # X.Y.Z is the version make deb
Note that you have to copy the source tarball to ./pkg
and move
to this directory before typing make deb
. This is, among other things,
to simplify the main Makefile
.
To build the extra maps .deb
package, untar the extra maps tarball, then:
make deb
Liquid War 6 does have a .spec
files in both main and extra maps packages.
To build the main .rpm
package, untar the main source tarball, then:
make dist cd pkg cp ../liquidwar6-X.Y.Z.tar.gz . # X.Y.Z is the version make rpm
Note that you have to copy the source tarball to ./pkg
and move
to this directory before typing make rpm
. This is, among other things,
to simplify the main Makefile
.
To build the extra maps .rpm
package, untar the extra maps tarball, then:
make rpm
This section describes how to compile the game from source under Microsoft Windows. Note that players are encouraged to use a free system such as GNU/Linux, which is the platform Liquid War 6 is being hacked on by default. If you encounter problems with this port, you’ll probably save time by installing a double-boot with GNU/Linux coexisting with your previous Microsoft Windows install.
Basically, Liquid War 6 requires
MinGW.
More precisely, it requires MSYS.
A standard Cygwin installation won’t
work, because it is too UNIXish to allow third party libraries
like SDL to compile natively.
You might argue that SDL is available for Cygwin, but in reality,
the Cygwin port of SDL is a MinGW port. Indeed, Cygwin brings
all standard POSIX functions including the use of main
instead of WinMain
and I suspect this is a problem for
graphical libraries like SDL which do require some sort of direct
access to the OS low-level functions. Therefore, MinGW is more
adapted for it does not define all these functions, and
allows any library to hook on Microsoft Windows internals directly.
Point is then, you also loose the cool effect of Cygwin which
is to have a complete glibc
available,
including network functions like select
defined the
POSIX way, and not the WinSock way. If you ever ported code from
POSIX sockets to WinSock 2, you know what I mean. Using MinGW
is also embarassing for some libraries won’t compile easily, and
for instance programs which heavily rely on a real TTY
interface to work are usually hard to port. This includes
ncurses
and
GNU readline.
Liquid War 6 tries to have workarrounds for all this, and in
some cases the workarround is simply that embarassing code
is not compiled on Microsoft Windows. For this reason, some
features are not available on this platform. Period.
Now the reason you need MSYS and not only MinGW is that MSYS
will allow ./configure
scripts to run, and this eases
up the porting process a lot. MinGW and MSYS packages are
downloadable on the
SourceForge MinGW download page. Alternatively, there is a
mirror on ufoot.org,
but files might be outdated.
To compile Liquid War 6, first download and unzip all the
following files in
the same directory, for instance C:\MSYS
.
If you do not have any tool to handle .tar.gz
and .tar.bz2
files under Microsoft Windows, which is likely to be the case
when MSYS is not installed yet, you can untar these on any GNU/Linux box,
then upload the whole directory to the target Windows host.
This file list might contain file which are not absolutely mandatory for Liquid War 6, for instance the Fortran 77 compiler is absolutely useless, but installing it won’t harm either. Some packages might unzip things the right way, but some do it in a subfolder. You might need to run commands like:
cp -r coreutils*/* . rm -rf coreutils*
Get rid of useless files:
rm ._.DS_Store .DS_Store
It’s also mandatory to move everything that has been installed in
/usr
or /usr/local
to /
since MSYS has some
builtin wizardry which maps /usr
on /
.
You need to do this if you don’t unzip files from a MinGW shell,
which is obviously the case when you first install it. Usefull command
can be:
mv usr/* . rmdir usr
Next, libintl
is not correctly handled/detected by LW6,
and can raise an error like
"gcc.exe: C:/msys/local/lib/.libs/libintl.dll.a: No such file or directory"
so one needs to copy some libraries in /usr/local/lib/.libs/
:
mkdir local/lib/.libs cp local/lib/libintl.* local/lib/.libs/
Another step is to edit /etc/profile
and add lines like:
export CFLAGS="-g -I/usr/local/include" export LDFLAGS="-L/usr/local/lib" export GUILE_LOAD_PATH="C:\\MSYS\\local\\share\\guile\\1.8\\"
Close and re-launch your msys shell (rxvt) so that these changes take effect. Check that those values are correctly set:
env | grep FLAGS env | grep GUILE
Finally, your MSYS environment is (hopefully...) working.
Now you need to compile the following programs, from source.
Files are mirrored on ufoot.org for your convenience, however these might be outdated.
Still, there are known to work.
Proceed like if you were under a POSIX system.
Some packages use the --disable-rpath
swith, there are various
reasons for which rpath is an issue.
In the same manner, --disable-nls
when linking against libintl
or libiconv
was painful.
make clean GC; cp pthread.h sched.h /usr/local/include/; cp pthreadGC2.dll /usr/local/bin/; cp libpthreadGC2.a /usr/local/lib/
gmp-4.2.2.tar.gz
then ./configure && make && make install
guile-1.8.5.tar.gz
.
Edit libguile/guile.c
and insert #undef SCM_IMPORT
just before #include <libguile.h>
.
Edit ./libguile/threads.c
and place struct timespec { long tv_sec; long tv_nsec; };
just before #include "libguile/_scm.h"
.
Then ./configure --disable-nls --disable-rpath --disable-error-on-warning --without-threads && make && make install
. The GUILE_LOAD_PATH
value must be correctly
set for guile-config
to work. For unknown reasons, running guile
can throw a stack overflow error. Don’t panic.
See bug 2007506 on SourceForge.net for an explanation on
why the Guile binary shipped with MSYS is not suitable for Liquid War 6.
expat-2.0.1.tar.gz
then ./configure && make && make install
sqlite-amalgamation-3.5.9.tar.gz
then ./configure && make && make install
libpng-1.2.29.tar.gz
then ./configure && make && make install
jpegsrc.v6b.tar.gz
then ./configure && make && make install && make install-lib
curl-7.18.1.tar.gz
then ./configure --without-ssl && make && make install
freetype-2.3.5.tar.gz
then ./configure && make && make install
libogg-1.1.3.tar.gz
then ./configure && make && make install
libvorbis-1.2.0.tar.gz
then LDFLAGS="$LDFLAGS -logg" && ./configure && make && make install
SDL-1.2.13.tar.gz
then ./configure && make && make install
SDL_image-1.2.6.tar.gz
then ./configure && make && make install
SDL_mixer-1.2.8.tar.gz
then ./configure && make && make install
SDL_ttf-2.0.9.tar.gz
then ./configure && make && make install
For your convenience, a zip file containing a complete MSYS "Liquid War 6 ready"
environment is available. It is simply the result of all the operations
described above.
Simply unzip msys-for-liquidwar6-20080819.zip
(about 240 megs) in C:\MSYS\
.
All dependencies compiled in /local
have been generated
using the command:
cd /usr/local/src ./msys-for-liquidwar6-build.sh > ./msys-for-liquidwar6-build.log 2>&1
Note that this script does’t do everything, you’ll still need to edit Guile source code and patch it manually.
It might even be possible to use this MSYS environment
under Wine.
Simply unzip it under $HOME/.wine/drive_c
, and run
wine "$HOME/.wine/drive_c/windows/system32/cmd.exe" /c "c:\\msys\\msys.bat"
and with
luck, you’ll get a working shell. Note that this might allow you to compile
the game, but running it is another story. Consider this MSYS over Wine trick
as a hack enabling the use of free software only when compiling for
Microsoft proprietary platform. It is not a reasonnable way to run the game.
If running under a UNIXish platform, or better, GNU, simply run native code.
Use the Windows 32-bit port only if you are jailed on a Microsoft system.
Now, let’s come to the real meat, untar the Liquid War 6 source tarball, launch your MSYS shell, and:
./configure make make install
Now the binary is in src/.libs/liquidwar6.exe
(beware, src/liquidwar6.exe
is only a wrapper).
This binary is an MSYS/MinGW binary, so it read paths “Ã la”
Microsoft, that is, it has no knowledge of what /usr
is,
for instance. It requires paths starting by C:\
.
This is still experimental. Basically, install MacPorts, and most dependencies with,
except for SDL which you compile from source. The idea is to compile SDL using
the native OS X bindings (and not some other GL files you could have in /opt/local
installed by MacPorts), then compile the game and other SDL dependencies
against this SDL.
The SDL_mixer library might need to be told to compile itself without dynamic ogg support.
By default it seems that it tries to load libvorbisfile.dylib
at runtime, and it can fail.
To disable this dynamic loading, use for instance :
/configure --prefix=/opt/extra --enable-music-ogg --disable-music-ogg-shared
Also, it might seem obvious for Mac OS X users, but there are some important issues related to compiling options and handling dynamic libraries at runtime.
ldd
does not exist, run otool -L
instead.
LD_LIBRARY_PATH
is DYLD_LIBRARY_PATH
.
.dylib
and not .so
.
OBJCFLAGS
environment variable along with CFLAGS
because the Mac OS X port uses some Objective-C code.
It is very important to have the right SDL flags when linking the Liquid War 6 binaries. For instance it could be:
-I/opt/extra/include -I/opt/local/include -Wl,-framework -Wl,CoreFoundation -I/opt/local/include -D_THREAD_SAFE -Wl,-framework -Wl,Cocoa -Wl,-framework -Wl,OpenGL -Wl,-framework -Wl,Cocoa
The point is to have Cocoa and OpenGL support. Depending on the way you installed SDL,
you might also need to include an SDL framework support, this is mostly if you installed SDL from
.dmg binary images, and not from source with the command line. A typical output of sdl-config --libs
is:
-L/opt/extra/lib -lSDLmain -lSDL -Wl,-framework,Cocoa
Another important issue is to include SDL.h
, which in turn includes SDLmain.h
, in
all the .c source files defining the standard main
function. This is done in liquidwar6 but
should you try to link yourself on liquidwar6 libraries and/or hack code, you must do this or
you’ll get errors when running the game. Such errors look like:
*** _NSAutoreleaseNoPool(): Object 0x420c90 of class NSCFNumber autoreleased with no pool in place - just leaking
The reason is that SDL replaces your main
with its own version of it. One strong implication
is that all the dynamic loading of SDL, which works on sandard GNU/Linux boxes, won’t work under
Mac OS X, since SDL hard codes itself by patching main
with #define
C-preprocessor commands.
A .dmg
file (disk image) containing a Liquid War 6.app
folder (OS X application)
is available for your convenience. It might work or not. In doubt, compile from source. The complicated part about this package (a “bundle” is OS X language) is that
it needs to embed various libraries which are typically installed in /opt
by MacPorts on a developper’s machine. So to build this package a heavy use
of the utilility install_name_tool
is required, normally all libraries
needed ship with the binary, remaining depedencies concern frameworks which
should be present on any working Mac OS X install. Still, this is only theory.
Needs to be widely tested.
The layout of the bundle follows:
./Contents/Info.plist
: metadata, bundle description file
./Contents/MacOS
: contains the main binary liquidwar6
as well as all specific low-level libraries
./Contents/Resources/data
: general game data, does not contain maps.
./Contents/Resources/music
: music for the game.
./Contents/Resources/map
: system maps, you can put your own maps (or “extra” maps) here if you want all users to share them.
./Contents/Resources/script
: Liquid War 6 specific scripts, the scheme scripted part of the program.
./Contents/Resources/guile
: common shared Guile scripts, part of Guile distribution.
./Contents/Resources/doc
: documentation in HTML and PDF formats.
Additionnally, the Mac OS X port uses /Users/<username>/Library/Application Support/Liquid War 6/
to store
configuration file, logs, etc. It does not use $HOME/.liquidwar6
like the default UNIX port.
The Mac OS X port also has a special behavior, in order to load some libraries with dlopen
(SDL_image does this with libpng and libjpeg) it needs to set DYLD_FALLBACK_LIBARY_PATH
to a
value that contains these libraries. This is typically in the bundle distributed on the disk image.
On a developper’s computer this problem does not appear for those libs are often in places like:
/usr/local/lib
/usr/X11/lib
/opt/local/lib
So the program sets DYLD_FALLBACK_LIBARY_PATH
(but not DYLD_LIBRARY_PATH
else
it breaks internal OS X stuff which relies, for instance, on libjpeg library that has the
same name but different contents) but it needs to do it before it is even run, else
the various dyld
functions do not acknowledge the change. That is, calling the C
function setenv()
, even before dlopen()
, has no effect. So the program
calls exec()
to re-run itself with the right environment variable. This is why,
on Mac OS X, there are two lines (exactly the same ones) displaying the program description
when it is started in a terminal.
This is not working yet, but there are good hopes that some day, Liquid War 6 can run on a GP2X console. This handled gaming device uses a Linux kernel on an ARM processor, does support most GNU packages through cross-compilation, and has basic SDL support.
To compile Liquid War 6 for GP2X, you first need to set up a working “toolchain”. It’s suggested you do this on a working GNU/Linux box. There are several solutions, the recommended one being Open2x. Read the online documentation on how to install Open2x.
Basically, the following should work:
mkdir /opt/open2x # check that you can write here svn co https://open2x.svn.sourceforge.net/svnroot/open2x/trunk/toolchain-new open2x-toolchain ./open2x-gp2x-apps.sh cd open2x-toolchain
Then, for your environment to be complete, you need to set up some environment variables. For instance:
export OPEN2X_SYSTEM_PREFIX=/opt/open2x/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux export GP2X_USER_PREFIX=$HOME/gp2x export CC=${OPEN2X_SYSTEM_PREFIX}/bin/arm-open2x-linux-gcc export CPP=${OPEN2X_SYSTEM_PREFIX}/bin/arm-open2x-linux-cpp export CXX=${OPEN2X_SYSTEM_PREFIX}/bin/arm-open2x-linux-g++ export AS=${OPEN2X_SYSTEM_PREFIX}/bin/arm-open2x-linux-as export CFLAGS=''-I${OPEN2X_PREFIX}/include -I${GP2X_USER_PREFIX}/include'' export CPPFLAGS=''-I${OPEN2X_PREFIX}/include -I${GP2X_USER_PREFIX}/include'' export CXXFLAGS=''-I${OPEN2X_PREFIX}/include -I${GP2X_USER_PREFIX}/include'' export LDFLAGS=''-L${OPEN2X_PREFIX}/lib -L${GP2X_USER_PREFIX}/lib'' export PATH=''${GP2X_USER_PREFIX}/bin:${OPEN2X_SYSTEM_PREFIX}/bin:$PATH''
In this setting, there’s a user $HOME/gp2x
directory which will
contain all the Liquid War 6 related libraries while the /opt/open2x
remains untouched.
Then you need to install the requirements. All these packages need to
be cross-compiled. To make things clear and non-ambiguous, even if you
have CC
set up in your environment variables, pass --build
and --host
arguments to the ./configure
script of all these
packages. A typical command is:
./configure --build=i686-pc-linux-gnu --host=arm-open2x-linux --prefix=${GP2X_USER_PREFIX}
Here’s the list of the requirements:
./configure --prefix=$GP2X_USER_PREFIX --build=x86_64-pc-linux-gnu --host=arm-open2x-linux --disable-pulseaudio --disable-video-directfb
--witout-threads
switch to the ./configure
script else it will try (and fail!) to run a test program. Liquid War 6 does
not use Guile threads, it does use threads but uses them “directly” outside
the Guile layer.
--build
and --host
for this one, they are
unsupported. Package compiles fine anyway.
Next, one needs to install a special version of SDL, which targets the GP2X specifically. This is not a generic SDL, and it does have limitations, which are related to the GP2X peculiar hardware. There are installation instructions about how to do this. The following should work:
cvs -d :pserver:anonymous@cvs.sourceforge.net:/cvsroot/open2x login # blank password cvs -d :pserver:anonymous@cvs.sourceforge.net:/cvsroot/open2x co libs-gp2x
Next: Coding guidelines, Previous: Core algorithm, Up: Hacker's guide [Contents][Index]