cabal-install-0.8 final testing

Duncan Coutts duncan.coutts at
Sat Dec 19 20:46:11 EST 2009

On Fri, 2009-12-18 at 19:44 -0800, Dave Bayer wrote:
> Hi Duncan,
> Installation was easy (I typed "cabal-install HTTP zlib
> cabal-install" ;-).

Thanks for testing it. I've uploaded it to hackage.

> Overall, seems to work fine. I couldn't build darcs, but I couldn't do
> that by hand either; I used their binary installer. I don't think they
> build yet under GHC 6.12.1.
> One oddity, I tried to use cabal install to install mmap, and it
> failed because the HUnit package was missing. I then installed HUnit
> without incident, went back and installed mmap without incident. No
> idea why this didn't work in one pass, but I have "sandbox" systems if
> you'd like me to see if I can reliably reproduce this.

Mm. This is a worse bug than I thought. It's not trivial to fix. I'll
have to think about it.

The problem is mmap uses:

Executable mmaptest
  Main-is: tests/mmaptest.hs
  if flag(mmaptest)
      Buildable: True
      Buildable: False
  Build-depends: base<5, bytestring, HUnit, directory

Now the question is what does this mean exactly. The previous version of
Cabal said essentially "well the executable needs HUnit thus the package
needs HUnit". This despite the fact that we're not going to actually
built this test executable!

The current Cabal code takes a slightly different approach. It says at
the end "oh this exe isn't buildable, so its deps do not contribute to
the deps of the package".

The problem is what it was doing before that. It sees the dependency on
HUnit and checks that it can be satisfied. It's only at the end that it
ends up discarding it. So if it was not actually available then it fails

The reason it's then inconsistent between configuring a package and what
the cabal install planner is doing is that the planner assumes all the
packages on hackage are available (sort of) while when we get to
actually configuring a package to install it, only the other installed
packages are available. So that's why the same solver gives us different
answers, because we're making different assumptions about the available

So the issue is we need to treat "Buildable: False" specially in the
solver because if we end up picking a configuration with "Buildable:
False" for a component then have to have not already required the
dependencies for that component.

Essentially we want to reinterpret it as something like:

  if flag(test)
      Buildable: True
      Build-depends: base<5, bytestring, HUnit, directory
      Buildable: False

So that the dependencies themselves are conditional on the component
being buildable. Then the solver would do the right thing.

In general I guess the transformation would look like:

  if A1
    Buildable: False
  if A2
    Buildable: False

  if B1
    Build-depends: blah
  if B2 
    Build-depends: blah

where A1,A2,... and B1,B2,... are arbitrary conditions (including none)

then this becomes:

  if A1
    Buildable: False 
  if A2
    Buildable: False

  if B1 && ! (A1 || A2 || ...)
    Build-depends: blah 
  if B2 && ! (A1 || A2 || ...) 
    Build-depends: blah

I don't especially like this though. It makes the meaning of buildable
rather magic. In the short term I may have to revert the change in
behaviour so that these dependencies become unconditional again, even
though they're not used. Sigh.


More information about the Glasgow-haskell-users mailing list