Setting up the new Windows bash to cross compile a Simple DirectMedia Library (SDL2) application

Preface

I’ve preferred using a linux environment to develop C/C++ applications for a long while. It’s only been for hobby projects so far so I’ve never really worked out the kinks trying to cross compile my applications to windows on linux.

Windows 10 recently began cooperating with Canonical in bringing the linux kernel to windows. With a few settings, you’re now able to run Bash on your Windows 10! It seems too good to be true, but it actually works. You get a well working Ubuntu 14.04 LTS where you can run pretty much anything compiled for linux. They altered the windows kernel to allow the linux kernel to do its thing, rather than placing it in a VM.

So I no longer need to dual boot linux every time I feel like writing a few lines of code. There’s no hassle with a VM not getting proper graphics hardware acceleration either. I can simply flip up cmd, type “bash” and I’m in linux.

Time to get that cross compiling to work!

Initial linux

First off, we’ll just setup the environment. We’ll want some build tools to get going. An editor like VIM is optional, since this environment isn’t sandboxed and you can access the files via your windows’ file explorer.

sudo apt-get install vim git mercurial build-essential mingw-w64

build-essential will install GCC and its standard libraries and some other handy build tools.

mingw-w64 gives you a GCC version that compiles for windows, including a few windows specific libraries and headers. It’ll add two gcc and g++ compilers prefixed with i686-w64-mingw32- and x86_64-w64-mingw32- for 32bit and 64bit respectively.

mercurial will be used to grab the SDL 2 source.

git to use my example project.

The cmake version in apt-get is rather old as well, so I got the latest version from cmake.org.

wget https://cmake.org/files/v3.6/cmake-3.6.3-Linux-x86_64.sh
sudo sh cmake-3.6.3-Linux-x86_64.sh --prefix=/opt/cmake

You’ll have to add /opt/cmake/bin to your env PATH.
export PATH=/opt/cmake/bin:$PATH
Add it to your ~/.profile as well by adding the line PATH="/opt/cmake/bin:$PATH" to it.

Graphical applications via bash

There’s no official support for graphical applications in the new Windows bash, but you can get an X server to run on your Windows quite easily.

Install Xming and start it. You probably need to run export DISPLAY=:0 in bash and add the same line to your ~/.bashrc.

To try it out, do sudo apt-get install mesa-utils and then run glxgears. A small window with a set of gears in 3D should pop up.

You won’t get a very up-to-date driver, so don’t expect anything beyond OpenGL 2.1 or even that. I’ve been unable to get SDL2 to select an accelerated driver even though the glxgears run and the glxinfo | grep version shows OpenGL 2.1. You’ll still get the SDL2 software renderer to work fine. There’s a mesa version of Xming, but it made no difference.

Setup SDL 2 in Linux for cross compiling to Windows

The libsdl2-dev package in apt-get is unfortunately not of much use to us, since it doesn’t come with a CMake find file or any windows compiled libraries (obviously).

Actually, it’s fine to use apt-get and avoid compiling SDL2 all together. I’ve described how in this follow up post.

We’ll download the source and install it via the makefiles instead. Start by downloading the source code to a directory of your choice, with hg clone http://hg.libsdl.org/SDL. Described on libsdl.org.

Linux SDL

cd SDL && mkdir build && cd build to prepare a good location to configure and build SDL.

The regular linux SDL is easy enough to configure. Just run ../configure --prefix=/usr. The lib/ and include/ directories are located under /usr/, so that’s where we want SDL to go.

When that’s done run make -j6 (-j6 use more threads) and finally sudo make install.

SDL for windows

Let’s create another directory parallel to the previous build/.

cd ../ && mkdir build-w64 && cd build-w64

The configuration for windows will require a few extra flags.

../configure \
--prefix=/usr/i686-w64-mingw32 \
--build=i686-unknown-linux-gnu \
--host=i686-w64-mingw32

The prefix leads to where mingw-w64 installed the 32bit w64 compiler and we specify the --host as such as well.

Running make -j6 and then sudo make install sets it all up.

Replace i686 with x86_64 for 64bit builds.

The SDL application

I created an example project hosted on github for convenience. It was a bit too much to fill the blog post with it.

Have a look at main.cpp. It’s a pretty straightforward SDL example which will create a small window and clear it with a nice turquoise color.

The CMakeLists.txt is also rather basic.  Of note is the -static-libgcc -static-libstdc++ flags. Leaving these out requires that you locate the appropriate .dll:s and distribute them with your application.

The find_package(SDL2 REQUIRED) will use the cmake find files generated by SDL’s install scripts to locate the correct libraries and headers.

Finally there’s the toolchain for the cross compilation, specifying the mingw-w64 compiler and prefixes.

Go ahead and clone the project git clone git@github.com:Zoomulator/SDLCrossCompileExample.git to where you want it.

Compiling for Linux

cd SDLCrossCompileExample && mkdir build && cd build

Just run cmake ../ and it should locate everything. Then make to compile. Hopefully all is good and you can now run ./main and see that your SDL application, compiled in Linux, runs in Linux via your Windows 10!

Compiling for Windows

cd SDLCrossCompileExample && mkdir w64-build && cd w64-build

For this build, we’ll only have to specify the correct tool chain. Run cmake -DCMAKE_TOOLCHAIN_FILE=../Toolchain-Ubuntu-mingw32.cmake ../ and it’ll now locate the compiler and libraries in /usr/i686-w64-mingw32/ instead.

Now make and it should hopefully be happy to build it.

Before we run, we’ll have to nab some DLLs. libwinpthread-1.dll should be in the /usr/i686-w64-mingw32/lib directory, so copy that next to your main.exe.

I could unfortunately not get the cross compilation to generate the SDL2.dll file, so you’ll have to grab the runtime binary zip for Windows at libsdl.org. Unpack it and copy the SDL2.dll next to your main.exe.

That’s it! Your main.exe should now run if you double click it in windows.

Final thoughts

It turned out to be quite simple once I figured it out, but the road there wasn’t easy. That’s why this entry exists, so I wont forget until next time. I hope that I took sufficient notes and made the right assumptions so that this entry actually reproduces the right steps. It’s sometimes difficult to keep track of all the things you do while trying to get something to work. If anyone has trouble following this, leave a comment and I’ll try to help out.

If anyone figures out how  to make mingw64 build the SDL2.dll, let me know. I’d like my final CMake setup to copy that dll as part of the distribution build.

Advertisements

One thought on “Setting up the new Windows bash to cross compile a Simple DirectMedia Library (SDL2) application

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s