Joachim Breitner

Building arbtt for Windows

Published 2009-12-25 in sections English, Haskell.

A friend of mine is interested in trying out the Automatic Rule Based Time-Tracker arbtt which I programmed. Unfortunately, he is using Windows and up to now, arbtt only worked on Linux. But as I wanted to check out Haskell’s cross-platform abilities for a while, this was a good opportunity to do so. I don’t have Windows installed myself (and did not plan to do so), so I did all this under WINE, the Windows compatibility layer, which works very well: It takes only a few minutes to install the Haskell Platform for Windows and then I was able to run wine ghc --make and cabal install.

I played around with some simple programs and was surprised by these timings:

$ rm *.o *.hi; ghc --make fourfours.hs ; time ./fourfours > /dev/null
[1 of 1] Compiling Main             ( fourfours.hs, fourfours.o )
Linking fourfours ...

real	0m1.909s
user	0m1.692s
sys	0m0.208s
$ rm *.o *.hi; wine ghc --make fourfours.hs ; time wine ./fourfours.exe > /dev/null
[1 of 1] Compiling Main             ( fourfours.hs, fourfours.o )
Linking fourfours.exe ...

real	0m1.631s
user	0m1.376s
sys	0m0.092s

So it is faster to run a compiled Haskell program on top of a compatibility layer than directly on Linux! The world is in order again, though, if optimization is enabled:

$ rm *.o *.hi; ghc -O --make fourfours.hs ; time ./fourfours > /dev/null
[1 of 1] Compiling Main             ( fourfours.hs, fourfours.o )
Linking fourfours ...

real	0m0.981s
user	0m0.876s
sys	0m0.108s
$ rm *.o *.hi; wine ghc -O --make fourfours.hs ; time wine ./fourfours.exe > /dev/null
[1 of 1] Compiling Main             ( fourfours.hs, fourfours.o )
Linking fourfours.exe ...

real	0m1.270s
user	0m1.036s
sys	0m0.072s

Funny. Anyways, I wanted to port arbtt. The only platform-dependent part is the capture module that gathers the list of open Windows. The Win32 package that comes with the Haskell Platform did not cover all the functions needed to do so, but creating additional function bindings is really easy with Haskell, as can be seen in the Graphics.Win32.Window.Extra module. I also replaced the locking code that prevents two instances of arbtt-capture to run at the same time by equivalent code using Windows mutexes (module System.Win32.Mutex). With these small changes and some CPP conditionals to make the code compile for either platform, the porting was done! Even accessing the files in ~/.arbtt works correctly on Windows, where it will look in the Application Data folder, without changing the code, thanks to System.Directory.getAppUserDataDirectory.

But Windows users won’t like compiling software on their own. They won’t even like installing software by copying various files to certain directories. Therefore, I also had to create a Windows Installer. I picked Inno Setup, because it’s Free Software and seems to be simpler than NSIS. The installer puts the compiled .exe files, the example categorize.cfg and the HTML documentation in the right spot, adds icons to the Start Menu (“Edit categorize.cfg”, which fires up wordpad, a link to the documentation and the uninstaller), puts arbtt-capture in the Autorun folder, puts the path to arbtt-stats in the PATH variable and starts arbtt-capture at the end (the last three points being optional). Of course it undoes all this when removing the program again. I integrated the call to the Inno Setup installer into the usual ./Setup build process of Haskell packages. Some more details of how to create the Windows installer are mentioned in the README file.

Now all this does not magically add a graphical user interface to arbtt, so users will still have to work with arbtt-stats on the command line – even on Windows. If this is not a problem for you then you can fetch the latest installer from the arbtt homepage. And if you happen to become a serious user of arbtt on Windows and want to help maintaining the Windows port, I’ll gladly share some responsibilities.

I’m very satisfied with the process and the result and I’m happy to know that I can offer some of my programs also to Windows users in the future.It is also a big plus for Haskell – with Python, shipping a program for Windows users is likely more difficult. The next step will be providing gtk-based graphical Haskell applications for Windows, including a nice installer that ideally includes all dependencies (gtk etc.).


FYI a Python application can just be the source script, considering the interpreter as a depenency, the user doesn't need to (manually) compile so it is much simpler (if no platform-dependent functionality is used). Packaging a single file including every dependency is harder.
#1 charon am 2009-12-25
Well, for python, I need to tell the user to manually install python and all python libraries (e.g. PyGTK) used. And as Felipe says, it is not easy to bundle these.

In contrast, a compiled Haskell program does not have any Haskell-specific dependencies.
#2 Joachim Breitner (Homepage) am 2009-12-25
If you do find a straightforward way of including Gtk+ and Gtk2Hs in the Windows installation process, I'll be really glad to hear. Not that I've tried, not that I'm a Windows user, it's just good to know. I remember being sort of a nightmare to pack Gkt+ and PyGtk together =(.
#3 Felipe Lessa am 2009-12-25
I was hoping someone would add a comment here with „look, it’s really easy, just do this and that and then...“ :-)
#4 Joachim Breitner (Homepage) am 2009-12-25
It actually does not seem to be so bad: From or fetch the bundle. Distribute the contents of this zip and put your binary in the bin/ subdirectory as well. This seems to be a simple and working way of distributing gtk with your application and not interfering with other gtk applications on the target PC.
#5 Joachim Breitner (Homepage) am 2009-12-25
Or you ship the installer from gtk-win ( inside your installer and use it to install the bundle into your application folder. Not sure though how that differs from the zip bundle mentioned above.
#6 Joachim Breitner (Homepage) am 2009-12-26

Have something to say? You can post a comment by sending an e-Mail to me at <>, and I will include it here.