issues with configurations

Duncan Coutts duncan.coutts at worc.ox.ac.uk
Fri Aug 11 11:15:06 EDT 2006


On Fri, 2006-08-11 at 15:08 +0100, Duncan Coutts wrote:
> On Fri, 2006-08-11 at 12:15 +0100, Simon Marlow wrote:
> 
> > The whole thing is easier to understand IMO, and it's simple to implement too: 
> > no ordering, conditionals can be evalutated independently.
> 
> I think that having the semantics of 'package()' in a configuration test
> be to just check for the availability of a package in the environment
> must be wrong. It's usually not what you want, and when it is what you
> want you shouldn't be doing it! :-)

Ok so let me try and propose something concrete:

build-depends := [package-with-version]

flag := 'flag:' name
        'default:' fexp

-- flag default value expression
fexp := '(' cexp ')'
      | cexp '||' cexp
      | cexp '&&' cexp
      | '!' cexp
      | 'True'
      | 'False'
      | 'os'   '(' string ')'
      | 'arch' '(' string ')'
      | 'compiler' '(' string ')'

-- this is the important one:
      | 'available' '(' package-with-version ')'

configuration := 'configuration:' cexp

-- configuration predicate expression
cexp := '(' cexp ')'
      | cexp '||' cexp
      | cexp '&&' cexp
      | '!' cexp
      | 'os'   '(' string ')'
      | 'arch' '(' string ')'
      | 'compiler' '(' string ')'

-- these are the important ones:
      | 'flag' '(' string ')'
      | 'using' '(' package-with-version ')'

So, semantics...

Default values of flags can be evaluated independently and up front. The
only non trivial test is the 'available' one. This checks if a package
exists in the environment with that name and with a version that
satisfies any given version range. "available (A>1) && available (A<1)"
means (exists A. A>1) && (exists A. A<1), so they do not need to be the
same A. Where as "available (A >1 <1)" would refer to the same A and
therefore not be satisfiable.

Configurations are evaluated in order, top to bottom (can we do better?
require them to be acyclic?). Each configuration predicate can be
evaluated based only on knowing the values of the flags (which may come
from their default values or be overridden by the user) and the set of
packages we are committed to. The 'using' test is the only non-trivial
one. This checks if we are committed to depending on a version of the
named package that satisfies the version range. We discover this by
starting with the top level build depends. We do the normal checks to
decide which version of each package we are going to depend upon. Once
we know that then we can evaluate the 'using' tests. Of course a
configuration may add extra build-depends and this can effect the value
of a 'using' test in later configurations.

How does this interact with the possibility of using multiple versions
of a dependent package? In that case 'using' refers to any of the
versions. So if we end up using Foo-1.0 and Foo-1.1 then both
configurations are active:

configuration: using(Foo>1.0)

configuration: using(Foo<=1.0)


Is there any way to make the order of configurations not matter? suppose
I've got a configuration:
configuration: using(Foo)
build-depends: Bar

configuration: using(Bar)
build-depends: Foo

We could ban it, or do it in order, or iterate 'til fixpoint. I think
iterating 'til fixpoint would be terminating.

Duncan



More information about the cabal-devel mailing list