[Haskell-cafe] Cabal dependencies

Duncan Coutts duncan.coutts at worc.ox.ac.uk
Tue Jan 20 05:39:30 EST 2009


On Thu, 2009-01-15 at 18:38 -0500, Stephen Hicks wrote:
> Hi,
> 
> I'm having some difficulty specifying dependencies in my .cabal file
> for a package I'm looking to upload to hackage soon.  The difficulty
> is as follows.  I basically want to specify
>   parsec (>= 2.1 && < 3.0.0) || (> 3.0.0 && < 4)

When we first introduced this kind of version range syntax we were
unsure if it was too general or not. We want to be able to translate
into other systems and they're typically more restrictive.

Internally we can easily represent the above expression as it uses
arbitrary unions and intersections. However the external parser still
only allows two clauses (I think it's two).

Personally I'm all for lifting that restriction. Yes it makes it a bit
harder for translating into some systems but I don't see that as a real
issue. If the package really does require the more complex version range
then forcing the package author to lie by using a less expressive syntax
does not help. We can still make the same choice at the point when we
translate into native packages.

Also, as it happens there is a way of getting around the restriction
anyway, which makes the restriction effectively pointless. That is by
listing the same dependency more than once. All the version constraints
must be satisfied so you can write:

  build-depends:
    parsec >= 2.1 && < 4,
    parsec < 3.0.0 || > 3.0.0

(have I got that right?)

So I'd be interested to get feedback on lifting the restriction and the
impact that might have on translation into native packages.

> The problem is that 3.0.0 as it exists on hackage is missing a
> constructor that I need (namely, Postfix, in the compatibility
> module).  The bug was fixed and will presumably work fine if a newer
> version of parsec is ever uploaded to hackage, and my package works
> fine with older parsecs as well - I just want to exclude this one
> version.  How can I go about doing that?

Try the above.

> A secondary question is this - I can actually compile with version
> 3.0.0 by just not using this constructor, although it does reduce the
> package's functionality.  I've seen flags in various .cabal files, and
> presumably I could invent a flag to make it work with 3.0.0, but I'm
> confused about how these flags are set.

Yes, if you need compatibility with older versions of Cabal then you'd
need to use a flag. If you're prepared to require Cabal-1.6 or later
then you can use the cpp macro:

#if MIN_VERSION_parsec(3,0,0)

though of course that only gives you >= 3.0.0, you'd need more tricky
combinations to get == 3.0.0, perhaps by assuming >= 3.0.1 is ok.

For older Cabal versions the main option is a flag, like so:

flag parsec3
...

if flag(parsec3)
  build-depends: parsec == 3.0.0
  cpp-options:   -DUSING_BAD_PARSEC
else
  build-depends: parsec > 3.0.0 || < 3.0.0

> Specifically, cabal-install has never asked me anything about flags,
> so what's the point?  Or does it automatically set whichever flags
> satisfy the dependencies?

It tries to work out what flags to set automatically (based on the
platform, the available packages and flag defaults in each package). You
can override them from the command line if you want to or need to.

Duncan



More information about the Libraries mailing list