Cross-compiling a2x with MinGW for Windows

I do my game development on Linux, and use MinGW to cross-compile my C framework and games for Windows. I thought I'd write down the steps for setting everything up on a Debian-based OS. Tested on Linux Mint 18 and Ubuntu 16.10.


Install MinGW

1
$ apt install mingw-w64

This installs all the compilers and files needed to cross-compile 32 and 64bit Windows executables. Try it out:

1
2
3
4
5
6
7
8
$ whereis x86_64-w64-mingw32-gcc
x86_64-w64-mingw32-gcc: /usr/bin/x86_64-w64-mingw32-gcc

$ x86_64-w64-mingw32-gcc --version
x86_64-w64-mingw32-gcc (GCC) 5.3.1 20160211
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Back to top

Install Libraries

zlib

This one is available in the repos:

1
$ apt install libz-mingw-w64-dev

SDL and SDL_mixer

You can build SDL 2 from source (worth doing at least once), but for convenience I just grab the prebuilt MinGW dev libs from the official website:

You need to edit Makefile and change CROSS_PATH := /usr/local/cross-tools to CROSS_PATH := /usr, so that it points to where MinGW is installed. Then follow the instructions in INSTALL.txt:

1
2
$ cd SDL2-2.0.5/
$ sudo make cross

Follow the same steps to install SDL_mixer.

libpng

libpng does not provide prebuilt MinGW binaries so we need to build it from source. It only depends on zlib which we already installed, so this is painless.

First, download and install the source code package from libpng.org. Then, configure the build and install it.

For 32bit:

1
2
3
4
5
6
7
$ cd libpng-1.6.28/
$ ./configure --host=i686-w64-mingw32 \
              --prefix=/usr/i686-w64-mingw32 \
              CPPFLAGS=-I/usr/i686-w64-mingw32/include \
              LDFLAGS=-L/usr/i686-w64-mingw32/lib
$ make
$ sudo make install

For 64bit replace the i686 MinGW prefixes with x86_64:

1
2
3
4
5
6
7
$ cd libpng-1.6.28/
$ ./configure --host=x86_64-w64-mingw32 \
              --prefix=/usr/x86_64-w64-mingw32 \
              CPPFLAGS=-I/usr/x86_64-w64-mingw32/include \
              LDFLAGS=-L/usr/x86_64-w64-mingw32/lib
$ make
$ sudo make install

You can confirm that the library is where it should be:

1
2
3
4
5
6
7
8
$ cd /usr/i686-w64-mingw32/lib
$ ls -lh *png*
-rw-r--r-- 1 root root 881K Mar 14 12:04 libpng16.a
-rwxr-xr-x 1 root root 157K Mar 14 12:04 libpng16.dll.a
-rwxr-xr-x 1 root root  948 Mar 14 12:04 libpng16.la
lrwxrwxrwx 1 root root   10 Mar 14 12:04 libpng.a -> libpng16.a
lrwxrwxrwx 1 root root   14 Mar 14 12:04 libpng.dll.a -> libpng16.dll.a
lrwxrwxrwx 1 root root   11 Mar 14 12:04 libpng.la -> libpng16.la

Back to top

Build a Test Program

Try building your regular SDL2 program with these Makefile additions, which will use the appropriate headers, libraries, and tools to produce a 64bit Windows exe:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
MINGW_ARCH = x86_64-w64-mingw32
MINGW_BIN = /usr/$(MINGW_ARCH)/bin

LDFLAGS += \
    $(shell $(MINGW_BIN)/sdl2-config --libs) \
    -lSDL2_mixer \
    -lpng \
    -lm \

CFLAGS += \
    $(shell $(MINGW_BIN)/sdl2-config --cflags) \

PREFIX := $(MINGW_ARCH)-

export CC      := $(PREFIX)gcc
export CXX     := $(PREFIX)g++
export AS      := $(PREFIX)as
export AR      := $(PREFIX)ar
export OBJCOPY := $(PREFIX)objcopy
export READELF := $(PREFIX)readelf
export STRIP   := $(PREFIX)strip

Runtime Libraries

You need to distribute the SDL, libpng, and zlib runtime DLLs along with your executable program, otherwise the program might not run on all users' systems. I grab known good copies from the same libsdl.org pages linked above.

Make sure to include the DLLs' readme files to comply with their licenses. All my projects come with a lib-readme/ folder with the texts for SDL, SDL_mixer, libpng, and zlib. I just copy this folder to everything I release, it's not tedious and you're doing the right thing.

Back to top