Blog Post

Surviving the Windows Wilds

Patrick Galbraith Published

When I first started developing software, it was always my intent to write Windows software. I remember buying Borland C++ at the college bookstore and started trying to get familiar with the Windows API. Then of course a friend of mine told me about this new OS called Linux. The very next weekend, I spent hours downloading Linux-- all 26 or so floppies onto my Packard Bell. To make a long story short, I have been immersed in the Linux world for the past 17 years.

More recently, at NorthScale, we've wanted to add support for memcached - particularly the NorthScale Memcached Server - on Windows. So, I've become well-acquainted not only with Windows, but also the Mingw compiler and the Msys *NIX-like environment.

Windows has changed a lot since I last used it. I remember the days when you had to be adept at editing configuration files such as windows.ini, config.sys, autoexec.bat-- particularly tweaking memory-management. As a UNIX guy, I have to say, Windows has come a long way. Particularly the most recent versions of Windows. It's interesting to come back to something you haven't used in a long time, a bit like stepping out of a time machine.

For building memcached, we use the Mingw cross-compiler. What is Mingw? Mingw is a contraction of "Minimalist GNU for Windows", the GNU compiler suite which includes pretty much anything you need to build Windows executables. Not only that, it is possible to cross-compile Windows binaries on Linux or other *NIXs with Mingw using mingw. Since we have some pieces that are Windows-only,we perform our builds on Windows.

One might ask, why not use Microsoft compilers? This is because the requirement and goal of the memcached source project to adhere to C99. This is a point I've noticed there are some strong feelings about. I've found some people to claim C99 isn't important. Well, for memcached, it is, so I use what will work for our needs. The other requirement or goal we try to achieve is to have the fewest number of changes to the memcached source in order facilitate support for Windows. So often-- and I have seen this in other projects-- is source code littered with pre-compiler ifdef complexities. This is what we want to avoid.

The other piece in this pie is Msys. Msys is a contraction of "Minimal System", this being the minimal set of tools to allow you to have *NIX command line environment. Since we use Git as our source code management tool, the Msysgit project has not only a more up to date Msys, but git packaged in. Also, for 32-bit Windows, Msysgit already has Mingw included.

Setting up Mingw and Msys

To set up Mingw and Msys, it depends on whether you use Windows 64-bit or 32-bit. For 32-bit, you can install Msysgit and have everything you need. For 64-bit Windows, you install Msysgit then you install the 64-bit port of Mingw, Mingw-w64.

Installing Msysgit

Msysgit can be found at http://code.google.com/p/msysgit/. For our needs, we select the "fullinstall" executable installer. Once downloaded, you simply need to run the downloaded executable. The installer will compile Msys in c:\msysgit\msysgit. Once installed, from bash, this directory structure will be /c/msysgit/msysgit, which the path is the same as /. You'll notice that upon installing Msysgit that Git is compiled at the same time, then finally you are presented with a bash shell terminal window. The first thing I recommend doing is running the tcl script (from the bash terminal window) to add shortcuts to your desktop and/or menu:

/share/msysGit/add-shortcut.tcl

This will display the options available to this useful script.

Installing Mingw-w64

For 64-bit Windows, you will need to install mingw-w64. You can find zipped archive for Mingw-w64 at http://sourceforge.net/mingw-w64 mingw-w64-1.0-bin_i686-mingw_YYYYMMDD.zip. Extract this file into C:\ (/c/).

Adding Paths to Your System

You will need to add PATH environment variable to include both the path to mingw and msysgit binaries AND libraries. Under Windows, environment variables use %NAME%, eg: %PATH%. Also, the path separation character in Windows is a semi-colon as opposed to a colon. To edit your PATH, do the following:

Control Panel ->
System ->
Advanced ->
Environment Variables ->
Path (click to edit)

Add the following to the existing PATH:

c:\mingw\bin;c:\msysgit\msysgit\bin;c:\msysgit\msysgit\local\bin;c:\msysgit\msysgit\mingw\bin;

Another thing to know on Windows is that the library load path is simply %PATH% ($PATH).

Compiling Code with Mingw

At this point, you should have a functional system, enough so that you can compile code and produce windows executables. Also, you will have the ability to work on your Windows system using the *NIX tools you know and love!

For compiling code on win32, simply running compiles the way you do on Linux should work out of the box. Take for instance the network library, Libevent. To compile on win32 (Msysgit) you simply:

./configure
make
make install

However, for win64, because you have mingw-w64 installed, you need to specify some flags when running configure:

./configure --host=x86_64-w64-mingw32 --build=i686-pc-mingw32 --prefix=/usr

make

These flags take care of ensuring you get 64-bit libraries and executables. Once you run make, you'll compile lines such as:

/bin/sh ./libtool --tag=CC --mode=compile x86_64-w64-mingw32-gcc -DHAVE_CONFIG_H -I. -I./compat -I
./include -IWIN32-Code -g -O2 -Wall -fno-strict-aliasing -MT select.lo -MD -MP -MF .deps/select.T
po -c -o select.lo select.c

If you look in the Mingw-w64 executable directory, /c/mingw/bin, you'll see why specifying the flags are needed-- all the binaries are prefixed with "compile x86_64-w64-mingw32". Specifying the --host and --build options, the correct compiler executables are used, ensuring the proper architecture.

For some other programs that don't have the convenience of the configure script, you can use the CROSS supplied to make:

CROSS=x86_64-w64-mingw32-

This will take care of ensuring the use of the proper compiler and linker binaries.