CrossCompileWithAudio - hpgDesigns/hpgdesigns-dev.io GitHub Wiki

Introduction

This page discusses how to cross-compile games from Linux to Windows using ENIGMA. This is useful for developers whose primary build environment is Linux, or for those who have trouble with the limitations of MinGW+ENIGMA on Windows (32-bit, slow, etc.). It differs from the previous guide (Cross compiling) by providing a step-by-step walkthrough, and by having mostly functioning audio rather than audio:none.

Note that mp3s still won't work, for reasons that are unclear to me (mpg123 is detected by alure, so...).

Step One: Build Tools and Environment setup

On an Ubuntu derivative, install the following. Other distros will have to track down their own versions of each tool, but these should be relatively easy to find.

sudo apt-get install mingw-w64 cmake wget

MinGW, unfortunately, is missing a lot of the libraries that ENIGMA needs. So we will build these libraries ourselves and install them in /home/USER/mingw-root, where USER is your username.

mkdir ~/mingw-root
mkdir ~/mingw-root/source

Some libraries (cough! zlib) have very limited configure scripts. So we need a special script to force those libraries (cough! only zlib) to compile for a different host:

cd ~/mingw-root/source
gedit mingw-force-host

Paste the following into this new file:

#!/bin/sh
PREFIX=x86_64-w64-mingw32
export CC=$PREFIX-gcc
export CXX=$PREFIX-g++
export CPP=$PREFIX-cpp
export RANLIB=$PREFIX-ranlib
export PATH="/usr/x86_64-w64-mingw32/bin:$PATH"
exec "$@"

Then, save, close and:

chmod a+x mingw-force-host

CMake also needs a special toolchain file:

cd ~/mingw-root/source
gedit Toolchain-mingw32.cmake

Paste the following into this file:

# the name of the target operating system
SET(CMAKE_SYSTEM_NAME Windows)

# which compilers to use for C and C++
SET(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc)
SET(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++)
SET(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)

# here is the target environment located
SET(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32  ~/mingw-root)

# adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search
# programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

Save and close. We're ready to start! ...compiling libraries!

Step Two: Compiling Dependencies

We'll build the most annoying library first.

Zlib

cd ~/mingw-root/source
wget http://zlib.net/zlib-1.2.8.tar.gz
tar xvf zlib-1.2.8.tar.gz
cd zlib-1.2.8
../mingw-force-host ./configure --static
../mingw-force-host make
DESTDIR=$HOME/mingw-root ../mingw-force-host make install

LibFFI

cd ~/mingw-root/source
wget ftp://sourceware.org/pub/libffi/libffi-3.1.tar.gz
tar xvf libffi-3.1.tar.gz
cd libffi-3.1
./configure --host=x86_64-w64-mingw32 --prefix=$HOME/mingw-root/usr/local
make
make install

For some reason, libffi thinks it's special, so don't forget to do this:

mv $HOME/mingw-root/usr/local/lib/libffi-3.1/include/* $HOME/mingw-root/usr/local/include/
rm -r $HOME/mingw-root/usr/local/lib/libffi-3.1

libOGG

cd ~/mingw-root/source
wget http://downloads.xiph.org/releases/ogg/libogg-1.3.2.tar.gz
tar xvf libogg-1.3.2.tar.gz
cd libogg-1.3.2
./configure --host=x86_64-w64-mingw32 --prefix=$HOME/mingw-root/usr/local CPPFLAGS="-I$HOME/mingw-root/usr/local/include" LDFLAGS="-I$HOME/mingw-root/usr/local/lib"
make
make install

libFLAC

cd ~/mingw-root/source
wget https://svn.xiph.org/releases/flac/flac-1.3.0.tar.xz
tar xvf flac-1.3.0.tar.xz
cd flac-1.3.0
./configure --host=x86_64-w64-mingw32 --prefix=$HOME/mingw-root/usr/local CPPFLAGS="-I$HOME/mingw-root/usr/local/include" LDFLAGS="-I$HOME/mingw-root/usr/local/lib"
make
make install

libModPlug

cd ~/mingw-root/source
wget http://jaist.dl.sourceforge.net/project/modplug-xmms/libmodplug/0.8.8.5/libmodplug-0.8.8.5.tar.gz
tar xvf libmodplug-0.8.8.5.tar.gz
cd libmodplug-0.8.8.5
./configure --host=x86_64-w64-mingw32 --prefix=$HOME/mingw-root/usr/local CPPFLAGS="-I$HOME/mingw-root/usr/local/include" LDFLAGS="-I$HOME/mingw-root/usr/local/lib"
make
make install

libMPG123

cd ~/mingw-root/source
wget http://jaist.dl.sourceforge.net/project/mpg123/mpg123/1.20.1/mpg123-1.20.1.tar.bz2
tar xvf mpg123-1.20.1.tar.bz2
cd mpg123-1.20.1
./configure --host=x86_64-w64-mingw32 --prefix=$HOME/mingw-root/usr/local CPPFLAGS="-I$HOME/mingw-root/usr/local/include" LDFLAGS="-I$HOME/mingw-root/usr/local/lib"
make
make install

libsndfile

cd ~/mingw-root/source
wget http://www.mega-nerd.com/libsndfile/files/libsndfile-1.0.25.tar.gz
tar xvf libsndfile-1.0.25.tar.gz
cd libsndfile-1.0.25
./configure --host=x86_64-w64-mingw32 --prefix=$HOME/mingw-root/usr/local CPPFLAGS="-I$HOME/mingw-root/usr/local/include" LDFLAGS="-I$HOME/mingw-root/usr/local/lib"
make
make install

This is the first library that might fail to build. If it builds, your path is probably set up correctly.

libvorbis

cd ~/mingw-root/source
wget http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.4.tar.gz
tar xvf libvorbis-1.3.4.tar.gz
cd libvorbis-1.3.4
./configure --host=x86_64-w64-mingw32 --prefix=$HOME/mingw-root/usr/local CPPFLAGS="-I$HOME/mingw-root/usr/local/include" LDFLAGS="-I$HOME/mingw-root/usr/local/lib"
make
make install

Another library that might complain if your headers aren't in the right place.

OpenAL

cd ~/mingw-root/source
wget http://kcat.strangesoft.net/openal-releases/openal-soft-1.16.0.tar.bz2
tar xvf openal-soft-1.16.0.tar.bz2
cd openal-soft-1.16.0
PKG_CONFIG_PATH=$HOME/mingw-root/usr/local/lib/pkgconfig  cmake -DCMAKE_TOOLCHAIN_FILE=../Toolchain-mingw32.cmake -DCMAKE_INSTALL_PREFIX=$HOME/mingw-root/usr/local -DCMAKE_PREFIX_PATH=$HOME/mingw-root/usr/local  .
make
make install

Double-check the output of configure and of make.

libAlure

cd ~/mingw-root/source
wget http://kcat.strangesoft.net/alure-releases/alure-1.2.tar.bz2
tar xvf alure-1.2.tar.bz2
cd alure-1.2
PKG_CONFIG_PATH=$HOME/mingw-root/usr/local/lib/pkgconfig  cmake -DCMAKE_TOOLCHAIN_FILE=../Toolchain-mingw32.cmake -DCMAKE_INSTALL_PREFIX=$HOME/mingw-root/usr/local -DCMAKE_PREFIX_PATH=$HOME/mingw-root/usr/local  .
make
make install

Again, make sure everything's configured correctly (configure) and builds (make) without error.

Configuring ENIGMA

Most of ENIGMA is already set to build with MinGW, but a few things will need changing. First, open up the directory where you installed ENIGMA, and find Compilers/Linux/MinGW64.ey. Make sure your cxxflags, cflags, and ldflags look like this:

cxxflags: -I../Additional/x86_64-w64-mingw32/include  -I/home/USER/mingw-root/usr/local/include  -I/home/USER/mingw-root/usr/local/include/AL
cflags:
ldflags: -L/home/USER/mingw-root/usr/local/lib  -static-libgcc  -static-libstdc++

Here, /home/USER/ is your home directory --our magic $HOME variable trick won't work here because ENIGMA eats the $H.

Also, in ENIGMAsystem/SHELL/Platforms/Win32/Makefile, change the following:

#Find:
LDLIBS += -lffi -lcomdlg32 -lgdi32 -lwinmm -lwininet

#Change to:
LDLIBS += -lcomdlg32 -lgdi32 -lwinmm -lwininet

Finally, in ENIGMAsystem/SHELL/Makefile:

#Find:
compile_game: $(OBJECTS) $(RCFILES) $(RESOURCEBINARY) $(DEPENDENCIES)
    $(CXX) $(LDFLAGS) -o "$(OUTPUTNAME)" $(OBJECTS) $(RESOURCEBINARY) $(LDLIBS)
    @echo Built to "$(OUTPUTNAME)"

#Change to:
compile_game: $(OBJECTS) $(RCFILES) $(RESOURCEBINARY) $(DEPENDENCIES)
    $(CXX) $(LDFLAGS) -o "$(OUTPUTNAME)" $(OBJECTS) $(RESOURCEBINARY) $(LDLIBS) /home/USER/mingw-root/usr/local/lib/libffi.a
    @echo Built to "$(OUTPUTNAME)"

Again, make sure you replace /home/USER/ with your actual home directory. These changes force libffi to link statically, which means one less DLL to distribute with your game.

Building your game

We're ready to build! Open ENIGMA like you normally would, and open your game. Now, open the "Enigma Settings" tab in your project, and change to the tab labeled "Api". In there, change the "Compiler" to "Mingw64". This will force the "Widgets" setting to change, so change "Widgets" back to "None" and then click Ok. (If you can figure out how to get widgets working, let me know.)

Now, click the "Run" button and wait for the game to compile. It will almost certainly not run, but you will see that the compilation process succeeds, producing a game labeled something like /tmp/egmXXXX.tmp. Now, do the following:

cd ~/Desktop
cp  /tmp/egm6806756291195138228.tmp game.exe
cp /usr/x86_64-w64-mingw32/lib/libwinpthread-1.dll .

The third line copies the pthreads library which cannot (I think) be linked statically. You will have to distribute it with your game. Now you can run your game in Wine:

cd ~/Desktop
wine ./game.exe

...or you can copy it over to your Windows partition and run it there. Note that you will need the pthreads dll too.

Limitations

For now, mp3 doesn't work, so I probably messed up something with one of the various libraries. Games may also crash; YMMV.