Tuplanolla Sampsa Kiiskinen

2015

This way to install GHC with Cabal worked for me and might work for you too. However these days it might be preferable to use Stack instead.

Installing GHC

Installing tools for working with Haskell is unfortunately nontrivial. There are many compilers and packaging solutions to choose from and they all have a plethora of configurations and use cases to consider. Indeed, this text provides just one such way and explains why it might be a good one.

As the title suggests, we decide to install GHC, the biggest and oldest Haskell compiler. For packages we choose Hackage, the biggest and oldest Haskell repository. As big and old as they may be, they also provide the latest and greatest features, so if we want all the bells and whistles we can get, it is essential to get the latest versions of whatever we are installing.

The target system here is Debian or Ubuntu, but much of this text is applicable to other systems too.

Get

The latest version of GHC is 7.10.2 at the time of writing this, so we set out to get that first (newer versions have since been released).

Compiler

We start by adding a suitable package source to our package manager. Herbert Riedel’s personal package archive contains just what we need.

# apt-get update
# apt-get install software-properties-common
# add-apt-repository ppa:hvr/ghc
# apt-get update

After setting up the package manager, we instruct it to install

  • ghc for the compiler,
  • ghc-dyn for dynamic linking support,
  • ghc-prof for profiling support,
  • cabal-install for installing packages from Hackage and
  • ghc-htmldocs for Haddock documentation for all of that.

They can be installed for all users as follows.

# apt-get install \
  cabal-install-1.22 \
  ghc-7.10.2 ghc-7.10.2-dyn ghc-7.10.2-htmldocs ghc-7.10.2-prof

For version 7.10.2 the package ghc-dyn does nothing, but we install it anyway.

You can also download the packages manually or compile them from source. It does not really matter as long as you get the needed binaries.

The binaries we got are

  • cabal,
  • ghc,
  • ghc-pkg,
  • ghci,
  • haddock,
  • hp2ps,
  • hpc,
  • hsc2hs,
  • runghc and
  • runhaskell.

We need to add their locations to the search path since they go into their own directory by default.

$ export PATH=$HOME/.cabal/bin:/opt/cabal/1.22/bin:/opt/ghc/7.10.2/bin:$PATH

It might be a good idea to add that to your ~/.bashrc or something.

Packages

Now we switch from apt-get to cabal. Its package index works analogously, so we begin by downloading a fresh copy.

$ cabal update

The invocation also creates a default configuration for us. If we want dynamic linking, profiling, optimization, shared libraries and Haddock documentation for more than just the packages we already installed, we need to specify that in the configuration before installing anything. We can do that by amending ~/.cabal/config with the following options.

documentation: True
executable-dynamic: True
executable-profiling: True
library-profiling: True
optimization: True
shared: True
haddock
  hyperlink-source: True

Note that the indentation at the end matters.

Alas, options are not enough by themselves. We need to take care of a few phantom dependencies. First of all, source code will be missing from documentation unless we install hscolour, which is a syntax highlighter for haddock.

$ cabal install hscolour

It also gets us the binary HsColour. Secondly, Template Haskell might not work properly without nats-1, so we install that.

$ cabal install nats-1

Finally, some packages require alex, which is a lexer (like flex), or happy, which is a parser generator (like yacc).

$ cabal install alex happy

In this case we get the binaries

  • alex and
  • happy.

Now we have everything we need.

$ ghc-pkg list
/opt/ghc/7.10.2/lib/ghc-7.10.2/package.conf.d
   Cabal-1.22.4.0
   array-0.5.1.0
   base-4.8.1.0
   bin-package-db-0.0.0.0
   binary-0.7.5.0
   bytestring-0.10.6.0
   containers-0.5.6.2
   deepseq-1.4.1.1
   directory-1.2.2.0
   filepath-1.4.0.0
   ghc-7.10.2
   ghc-prim-0.4.0.0
   haskeline-0.7.2.1
   hoopl-3.10.0.2
   hpc-0.6.0.2
   integer-gmp-1.0.0.0
   pretty-1.1.2.0
   process-1.2.3.0
   rts-1.0
   template-haskell-2.10.0.0
   terminfo-0.4.0.1
   time-1.5.0.1
   transformers-0.4.2.0
   unix-2.7.1.0
   xhtml-3000.2.1
/home/user/.ghc/x86_64-linux-7.10.2/package.conf.d
   QuickCheck-2.8.1
   mtl-2.2.1
   primitive-0.6
   random-1.1
   tf-random-0.5

Backends

Modern versions of GHC come with interchangeable code generators called backends, some of which are better suited for certain tasks than others. For version 7.10.2 they are

  • the default native code generator,
  • the default interpreted code generator,
  • the LLVM code generator and
  • the C code generator.

They work out of the box with the exception of the LLVM option, which requires version 3.5 of the associated development libraries.

# apt-get install llvm-3.5-dev

Anything Else

You are now ready to install whatever you want.

$ cabal install random text

Just keep in mind dependency spaghetti should be kept in boxes.

$ cabal sandbox init
$ cabal install lens pandoc

That should keep you busy for a few hours.

Use

I wrote the following utilities to help with common tasks.

Browse Documentation

Since documentation goes somewhere on the file system and that somewhere depends on a few of things, it is laborious to dig up by hand every time.

We would like to be able to open the documentation for any given packages and have it take sandboxes into account too.

$ cabal-doc random text

The following shell script does just that.

$ cat cabal-doc
#! /bin/bash

cabal info "$@" | \
grep -o 'Documentation: .*' | \
cut -d ' ' -f 2- | \
sed 's|$|/index.html|' | \
xargs xdg-open 1> /dev/null 2>&1

Note that we use bash as the interpreter just to get "$@"; you can change it into $* to make it almost compatible with sh.

Dynamic Linking and Profiling

We only get dyn and p variants of libraries from the package source we chose. Since p_dyn is missing, we will always have to choose dynamic linking over profiling or vice versa and reconfigure to use either.

We would like to automate this reconfiguration, because it is something that needs to be done quite often.

$ cabal-dyn
$ cabal run
$ du -hs dist
3.2M    dist
$ cabal-prof --ghc-options='-O2 -auto-all -prof -rtsopts'
$ cabal run -- +RTS -hy -p
$ du -hs dist
16M     dist

The following shell scripts do just that.

$ cat cabal-dyn
#! /bin/bash

cabal configure "$@" \
--disable-executable-profiling --disable-library-profiling \
--enable-executable-dynamic --enable-shared
$ cat cabal-prof
#! /bin/bash

cabal configure "$@" \
--disable-executable-dynamic --disable-shared \
--enable-executable-profiling --enable-library-profiling
$ cat cabal-static
#! /bin/bash

cabal configure "$@" \
--disable-executable-profiling --disable-library-profiling \
--disable-executable-dynamic --disable-shared