Cross-Compile
Cross-Compile from Linux to Windows
In this article we will cross-compile UFO:AI in a Debian chroot environment to Windows, using MingW64_64 (64bit).
We chose a chroot environment, as it kind of standardizing the build environment and fairly cheap to build. You can achieve the same in Docker or other containerization techniques, but chroot just does its job.
Building the chroot
Prerequisites
For this step you will need:
- Debootstrap: Debootstrap is a program that can fetch and construct a Debian-like filesystem. This is the only software you need to install on your system. It is available on all major distributions, if you are unsure, check it on Repology.
- Root access: You will need to be able to run commands as system administrator (`su` or `sudo`).
- Disk space: You will need around 7-10GiB free space for the cross-compilation.
- Internet access: You will need to download packages and libraries from the Internet.
Build
As root user, create a directory and call `debootstrap` to build the root filesystem into that. We are using /ufoai.xcompile in this example, but use any path you like!
mycomputer ~ # mkdir /ufoai.xcompile mycomputer ~ # debootstrap stable /ufoai.xcompile ...
Mount the pseudo-filesystems:
mycomputer ~ # mount --bind /dev /ufoai.xcompile/dev mycomputer ~ # mount --bind /dev/pts /ufoai.xcompile/dev/pts mycomputer ~ # mount --bind /proc /ufoai.xcompile/proc mycomputer ~ # mount --bind /sys /ufoai.xcompile/sys
If you plan to keep this environment permanent you can also move these mountings to `/etc/fstab` of your host machine.
It is a good idea to make it clear when you're in the chroot environment via the prompt:
mycomputer ~ # echo "export PS1='\\u@chroot:\\w \\\$ '" >> /ufoai.xcompile/root/.bashrc mycomputer ~ # echo "export PS1='\\u@chroot:\\w \\\$ '" >> /ufoai.xcompile/etc/skel/.bashrc
Enter
Entering chroot is just a command:
mycomputer ~ # chroot /ufoai.xcompile root@chroot:/ #
Dependencies and build tools
To make step easier, we built a Bash (v4.0+) script contrib/scripts/cross-env.sh
to prepare the chroot for building UFO:AI.
It installs the mingw cross-compiler and other tools, downloads necessary libraries and compiles them.
root@chroot:/development/ufoai.git # contrib/scripts/cross-env.sh
Please note that the script currently misses requirements of the UFORadiant map editor. Some optional dependencies are also missed, like video playing support and backtraces
Cross-Compiling UFO:AI
Check out the source code if you haven't done yet Getting the source. Enter the directory and run configure.
root@chroot:/development/ufoai.git # ./configure --target-os=mingw64_64 ... Build modules: Build cgame-campaign Build cgame-multiplayer Build cgame-skirmish Build game Build testall Build ufo Build ufo2map Build ufoded Build ufomodel Disable uforadiant - Gtk2 missing - GtkGL missing
Consider adding configure options as needed:
- --enable-release
- --prefix
- --datadir
- --libdir
- --localedir
- --bindir
Read more on command-line options in the configure script's help.
root@chroot:/development/ufoai.git # ./configure --help
To compile the game, run its make target.
root@chroot:/development/ufoai.git # make -j 4 ufo
The Unit-test suite testall is a bit special, as it requires ufo2map and its test maps to be compiled. However in a Linux cross-compile environment, you cannot run ufo2map.exe (without help, like wine). If you just want to compile the test suite, a workaround is compiling ufo2map.exe, then creating empty files for the compiled maps, then compiling the test suite. The order matters as make check file timestamps for dependency resolution.
root@chroot:/development/ufoai.git # make -j 4 ufo2map root@chroot:/development/ufoai.git # touch unittest/maps/test_game.bsp root@chroot:/development/ufoai.git # touch unittest/maps/test_reverse_door.bsp root@chroot:/development/ufoai.git # touch unittest/maps/test_routing.bsp root@chroot:/development/ufoai.git # make -j 4 testall
As mentioned before UFORadiant needs more work, as it needs the whole Gtk2+ eco-system.
needed DLLs
To run the game we need to pack the dynamically linked DLLs into the game. My tests suggested these are:
- base/game.dll (of course, the battlescape engine)
- libcurl-x64.dll
- libgcc_s_seh-1.dll
- libiconv-2.dll
- libintl-8.dll
- libjpeg-62.dll
- libstdc++-6.dll
- libwinpthread-1.dll
- SDL2.dll
- SDL2_mixer.dll
- SDL2_ttf.dll
- zlib1.dll