cabal should reject multiple definitions of the same dependency #1107

Open
erikd opened this Issue Nov 11, 2012 · 13 comments

5 participants

@erikd
Haskell member

The buildbox-2.1.2.2 package has the following Build-Depends:

Build-Depends: 
    base           >= 4.4 && < 4.7,
    containers     >= 0.4 && < 0.6,
    time           >= 1.2 && < 1.5,
    directory      >= 1.1 && < 1.3,
    bytestring     >= 0.9 && < 0.11,
    mtl            == 2.1.*,
    old-locale     == 1.0.*,
    process        == 1.1.*,
    random         == 1.0.*,
    pretty         == 1.1.*,
    bytestring     == 0.10.*,
    stm            == 2.4.*

Note that bytestring is defined twice. cabal should detect and reject multiple definitions of the same dependency.

@erikd
Haskell member

In the file Cabal/Distribution/PackageDescription/Configuration.hs we have:

toDepMap :: [Dependency] -> DependencyMap
toDepMap ds =
  DependencyMap $ fromListWith intersectVersionRanges [ (p,vr) | Dependency p vr <- ds ]

If the right thing is for cabal-install is to reject multiple definitions of the same dependency, then it could be detected in this function and just throw an error.

Are there any objections to this? Is there a better way to indicate an error?

@tibbe
Haskell member

Somewhere in the neighborhood of that code sounds reasonable. Use D.S.Utils.die and make sure to include enough information to easily figure out what went wrong.

@23Skidoo
Haskell member

There should also probably be a check added to Distribution.PackageDescription.Check.

@23Skidoo
Haskell member

I tried adding a check for this, but bumped into a problem - cabal check merges all build-depends fields together with flattenPackageDescription (see Distribution.Client.Check), so the following (correct) .cabal file generates an erroneous warning:

library
  build-depends: foo > 1.0

executable bar
  build-depends: foo > 1.0
@erikd
Haskell member

Been meaning to have a look at this but been busy (this weekend too).

Maybe for identical dependencies cabal could just drop one and only complain about dependencies where the name is the same but the versions don't match. However, something like this:

build-depends: foo >= 1.0
                    , foo < 2.0

should probably be accepted as the ranges aren't contradictory.

One issue I had with what I was originally going to do was that if I just error out where the dependency list gets converted to a DependencyMap then its difficult to unit test without changing the return type of the function.

@23Skidoo
Haskell member

and only complain about dependencies where the name is the same but the versions don't match

Currently, this gives you an error at the solver stage.

@erikd
Haskell member

It does? I just tried this with cabal-install from git HEAD and it quite happily accepted my original example.

@23Skidoo
Haskell member

It does? I just tried this with cabal-install from git HEAD and it quite happily accepted my original example.

Contradictory version ranges (e.g. foo > 1.0, foo == 0.5.*) are rejected. Your original example specifies a consistent set of dependencies.

@erikd
Haskell member

Ah ok, if I specify

bytestring <0.9,
bytestring >=0.9 && <0.11

then I get:

$ cabal configure
Resolving dependencies...
Configuring buildbox-2.1.2.2...
cabal: At least the following dependencies are missing:
bytestring <0.9 && >=0.9 && <0.11

Wherever this is detected and reported is probably the best place to work on tightening up what accepted.

@erikd
Haskell member

Actually on second thought, I think its probably better to detect and report problems as soon as possible, which would mean detecting this as close as possible to when the cabal file is parsed.

@23Skidoo 23Skidoo added a commit to 23Skidoo/cabal that referenced this issue Jan 1, 2013
@23Skidoo 23Skidoo Add a check for multiple definitions of the same dependency.
An attempted fix for #1107 (doesn't actually work).
110f18b
@ttuegel ttuegel added this to the _|_ milestone Apr 23, 2015
@grayjay

Some packages list a dependency twice to specify a range. For example, hint uses build-depends: base >= 4, base < 5.

@23Skidoo
Haskell member

Still, stuff like

    bytestring     >= 0.9 && < 0.11,
    [...]
    bytestring     == 0.10.*,

should probably produce a warning about redundant constraints. Fairly minor issue IMO.

@grayjay

Yeah, it would probably be easy to distinguish between those two cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment