GHC 7.8′s -staticlib flag

The new flag in GHC 7.8 -staticlib allows you to produce static libraries for linking with C code on OS X. Previously you would need to link every Haskell dependency and object file to produce a static archive. But by using -staticlib it will link all Haskell dependencies into the one archive.

Let’s look at this in action. We write the Haskell module Foo.

module Foo where

import Foreign.C
import Foreign.C.Types
import Foreign.C.String
import Data.List

foreign export ccall comma :: CString -> IO CString

comma :: CString -> IO CString
comma x = do
  s <- peekCString x
  newCString $ intercalate ", " $ words s

If we compiled it conventionally with ghc -no-hs-main we would need to include libHSrts_tthr.a, libHSffi.a, libHSbase.a plus any other libraries we imported. So instead, we use:

maxs$ ghc -staticlib Foo.hs

This produces a single liba.a with all the libraries linked in!

We defined a comma function that takes a string and puts commas between each word. We exported this function via the FFI, so we also get a foo_stub.h to include in C to use these functions with. For example:

#include <stdio.h>
#include "foo_stub.h"

int main(int argc, char *argv[]) {
  hs_init(&argc, &argv);

  char *word = comma("foo bar");
  printf("%sn", word);

  hs_exit();
  return 0;
}

This calls the comma function and prints out foo, bar. To compile it, we use a C compiler. E.g.

maxs$ gcc main.c liba.a -liconv -lgmp

This compiles the main.c file above, links in our Haskell archive, plus links in the system iconv and gmp libraries. This gives us a static executable we can run.

maxs$ ./a.out 
foo, bar

Sorry it is OS X only. For BSD / Linux I recommend using Justin Spahr-Summers’s flagsForPackage program or a bash script.