issues with configurations

Duncan Coutts duncan.coutts at worc.ox.ac.uk
Fri Aug 11 09:23:53 EDT 2006


On Fri, 2006-08-11 at 12:15 +0100, Simon Marlow wrote:
> Einar Karttunen wrote:
> 
> > 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
> 
> What can I say?  yeuch!  I think we've left simplicity behind here.

Well the point is to separate the decision to pick up an optional
dependency from actually doing it.

I'm not going to defend the '?' syntax too much, but I do like the
separation of flags with default values that depend on the environment
from configuration tests which depend on those flags.

> One goal (that I keep having to remind myself of) is that a .cabal file should 
> be modifyable by an IDE such as Visual Haskell.  I can't see Visual Haskell 
> being able to successfully modify that complicated build-depends expression.

Is that really any different from the conditionals in the configuration
tests?

> This is one reason I decided to go the simpler route of individual 
> configurations with conditionals, and why a conditional could be evaluated 
> independently of all the others knowing only facts about the environment.
> 
> FWIW, using my original syntax and semantics, here's how to do what you did above:
> 
> configuration: debug && !Hunit11
> build-depends: HUnit >= 1
> 
> configuration: debug && HUnit11
> build-depends: HUnit-1.1
> 
> configuration: debug && (HUnit11 || package(HUnit>=1, 1.1))
> ghc-options: -DHUNIT11
> 
> The whole thing is easier to understand IMO, and it's simple to implement too: 
> no ordering, conditionals can be evalutated independently.

Well they're only independent if you take the view that package()
conditionals test what's available in the environment rather than what
we're going to actually use. If it's what we're going to use then one
configuration can affects the condition of another.

Having it just pick up things from the environment is also evil. Any
package manager (debian, gentoo) need to be able to control/override
that. That's why we were proposing a split between flags with their
default values and conditions based on those flags. That way it's clear
what can be overridden.

> I'm back to the two-argument package() conditional, because it's actually 
> useful.  package(Hunit>=1, 1.1) is not the same as package(HUnit-1.1) or even 
> package(HUnit>=1 && 1.1).  It says "the dependency HUnit>=1 resolves to version 
> 1.1", which is exactly what you wanted to know.  This is how you write 
> conditionals that test the versions of packages you actually depend on, which is 
> the criticism raised by Duncan at the beginning of this thread.  I believe my 
> original syntax addressed this concern.

Ok if we have package(Hunit>=1, 1.1) then do we not then have an
ordering issue?

configuration: debug
build-depends: HUnit-1.1

configuration: package(HUnit>=1, 1.1)
ghc-options: -DHUNIT11

If I do the first one then the second then we know that we're going to
depend on HUnit-1.1, if we do it the other way around we don't know that
yet.

That was one reason for bringing the conditionals up front with the '?'
syntax that you object to. We can move it back to the above style if
it's easier for users/IDEs but then there must be an ordering.

> Now there are bad things that you can do with this syntax (auto-optional 
> dependencies), and there are downright ridiculous things you can do with this 
> syntax (test versions of packages you don't depend on), but I believe we could 
> either make Cabal warn about those or disallow them altogether.  I don't mind which.

I really worry that this will make many packages unpackagable because
their semantics will not be translatable into sane distro packages. As I
said, if I made a gentoo package that did auto-optional dependencies
then the QA team would shoot me.

I think it's quite easy to make package tests be only internal, that is
what deps have we resolved for the package, and not mix that up with
what happens to be available in the environment. Then as a separate
thing have some facility to make the default decisions about which
configurations to use to depend on the environment, but in a clearly
separated way so that users or packagers can override the defaults.

So let me suggest something with flags but without '?' syntax:

flag: debug
default: False

configuration: flag(debug)
build-depends: HUnit-1.1

configuration: using(HUnit==1.1)
ghc-options: -DHUNIT11

flag: gui
default: os(windows)
      || (available(gtk>=0.9.10) && available(cairo>=0.9.10))

configuration: flag(gui) && os(windows)
build-depends: Win32>=1.1
ghc-options: -DUSE_WIN32_GUI

configuration: flag(gui) && !os(windows)
build-depends: gtk>=0.9.10, cairo>=0.9.10, glib>=0.9.10
ghc-options: -DUSE_GTK_GUI


So in a flag we can make the defaults depend on the environment.
In a configuration test we can only depend on internal things like flags
and which version of a package that we depend on we decided to use. (I'm
deliberately avoiding using 'package' here because it's meaning is
overloaded with our various proposals). I'd also say that os/arch tests
could be used in flag defaults and also in configuration tests since
they're fixed aspects of the environment rather than variable like
package availability.

Then there is the problem that the order of evaluating configurations is
significant. My previous proposal was to move them up front and use '?'
but I see that's not great either. We could just say they're done in
order. I do not think it's ok that they be made independent by just
saying that they only depend on the environment rather than what we're
actually using, that stores up too many problems imho.

Duncan



More information about the cabal-devel mailing list