This morning, I was having a problem involving Haskell’s Cabal build system. Since it’s something which could conceivably affect others, and since googling on the error text didn’t help me, I’m going to report my experience for the benefit of future travellers/googlers.
I was trying to (re)build xmonad, and got the following error:
[gimbo@orb xmonad] runghc -v Setup configure Could not find module `Distribution.Simple': Use -v to see a list of the files searched for.
Vexing. Distribution.Simple is Cabal’s “simple build system”, and is the only dependency of the Setup script in question:
[gimbo@orb xmonad] cat Setup.lhs #!/usr/bin/env runhaskell > import Distribution.Simple > main = defaultMain
Now, I had actually already installed Cabal – the latest version from darcs, in fact:
[gimbo@orb ~] ls -l /usr/local/lib/Cabal-1.1.7/ghc-6.6 total 4614 drwxr-xr-x 5 root wheel 512 20 Apr 15:09 Distribution -rwxr-xr-x 1 root wheel 1836956 27 Apr 12:42 HSCabal-1.1.7.o drwxr-xr-x 3 root wheel 512 20 Apr 15:09 Language drwxr-xr-x 2 root wheel 512 20 Apr 15:09 include -rwxr-xr-x 1 root wheel 2829692 27 Apr 12:42 libHSCabal-1.1.7.a
and Simple really was there:
[gimbo@orb ~] ls -ld /usr/local/lib/Cabal-1.1.7/ghc-6.6/Distribution/Simple* drwxr-xr-x 2 root wheel 512 20 Apr 15:09 /usr/local/lib/Cabal-1.1.7/ghc-6.6/Distribution/Simple -rwxr-xr-x 1 root wheel 30049 27 Apr 12:42 /usr/local/lib/Cabal-1.1.7/ghc-6.6/Distribution/Simple.hi
So what was the problem? Why wasn’t it getting picked up? I started to realise the answer when I followed the advice of the original error message, and passed runghc the -v flag (I’ll snip non-relevant lines, of which there were many):
[gimbo@orb xmonad] runghc -v Setup configure Glasgow Haskell Compiler, Version 6.6, for Haskell 98, compiled by GHC version 6.6 Using package config file: /usr/local/lib/ghc-6.6/package.conf Using package config file: /home/gimbo/.ghc/i386-freebsd-6.6/package.conf hiding package Cabal-1.1.6 to avoid conflict with later version Cabal-1.1.7 [snip] Setup.lhs:1:8: Could not find module `Distribution.Simple': locations searched: Distribution/Simple.hs Distribution/Simple.lhs /usr/home/gimbo/cabal/Cabal/dist/build/Distribution/Simple.hi Failed, modules loaded: none. [snip]
There are three things to notice here.
First, ghc is using two package config files: a global one and one off my home directory. This is perfectly normal, sane behaviour. More on this shortly.
Second, I have conflicting versions of Cabal installed, and it’s only using the latest one. All good: I want it to be using 1.1.7 (which I’d installed from darcs) anyway. I don’t know where 1.1.6 cae from: maybe an older darcs checkout, or maybe a snapshot. (Later I removed the old version using ghc-pkg, but that’s not what this story is about…)
Third, and most interestingly, where did it look for Distribution.Simple? Decidedly not in /usr/local/lib/Cabal-1.1.7/ghc-6.6/ (where, as we saw earlier, it would be found). Instead, it’s looking for it in /usr/home/gimbo/cabal/Cabal/dist/build/Distribution/Simple.hi. Suddenly I realised what the problem was.
When today started, my home directory contained a directory called cabal, in which I had downloaded the Cabal source, built it, and installed it (several days ago). One of my first actions today was to delete that directory, since Cabal was indeed built and installed. Little did I suspect that ghc would look for the code there, rather than in /usr/local/lib/...
So why did it? I realised the answer when I read the packages chapter of the GHC manual, which I should have done sooner. If you use Haskell and haven’t read this yet, do so! Very quickly I began to see that the key to debugging and solving my problem was the ghc-pkg utility which, among other things, can list all your installed packages:
[gimbo@orb ~] ghc-pkg list /usr/local/lib/ghc-6.6/package.conf: Cabal-1.1.7, GLUT-2.0, HGL-3.1, HUnit-1.1, HaXml-1.13.2, Haskore-0.0, OpenGL-2.1, QuickCheck-1.0, ShellPipe-0.0, X11-1.1, X11-1.2, X11-extras-0.0, base-2.0, cgi-2006.9.6, fgl-5.2, filepath-1.0, (ghc-6.6), haskell-src-1.0, haskell98-1.0, html-1.0, mtl-1.0, network-2.0, parsec-2.0, readline-1.0, regex-base-0.71, regex-compat-0.71, regex-posix-0.71, rts-1.0, stm-2.0, template-haskell-2.0, time-1.0, unix-1.0, xhtml-2006.9.13 /home/gimbo/.ghc/i386-freebsd-6.6/package.conf: Cabal-1.1.7, HAIFA-0.11, HTTP-2006.7.7, Shellac-0.6, Shellac-readline-0.3, (hat-2.5), hxt-7.1, syb-generics-2.9
Here we see two versions of Cabal-1.1.7 referenced – one in the global package database, and one in my per-user package database. The per-user version “wins” by default, so the global Cabal-1.1.7 was getting ignored. I realised that at some point in the past I had configured/built/installed Cabal-1.1.7 using the options to install it as user rather than root (see the Cabal README for how). I deduce that this registers the code in the per-user package database and (critically) doesn’t copy it anywhere – ie it assumes you won’t delete the code from the place where it was compiled. Since I deleted that code this morning, it could no longer be found.
The fix was simply to delete the Cabal-1.1.7 entry from the per-user package database:
[gimbo@orb ~] ghc-pkg --user unregister Cabal Saving old package config file... done. Writing new package config file... done.
Now ghc uses the Cabal-1.1.7 entry in the global package database, looks in the right place, and finds it – and I can build xmonad once again.
The moral of the story: RTFM. :-)