cabal-install.py

cabal-install.py is a Python script for manually installing Cabal packages, available under a permissive license. It has been tested on Mac OS X 10.6.2 (Snow Leopard), with GHC Haskell 6.12.1. It offers a viable solution for someone who might have written a similar script but didn't find the time, and can read and understand the Python code.

Usage

First, organize one's Cabal downloads in a single master directory, using the base package name for each subdirectory. In each subdirectory, place the corresponding .tar.gz file downloaded from Hackage, and any associated files such as notes or links back to Hackage. If multiple .tar.gz files are present, the script will select the last file in sort order, which tends to be the latest version. To instead select an earlier version, hide later versions in a subdirectory.

For example, in the subdirectory GLUT I placed the file GLUT-2.2.2.0.tar.gz.

Next, set the environment variable $CABAL to the location of this master Cabal directory. For example, in my .bashrc file I have the line

export CABAL="/Global/Code/Haskell/__Cabal/Packages/"

Next, copy cabal-install.py to a location on your path, renamed cabal-install. For example, I used the command

sudo cp cabal-install.py /usr/local/bin/cabal-install

Now, one can iteratively figure out a command line for installing any particular Cabal package. cabal-install.py will skip over packages that have already been installed, and abort on the first error with an attempt at a useful message. For example, by trial and error I figured out that on my system, the following command installs GLUT:

cabal-install StateVar Tensor OpenGLRaw GLURaw ObjectName OpenGL GLUT

For troubleshooting, familiarize yourself with the workings of ghc-pkg, part of the GHC installation. For example, the command

sudo ghc-pkg unregister {pkg-id}
unregisters the specified package, which is a necessary step in rolling back to an earlier version.

Background

At the time of this writing, the far more powerful Cabal package cabal-install had not yet been released in a version compatible with GHC 6.12. Meanwhile, GHC 6.12 ships with fewer libraries than before. I don't mind supervising the package installation process, choosing and downloading versions manually, but the configure-build-install cycle and keeping track of dependencies was getting to me. I had been wanting a script like this because, truth be told, I could never get cabal-install to work on earlier systems either. I drive stick, and even the cabal-install package bootstrap.sh script defaults to making different choices than I would make by hand.

cabal-install.py doesn't free me from the need to fiddle with packages. Hey, anyone following the discussions knows that they don't all work together; the folks working on the Haskell Platform have bit off a mouthful, and I don't want to wait months to start using GHC 6.12. For my limited package needs, I don't mind being involved in manually selecting package versions. I just can't remember the partially ordered set of dependencies, I never want to type runhaskell Setup again, yada yada. This script handles that tedium, and speeds up the turnaround time until I need to think again, while I'm working my way to a usable Haskell system.

The "Package Problem"?

So packages don't all work together? It dawns on me that I've always had my own package problem, in any language that I've ever used, which is why I copy modules between projects rather than maintaining master copies. One can imagine language support for module versioning, coupled perhaps with automated testing to determine version dependencies, so that this package problem would go away.

I understand why the GHC team wanted to get out of the library business, and why there needs to be a delay between GHC and Haskell Platform releases, but the "package problem" does seem to be the elephant in the room.