Setting up MinGW32 on Ubuntu

Finally, a non-controversial topic :)

Having a cross-compiler that can compile Windows executables on a Linux machine can be an extremely useful tool to have, since it prevents you from having to install WINE or a virtual machine just to generate Windows executables for your software project. I find myself often in need of such a tool, and since there doesn't seem to be any up-to-date tutorial on how to set up a MinGW32 cross-compiler, I decided to write one. :)

Okay, so here we go: First, install the gcc-mingw32 package with the following command:

sudo apt-get install gcc-mingw32

And we're basically finished. To use your newly-installed cross-compiler, use the following command:

As a final finishing touch, I add a soft link that allows me to access my new cross-compiler with shorter name, like so:
ln -s $(which i586-mingw32msvc-gcc) gcc-mingw32

If you execute that command in your $HOME/bin directory (assuming, of course, that that directory is on your $PATH), you can access your cross-compiler via gcc-mingw32 instead of the longer i586-mingw32msvc-gcc.

Let's test our cross-compiler on a simple piece of software: Lua 5.1. I'll assume you've already unpacked Lua into some convenient directory, and have opened a terminal there. I'll also assume you made the soft link I talked about earlier, but that's no big deal - if you didn't, just replace gcc-mingw32 with i586-mingw32msvc-gcc.

Lua makes things easy on us by having 99% of the compiler options already set up for us; we just have to tell it where to find our cross-compiler - otherwise, it will find the non-cross-compiling installation of GCC:
make mingw CC=gcc-mingw32

That wasn't too hard either. :) Here's what that command outputs on my system:
cd src && make mingw
make1: Entering directory /home/(my username)/Downloads/lua-5.1/src'<br/>make "LUA_A=lua51.dll" "LUA_T=lua.exe" \<br/>"AR=gcc-mingw32 -shared -o" "RANLIB=strip --strip-unneeded" \<br/>"MYCFLAGS=-DLUA_BUILD_AS_DLL" "MYLIBS=" "MYLDFLAGS=-s" lua.exe<br/>make2: Entering directory/home/(my username)/Downloads/lua-5.1/src'
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o lua.o lua.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o lapi.o lapi.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o lcode.o lcode.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o ldebug.o ldebug.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o ldo.o ldo.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o ldump.o ldump.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o lfunc.o lfunc.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o lgc.o lgc.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o llex.o llex.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o lmem.o lmem.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o lobject.o lobject.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o lopcodes.o lopcodes.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o lparser.o lparser.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o lstate.o lstate.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o lstring.o lstring.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o ltable.o ltable.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o ltm.o ltm.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o lundump.o lundump.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o lvm.o lvm.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o lzio.o lzio.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o lauxlib.o lauxlib.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o lbaselib.o lbaselib.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o ldblib.o ldblib.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o liolib.o liolib.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o lmathlib.o lmathlib.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o loslib.o loslib.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o ltablib.o ltablib.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o lstrlib.o lstrlib.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o loadlib.o loadlib.c
gcc-mingw32 -O2 -Wall -DLUA_BUILD_AS_DLL -c -o linit.o linit.c
gcc-mingw32 -shared -o lua51.dll lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o lstrlib.o loadlib.o linit.o
strip --strip-unneeded lua51.dll
gcc-mingw32 -o lua.exe -s lua.o lua51.dll -lm
make2: Leaving directory /home/(my username/Downloads/lua-5.1/src'<br/>make1: Leaving directory/home/(my username/Downloads/lua-5.1/src'

Hey, looked like it worked. Let's try running our new executable with WINE:
wine src/lua.exe
fixme:advapi:RegisterTraceGuidsW (0x100778a, 0x100a060, {485e7de8-0a80-11d8-ad15-505054503030}, 1, 0x33fe00, (null), (null), 0x100a068,): stub
fixme:advapi:RegisterTraceGuidsW (0x100778a, 0x100a080, {485e7de9-0a80-11d8-ad15-505054503030}, 1, 0x33fe00, (null), (null), 0x100a088,): stub
fixme:advapi:RegisterTraceGuidsW (0x100778a, 0x100a0a0, {485e7dea-0a80-11d8-ad15-505054503030}, 1, 0x33fe00, (null), (null), 0x100a0a8,): stub
fixme:advapi:RegisterTraceGuidsW (0x100778a, 0x100a0c0, {485e7deb-0a80-11d8-ad15-505054503030}, 1, 0x33fe00, (null), (null), 0x100a0c8,): stub
fixme:advapi:RegisterTraceGuidsW (0x100778a, 0x100a0e0, {485e7dec-0a80-11d8-ad15-505054503030}, 1, 0x33fe00, (null), (null), 0x100a0e8,): stub
fixme:advapi:RegisterTraceGuidsW (0x100778a, 0x100a100, {485e7ded-0a80-11d8-ad15-505054503030}, 1, 0x33fe00, (null), (null), 0x100a108,): stub
fixme:win:RegisterDeviceNotificationW (hwnd=0x14fae8, filter=0x65e93c,flags=0x00000001) returns a fake device notification handle!
Lua 5.1 Copyright (C) 1994-2006, PUC-Rio

And there you have it: We went step-by-step through the process of installing MinGW32, adding a convenience soft link, and compiling a simple piece of software - Lua.

Happy cross-compiling!