
Duncan Coutts wrote:
On Fri, 2006-08-11 at 12:15 +0100, Simon Marlow wrote:
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?
Visual Haskell would ignore complicated configuration sections. It can handle configuration sections that just test a single flag, because this fits in with the Visual Studio notion of "configurations". It also needs to be able to grok and modify the build-depends field. The idea would be that if you want to do anything more complicated, then you add a configuration section to the .cabal file by hand.
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.
Yes, that's the intended semantics (sorry for not saying that explicitly). It's what makes simpler, but possibly too general.
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?
No, it's evaluated based on the environment only. That's why the dependency is repeated from the build-depends field.
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 imagine you could figure out for a given package description whether it had any auto-optional dependencies in it (it's not trivial, but not too hard I think).
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.
Ok - so is it a goal that you want to allow auto-optional dependencies but allow the packaging environment to turn them off? If so, then I agree you need something like the scheme you suggest, I just want to be clear about why we need that (especially if auto-optional deps are considered evil).
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
with this you can still write silly tings - an available() condition for a package you don't care about, for example. To summarise there are a couple of issues. I'll use the abbreviations AOD for auto-optional dependencies and SC for silly conditionals (predicates on packages that aren't a dependency). Ordering requirement on configurations: Option O1. No ordering, requires 2-argument package() predicate. Allows AOD and SC, but we could (possibly) detect these. Option O2. Ordering matters, we have using(P) predicates, doesn't allow AOD or SC. Default settings for flags: Option D1. All flags default to off. Option D2. Defaults can be set based on the availability of packages. Allows AOD and SC, but both can be disabled with a command-line switch. If we can do without AOD, then we just choose between O1 and O2 - not a straightforward choice, but I went the O1 route because it's easier to implement and more declarative, on the other hand adding detection of AODs would mean more complexity. If we want AOD, then probably O2/D2 (the dcoutts proposal) is the sensible choice. On the other hand, it means adding yet more stuff to Cabal... Cheers, Simon