How to cabal install

cabal is a command-line program for downloading and building software written in Haskell. It can install all kinds of fascinating and useful software packages from the Hackage repository. It is excellent and indispensable, but it currently has a troublesome flaw: it sometimes mysteriously refuses to install things, leading to cries of "AAAGH! CABAL HELL!!".

A little extra know-how prevents this. This tutorial aims to show you how to install cabal packages with confidence, especially if you are new to Cabal and Haskell. Welcome and let's get started!

Should I use cabal ?

Your system may have a package manager, like apt-get, yum, or macports, and it might offer packages for the Haskell software you want to install. In this case you may save time by using it instead of cabal. It probably offers more stable, better-integrated packages, and they may be pre-compiled.

Otherwise, yes, use cabal. It is cross-platform and can install the widest range of up-to-date Haskell software. It is also an essential tool if you want to develop Haskell software.

cabal, Cabal, cabal-install

Let's clarify these now to avoid confusion later. The Cabal wiki page says:

> "Cabal is a package and build system. Cabal is only involved in the creation of packages and the building of their contents. It does not manage packages. > Cabal-Install installs cabal packages. It is distinct from Cabal (the build system). This often confuses new users. Furthermore, Cabal-Install is not a fully featured package manager. For example, it cannot install non cabal packaged dependencies, it cannot uninstall packages, nor can it automatically upgrade installations.

In short: this tutorial is about using cabal-install, which is cabal on the command line. We'll just say cabal from now on. It installs cabal packages, can't uninstall them, and can upgrade them only with supervision. (Uninstalling is done with a lower-level tool called ghc-pkg, as we will see below.)

Getting cabal

cabal installs software, and can upgrade itself, but first you need get it installed by some other means. It is often available as a system package, otherwise get it by installing the Haskell Platform, or just GHC.

To check that it's installed, at a command prompt do:

$ cabal --version
cabal-install version 1.16.0.2
using version 1.16.0 of the Cabal library
$

You should avoid versions older than 0.14. (After 0.14 the version number jumped to 1.16). If you do have a very old version, you might be able to upgrade like so (we take care not to leave two versions of Cabal installed):

Installing things

download and install the package with cabal install PACKAGE. Some useful options:--dry-run to see what cabal plans to do (recommended),-jN to build N packages in parallel (faster, uses more memory),-fFLAG or -f-FLAG to turn build flags on or off (for packages that have them).

Packages can contain libraries (for use by other packages), executables (for use by humans), or both. cabal and ghc-pkg only keep track of installed library packages. The shelltestrunner package provides only executables, so cabal and ghc-pkg do not care about it after installation. To check for installed executables, we can do eg:

When it won't install: cabal hell

Over time, as you install more packages, and as new versions are released on Hackage, cabal install becomes more likely to fail due to unresolvable dependencies. There are other reasons for install failure (bad dependencies, bad code, incompatible compiler version, missing C libraries), but unresolvable dependencies is the most common. When it happens, you'll see something horrible like:

What has happened is that your installed packages, plus the new packages cabal thinks should be installed, plus a GHC restriction that only one version of each package is used in any build, have formed a network of dependencies that cabal can't satisfy. And, cabal's explanation of the problem is hard for a human to understand. You are entering.. cabal hell!

The easy solution: reset your packages

There is an easy workaround that does not require cabal troubleshooting skills or special tools. If we clear out all installed libraries, cabal may have to reinstall a few but will have a much better chance of success. The easiest way to do this (on unix) is:

$ rm -rf ~/.ghc ~/.cabal
$

This is simplest and reclaims most disk space, but it also deletes executables and config files. A less crude way is to use this bash script, which you can add to your ~/.bashrc:

The careful solution: use a sandbox

Another approach is to keep separate installed package sets, known as sandboxes. This costs more disk space and build time overall (for me, each package set takes about 0.5G of space). But when you need to work on multiple projects whose dependencies are incompatible, or to isolate projects from unrelated upgrades, this is the solution. cabal does not yet provide this feature natively; for now it means using an additional tool, either cabal-dev or hsenv.

The harder, quicker solution: clean your packages

As you get familiar with diagnosing these failures, you will more often be able to see how to clean up your installed package set to give cabal more freedom. Sometimes just removing the right old package will get things unstuck. Use ghc-pkg unregister PACKAGE for this. If other packages depend on it, you can add --force, then also remove those packages (which will now be in a broken state). The following bash script makes this easier:

Since cabal will reinstall whatever it needs, you can keep removing and cleaning until your install command works again. This incremental removal might be preferable to a full reset.

Dealing with bad dependencies

If, after a reset or in a clean sandbox, there are still unresolvable dependencies, it means the released packages on Hackage have bad (incorrect, out-of-date, too tight, too loose) dependency declarations, or the packages are not compatible with your GHC version. In this case identify the problem package(s) and get the maintainer's help, and/or try fixing the dependencies yourself in a local copy of the package (cabal unpack is good for this).