Fork me on GitHub

Cross-compiling for windows (from Linux) - Part 2

*Update 2014-11-18*

I've uploaded a script (crosscompile_libs.sh) that simplifies the process of cross-compiling the libraries. Usage is described in the scons-x-compile repository's README.md

In part 1, I covered a basic cross-compilation setup, that let us use any of the libraries that come as part of the mingw-w64-x86-64-dev package:

Part 1:
  • Install the mingw cross-compilation tools.
  • Compile hello_world.exe.
  • A SCons based build system, that will be used in part 2.

In this part two, I'll cover how to:

Part 2:
  • Cross-compile SDL2. Cross-compile a program that links to, and initializes SDL2.
  • Repeat the process for similar libraries:
    • SDL2_image, together with libjpg and libpng.
    • SDL2_mixer, with libogg and libvorbis
    • SDL2_ttf, with libfreetype
    • GLEW

A quick word about cross-compiled libraries

Libraries used when cross-compiling also need to be cross-compiled.

For example, you probably use <cmath> functions on Linux, and link to the shared libm.so or static libm.a library file. For cross-compilation, you want to link to a static cross-compiled libm.a (shared libraries for cross-compilations are a pita, so I'll avoid it altogether).

How do we get these static cross-compiled libraries? Lucky for us, the mingw-w64-x86-64-dev package provides many fundamental libraries.

On my system, these are located in /usr/x86_64-w64-mingw32/lib/. If you find that libm.a is located there, then you can link with it without any fuss. When building your project, it is not necessary to specify this directory, as x86_64-w64-mingw32-g++ will look for libraries here by default.

The important thing to note is that all the static libraries you link to will become part of the .exe, which ends up being a large file.

1. Building a cross-platform SDL2 library

As mentioned above, the mingw-w64-x86-64-dev package provides many fundamental libraries. This is great, but for all other libraries, you typically need to find these elsewhere, or build them yourself. I'm only interested in the latter. First off, Simple DirectMedia Layer (SDL).

SDL2 can be built using autotools, i.e. configure && make && make install.

Autotools has very good support for cross-compiling, which makes this easy. Typically, we just need to tell configure that we want to use the x86_64-w64-mingw32 toolchain.

I'll be placing all cross-compiled libraries we build in:

1.1 Building a cross-platform SDL2 library

In the SDL2 source repository, we'll create a directory build-win64, and from there call configure with the cross-compilation configuration set. Pay attention to features the configure output might warn you about. In my case, it all looked good, so I went ahead with a make install.

From the SDL2 directory:

You should now find libSDL2.a and libSDL2main.a in the $PREFIX/$TOOLSET/lib directory you used.

1.2 Hello_SDL.exe

In part 1, I described a SCons based build setup for cross-compilation. We want to use this to build a simple program that uses SDL2.

To check out the SCons setup, and this program, use (note the hello-sdl branch):

Here is a simple program that initializes SDL2, outputs version information, creates a small window, and waits for the user to exit.

If you have checked out the example code, you can build a windows execuable with scons --win64. I won't go into much detail on how it is compiled. If it doesn't work, and utils/windows_build.py and utils/linux_build.py doesn't make sense, shoot me an email.

The Linux SCons build requires that sdl2-config is in the $PATH variable. The windows build assumes that the cross-compiled SDL2 library is in: /usr/local/cross-tools/x86_64-w64-mingw32/

The only important difference from what sdl2-config suggests (the one corresponding to the cross-compiled SDL2), is that I omit the -mwindows flag. With this flag set, a console window isn't created. Although very nice for a release, I want to see the standard output, so I won't use this flag.

Linux output
Windows output

2. Building a cross-platform SDL2_image library

We want to build a cross-platform version of SDL2_image with jpeg and png support. This means we have to first build libpng and libjpeg. Also, libpng requires zlib. Will compile these three first.

2.1 Cross-compiling zlib

Static library libz.a should now be in $CROSSPATH/lib

2.2 Cross-compiling libpng

Static library libpng.a should now be in $CROSSPATH/lib

2.3 Cross-compiling libjpeg

Static library libjpeg.a should now be in $CROSSPATH/lib

2.4 Cross-compiling SDL2_image

From the SDL2_image source directory:

Static library libSDL2_image.a should now be in $CROSSPATH/lib

2.5 Hello_SDL_image.exe

An example program with SCons build setup can be checked out with:

3. Building a cross-platform SDL2_mixer library

For the SDL2_mixer, I won't bother with .mp3 support, since I prefer the better ogg format. For this we need both libogg and libvorbis. I'll show how to cross-compile both.

3.1 Cross-compiling libogg

Static library libogg.a should now be in $CROSSPATH/lib

3.2 Cross-compiling libvorbis

Static library libvorbis.a and libvorbisfile.a should now be in $CROSSPATH/lib

3.3 Cross-compiling SDL2_mixer

From the SDL2_mixer source directory:

Static library libSDL2_mixer.a should now be in $CROSSPATH/lib

3.4 Hello_SDL_mixer.exe

An example program with SCons build setup can be checked out with:

The program should list which sound and music decoders it has available. On my Linux machine, the (relevant) output is:

On my virtual Windows7 machine:

4. Building a cross-platform SDL2_ttf library

As with previous libraries, SDL2_ttf has a dependency. In this case, libfreetype. It also depends on libpng, but I assume you are following this article in order, and already have that available.

4.1 Cross-compiling libfreetype

Static library libfreetype.a should now be in $CROSSPATH/lib

4.2 Cross-compiling SDL2_ttf

From the SDL2_ttf source directory:

Static library libSDL2_ttf.a should now be in $CROSSPATH/lib

4.3 Hello_SDL_ttf.exe

An example program with SCons build setup can be checked out with:

4. Building a cross-platform GLEW library

In order to make OpenGL function calls, we use a helper library for figuring out which functions are supported by the graphics card, based on a system of extensions. One such helper library is GLEW.

Static library libglew32.a should now be in $CROSSPATH/lib

5. Hello_OpenGL.exe

Let's put everything together into a program that uses and initializes SDL2, SDL2_image, SDL2_mixer, SDL2_ttf, and OpenGL through GLEW. For OpenGL creation, it should try to find the highest version that it can create a context for.

You can check out and compile this example with:

The example tries to create an OpenGL 4.4 context, if that fails, it tries a 4.3 context, then 4.2 and so on. After it creates an OpenGL context, it initializes GLEW.

The version of the created context, together with graphics driver information, extensions found, etc, are sent to the standard output.

Linux output
Windows output