Building ghc-7.8.4 for Debian 7 (wheezy) with Stackage

This article is a recipe for building ghc-7.8.4 from source, along with the other tools you need to use Haskell. Why would you do this rather than use haskell-platform? Well, the latest haskell-platform is now over a year old, and ships with ghc-7.8.3, so perhaps you want or need the latest compiler in the 7.8 series. Or perhaps you're just curious as to how it's done.

We're also going to ensure that any packages we install to get things going will be the ones from the current Stackage LTS.

So far, I've only tried this recipe on a Debian 7 (wheezy) server, although apart from the very first step it should be the same for any distro.

Install a binary ghc

The very first step is to install a functioning binary build of haskell-platform from somewhere... presumably your distro's packages:

# apt-get install haskell-platform

(Throughout this recipe, I will prefix commands to be run as root with # and commands to be run as any non-root user with $. For the root commands, you can of course either use a root shell, or prefix each command with sudo.)

We're also going to need some other bits and pieces to build a new ghc. On a pretty minimal Debian 7, all I needed was this:

# apt-get install make libncurses5-dev

Build and install ghc

This is all straight forward. We want the default installation paths under /usr/local so there is nothing to pass to configure. Build as some non-root user:

$ wget
$ tar xfJ ghc-7.8.4-src.tar.xz
$ cd ghc-7.8.4
$ sh configure
$ make -j5

In the last line, the number 5 should be 1 more than the CPU cores you have available.

Now install as root:

# cd /home/toby/ghc-7.8.4
# make install

Bootstrap cabal

This is the tricky part, that took me a while to work out. There is a very loose coupling between ghc and cabal, but they do need to agree on some things: cabal needs to install libraries to where ghc is going to look for them! The distro supplied cabal cabal-1.14 won't work properly with our newly installed ghc as it uses the wrong value for libsubdir. The symptom of this is that any library including C code will install happily, but anything depending on such a library will then produce errors like these:

/usr/bin/ld: cannot find -lHStf-random-0.5-ghc7.8.4
/usr/bin/ld: cannot find -lHSprimitive-0.6-ghc7.8.4
/usr/bin/ld: cannot find -lHSrandom-1.1-ghc7.8.4

The cleanest way to fix this is to perform a two-stage boot of cabal: use cabal-1.14 to install a “stage1” cabal-1.18, then clean everything out and use that stage1 cabal to install a fully functional “stage2” cabal-1.18. The particular version of cabal we are using will be the one from the current LTS stackage:

# cd
# cabal update
# cabal install cabal-install==
# cp .cabal/bin/cabal .
# rm -r .ghc .cabal
# ./cabal update

The last line creates a new cabal configuration file that just needs a couple of tweaks. First, we want to reset the user-install flag. You could do that in your favourite text editor, or with this handy sed script:

# sed -i '/user-install/auser-install: False' .cabal/config

And we want to append the LTS stackage global file to the end of the file:

# u=''
# wget -q -O- $u >> .cabal/config

Now we're ready to perform the second stage install:

# ./cabal install cabal-install
# rm ./cabal
# hash -r # sacrifice goat to the great god Bash

Install other tools

Finally, to finish off, install the other basic tools:

# cabal install alex
# cabal install happy