views:

115

answers:

2

I'm working on a dataflow-based optimization library written in Haskell. It now seems likely that the library is going to have to be split into two pieces:

  • A core piece with minimal build dependencies; call it hoopl-core.

  • A full piece, call it hoopl, which may have extra dependencies on packages like a prettyprinter, QuickCheck, and so on.

The idea is that the Glasgow Haskell Compiler will depend only on hoopl-core, so that it won't be too difficult to bootstrap the compiler. Other compilers will get the extra goodies in hoopl. Package hoopl will depend on hoopl-core.

The Debian package tools can build multiple packages from a single source tree. Unfortunately Cabal has not yet reached that level of sophistication. But there must be other library or application designers out there who have similar issues (e.g., one package for a core library, another for a command-line interface, another for a GUI interface).

What are current best practices for building and managing multiple related Haskell packages using Cabal?

+2  A: 

Put the two packages into separate subdirectories of your source control repo, and use two separate cabal files.

Make sure you use the move operation of your source control system when moving files, so that it tracks the history properly.

Ganesh Sittampalam
Is there a way to manage dependencies other than remember to install `hoopl-core` every time I try to build `hoopl`?
Norman Ramsey
Wouldn't hoopl depend on hoopl-core (so e.g. cabal install will resolve the build chain?)
Don Stewart
Don: It wouldn't resolve it from the local copy, which is normally what you'd want, though.Norman: I don't know any nice way to manage that automatically. One option would be to use a flag or temporary change to the cabal file for hoopl that included the hoopl-core sources on the search path, so it automatically incorporated them without using the package mechanism. You'd need to make sure you built without the flag before uploading to check you'd got exposed modules right in hoopl-core, though.
Ganesh Sittampalam
@Don Yes, definitely hoopl will depend on hoopl-core. But I can't think of an easy way to force my mkfile to install hoopl-core when needed before building hoopl. @Ganesh thanks for the suggestions; let's see if any other ideas come in...
Norman Ramsey
+1  A: 

I'd put the two packages in separate subdirectories, and have a Makefile with something like this:

.PHONY: all hoopl hoop-core
all : hoopl

hoopl : hoopl-core
       cd hoopl && cabal build && cabal register --inplace

hoopl-core
       cd hoopl-core && cabal build && cabal register --inplace

this assumes you've bootstrapped the process by first building hoopl-core and registering it (--inplace) and then building hoopl. You could automate more of this using the Makefile.

As you know, when we wanted similar functionality for GHC, we wrote our own build system instead ;-) I don't recommend that. Technically I suppose it would be possible to extract from the GHC build system the required pieces and make a re-usable framework, though...

Simon Marlow
The `register --inplace` looks like just the ticket, thanks. I promise not to write my own build system unless I can get a grant to do it ;-)
Norman Ramsey