Shared Haskell .so library with GHC 6.10.4 and Cabal
I wanted to extend an app written in ANSI C with a functionality written in Haskell. This can be somewhat complicated process. If you use GHC 6.12.1 or newer it can supposedly be easily done with -shared flag. Well, I’m not sure how it works there, but installing GHC 6.12.1 is a painful process. Instead I wanted to do the same with GHC 6.10.4. Turns out it can be done with a simple Makefile like this:
shared:
ghc -O --make \
-no-hs-main -optl '-shared' -optc '-DMODULE=HaskellExts' \
-o HaskellExts.so src/HaskellExts.hs src/module_init.c
module_init.c is also pretty simple and generic:
#define CAT(a,b) XCAT(a,b)
#define XCAT(a,b) a ## b
#define STR(a) XSTR(a)
#define XSTR(a) #a
#include
extern void CAT (__stginit_, MODULE) (void);
static void library_init (void) __attribute__ ((constructor));
static void
library_init (void)
{
/* This seems to be a no-op, but it makes the GHCRTS envvar work. */
static char *argv[] = { STR (MODULE) ".so", 0 }, **argv_ = argv;
static int argc = 1;
hs_init (&argc, &argv_);
hs_add_root (CAT (__stginit_, MODULE));
}
static void library_exit (void) __attribute__ ((destructor));
static void
library_exit (void)
{
hs_exit ();
}
I took both from http://wiki.python.org/moin/PythonVsHaskell.
Now, this method works in general. However, I wanted to make a .cabal package description, because cabal-install handles some common tasks (like pulling dependencies and cleaning) automatically. This turned out to be little tricky. I had to cheat: the shared library is actually build as executable. Here is the core part of .cabal:
executable HaskellExts.so
build-depends: base == 4.*, directory == 1.0.* , filepath == 1.1.*, edit-distance == 0.1.2.*
hs-source-dirs: src
ghc-options: -optl-shared -optc-DMODULE=HaskellExts -no-hs-main
main-is: HaskellExts.hs
c-sources: src/module_init.c
include-dirs: src
install-includes: HaskellExts.h
cc-options: -DMODULE=HaskellExts -shared
ld-options: -shared
I’m not sure it is the minimal configuration that works. But it works for me so I’m happy with it. The whole code is available here: http://dl.dropbox.com/u/1479187/blog/killer-haskell-exts.7z

This will work on Windows and Linux, but not MacOs X. You need to build the development version of ghc for the latter.
Frankly speaking, I didn’t even know it’ll work on Windows. It worked for me on Linux tough.