[Haskell-cafe] A new cabal odissey: cabal-1.8 breaking its
ownneck by updating its dependencies
Claus Reinke
claus.reinke at talk21.com
Fri Sep 17 13:54:29 EDT 2010
On the topic of cabal odisseys:
I think it would help to document (prominently) what Cabal
fundamentally doesn't (try to) do, to avoid optimistic
expectations (and hence the surprises when Cabal doesn't
meet those expectations), and to point out the design choices
behind many bug tickets (even if the choices are temporary
and driven by limited manpower). Such as
- cabal doesn't keep track of what it installs, hence
- no uninstall
- no application tracking
- library tracking and information about installed
library configurations only via ghc-pkg
..
- cabal's view of package interfaces is limited to explicitly
provided package names and version numbers, hence
- no guarantee that interface changes are reflected in
version number differences
- no detailed view of interfaces (types, functions, ..)
- no reflection of build/configure options in versions
- no reflection of dependency versions/configurations
in dependent versions
- no knowledge of whether dependencies get exposed
in dependent package interfaces
..
This is just to demonstrate the kind of information I'd like
to see - Duncan&co know the real list, though they don't
seem to have it spelled out anywhere? So users see that
it works to say "cabal install" and build up their own often
optimistic picture of what (current) Cabal is supposed to
be able to do. It might even be useful to have a category
of "core-tickets" or such on the trac, to identify these as
work-package opportunities for hackathons, GSoC and
the like, positively affecting many tickets at once.
On to the specific issue at hand:
> 2. cabal ought to allow using multiple versions of a single package in
> more circumstances than it does now
>..
> 2. This is a problem of information and optimisitic or pesimistic
> assumptions. Technically there is no problem with typechecking or
> linking in the presense of multiple versions of a package. If we have
> a type Foo from package foo-1.0 then that is a different type to Foo
> from package foo-1.1. GHC knows this.
>
> So if for example a package uses regex or QC privately then other
> parts of the same program (e.g. different libs) can also use different
> versions of the same packages. There are other examples of course
> where types from some common package get used in interfaces (e.g.
> ByteString or Text). In these cases it is essential that the same
> version of the package be used on both sides of the interface
> otherwise we will get a type error because text-0.7:Data.Text.Text
> does not unify with text-0.8:Data.Text.Text.
>
> The problem for the package manager (i.e. cabal) is knowing which of
> the two above scenarios apply for each dependency and thus whether
> multiple versions of that dependency should be allowed or not.
> Currently cabal does not have any information whatsoever to make that
> distinction so we have to make the conservative assumption. If for
> example we knew that particular dependencies were "private"
> dependencies then we would have enough information to do a better job
> in very many of the common examples.
>
> My preference here is for adding a new field, build-depends-private
> (or some such similar name) and to encourage packages to distinguish
> between their public/visible dependencies and their private/invisible
> deps.
This private/public distinction should be inferred, or at least be
checked, not just stated. I don't know how GHC computes its
ABI hashes - are they monolithic, or modular (so that the
influence of dependencies, current package, current compiler,
current option settings, could be extracted)?
Even for monolithic ABI hashes, it might be possible to compute
the package ABI hash a second time, setting the versions of all
dependencies declared to be private to 0.0.0 and seeing if that
makes a difference (if it does, the supposedly private dependency
leaks into the package ABI, right?).
And secondly, how about making it possible for cabal files to
express sharing constraints for versions of dependencies?
To begin with, there is currently no way to distinguish packages
with different flag settings or dependency versions. If I write a
package extended-base, adding the all-important functions car
and cdr to an otherwise unchanged Data.List, that package will
work with just about any version of base (until car and cdr
appear in base:-), but the resulting packages may not be
compatible, in spite of identical version numbers.
If it was possible to refer to those package parameters (build
options and dependency versions), one could then add constraints
specifying which package parameters ought to match for a build
configuration to be acceptable.
Let us annotate package identifiers with their dependencies
where the current lack of dependency and sharing annotations
means "I don't care how this was built". Then
build-depends: a, regex
means "I need a and regex, but I don't care whether a also uses
some version of regex", while
build-depends: a, regex
sharing: a(regex)==regex
would mean "I need any version of a and regex, as long as a
depends on same the version of regex I depend on" (choose
any syntax that works). And
build-depends: a, b
sharing: a(text)==b(text)
would mean "I need any version of a and b, as long as they
both depend on the same version of text".
I can already think of situations where one might want more
complex constraints (e.g. "I want any version of base and mtl,
but either both have to be before the Either-move, or both
have to be after the move" - this part could be expressed
already, but there is currently no way to enforce this
transitively, for dependencies, so if I depend on c, which
depends on a new base, and on d, which depends on an
old mtl, I'm out of luck, I think). Or: "never mix mtl and
its alternatives".
Of course, this scheme depends on whether it is possible
to reverse engineer the information about dependencies of
installed packages from ghc-pkg info or ABI hashes.. but
if the general idea is sound, perhaps that could be made
possible?
Just a suggestion,
Claus
More information about the Haskell-Cafe
mailing list