I’ve been looking at cabal’s default layout of installed packages, as implemented in Distribution.Simple.InstallDirs. On non-Windows systems this ends up like:

$prefix -- /usr/local if --global, ~/.cabal if --user bin -- binaries lib $pkgid $compiler -- libraries & .hi files include -- include files libexec -- private binaries share $pkgid -- data files doc $pkgid -- documentation html -- html doc man -- man pages

There are several problems with this layout:

It doesn’t truly support multiple compilers (or even versions of the same compiler), because while the libraries and .hi files can be multiply resident, things like the doc and the binaries only get the last set built. But, the doc for a package could change depending on which compiler it is compiled for (perhaps not all of the API is available under an older version…) If you want to remove a package, you’ve got to ferret all the pieces out of global bin, libexec, and man directories, and there are three separate directories named with $pkgid to remove. If you want to remove a compiler, you need to remove all the $compiler directories out of all the packages. Then, if a package has no other $compiler subtrees, remove that package (see #2).

Most other language library sets on other platforms seem to place things under per interpreter version sub-trees[1]. In keeping with that, and trying to better support the three use cases above, I developed this:

$prefix -- /usr/local/haskell if --global, and ~/.cabal if --user $compiler $pkgid bin -- binaries lib -- libraries & .hi files include -- include files libexec -- private binaries share -- data files doc -- documentation html -- html doc man -- man pages

The first big advantage is that a package can be installed for multiple compilers easily, and independently. The second is that removing an older compiler, and all the package versions for it, is really easy. And removing a package is quite a bit easier: just remove the $pkgid under each $compiler . Of course, there is also the nicety that bits of Haskell packages aren’t intermingled throughout /usr/local .

The actual $prefix directories would probably be platform and distribution specific. For example, on Mac OS X the would be /Library/Haskell and ~/Library/Haskell .

This structure is similar to what I proposed for Mac OS X awhile back, and have been running on my systems for about a year. Note that the GHC distribution, uses a somewhat different layout for the packages it includes, but shares with this structure the ordering of $compiler/$pkgid rather than the other way ’round. This structure also has no need for the special $libsubdir and $datasubdir processing.

To Facilitate easy access to binaries and docs, we could add:

$prefix -- /usr/local/haskell or ~/.cabal $compiler bin -- symlinks to binaries in built with this $compiler doc -- doc for packages for this $compiler html -- master index of html man -- symlinks to man pages under this current -- symlink to current $compiler bin -- symlink to current/bin doc -- symlink to current/doc

Users can then put /usr/local/haskell/bin and ~/.cabal on their PATH , or further simlink from those locations to bin directories that already are.

It is relatively easy to set up your own .cabal/config file to do this. But, now with Haskell Platform, more people will be doing their initial installs via these prepackaged means, and they all use the current layout, and default new package installs to that layout as well. If there is consensus that the above layout would improve things going forward, especially in supporting multiple installed compiler versions, then I’d be happy to submit a patch to Cabal for it.

Thoughts?

– Mark