issues with configurations

Einar Karttunen ekarttun at
Fri Aug 11 01:59:34 EDT 2006

This kills a few typos and makes things more consistent
with more #haskell discussion.

build-depends := bexp

bexp := package-with-version
      | cexp '?' '(' bexp ')'
      | bexp ',' bexp

configuration := 'configuration:' cexp

cexp := '(' cexp ')'
      | cexp '||' cexp
      | cexp '&&' cexp
      | '!' cexp
      | 'True'
      | 'Flag(' string ')'

flag := 'flag:' name '=' dexp

dexp := cexp extended with 
        { package-with-version, Os(...), Compiler(...) }

Some observations:
* build-depends don't on packages
* order does not matter
* most of the problems seem to be solved
* see the end how this works for practical problems
* False = !True. Can be supported in the parser, but
  not needed for the semantics.

And now for the semantics of the whole thing:

ceval :: CExp -> M Bool
ceval (COr  a b) = liftM2 (||) (ceval a) (ceval b)
ceval (CAnd a b) = liftM2 (&&) (ceval a) (ceval b)
ceval (CNot x)   = liftM not (ceval x)
ceval (CTrue)    = return True
ceval (CFlag s)  = isDefinedFlag s

beval :: BExp -> M (Map Name Version)
beval (BPackage n v) = return $ singleton n v
beval (BCond c b)    = do e <- ceval c
                          if e then beval b else return empty
beval (BSeq a b)     = do x <- beval a
                          y <- beval b
                          return $ unionWith intersectVersion x y

The flag declarations simply introduce intelligent default
*guesses* for the flag values. They don't affect the resolving
the conditionals at all (except for flag values).

./setup configure support the following additional options:
--no-default-flags    don't guess - initialize all flags to False
--enable-foo          set flag foo to true
--disable-foo         set flag foo to false
--auto-foo            use guess to determine flag foo

The Art of Guessing

Package managers etc can just pass --no-default-flags and specify
things manually. This is enough for Gentoo etc.

Guesses allow the optional package dependencies, but they are
more than guesses and can be easily overridden by the user.

Solutions to various problems:

1) fps

build-depends: base, Flag(old_fps) ? (base < 2, fps >= 0.8)
flag: old_fps = base < 2
configuration: Flag(old_fps)
ghc-options: -DOLD_FPS

If we are using guessing then 6.4 will use external fps and
6.6 the one in base - correctly.

2) HUnit

build-depends: Flag(debug) ? 
               (Flag(Hunit11) ? (HUnit-1.1),
                !Flag(Huni11) ? (HUnit >= 1, Hunit < 1.1 || > 1.1))

flag: debug   = !True
flag: HUnit11 = HUnit-1.1 && !(Hunit > 1.1)

configuration: Flag(HUnit11)
ghc-options: -DHUNIT11

This seems quite complex. But it works - the meaning is:
* if debug flag is set then:
* if HUnit11 is set depend on on HUnit-1.1 and -DHUNIT11
* if HUnit11 is not set depend on version of HUnit
  that is >1 and (<1.1 or >1.1) that is not 1.1
* thus the -D is correct
* the guess is just a guess and does not affect the semantics

- Einar Karttunen

More information about the cabal-devel mailing list