On 10/24/06, Duncan Coutts <duncan.coutts@worc.ox.ac.uk> wrote:
Hi All,

Before the 6.6 release we had a longish discussion on how to do
configurations and their semantics and implementation complexity etc.

I would like to re-propose the last scheme that I cam up with. I'll try
to make it a concrete proposal as well as giving some motivating
examples to give the intuition of the meaning.

Duncan, I have thought about this more and I have the following questions:

* How does the proposed configuration mechanism work with executables? Can executables be built conditionally? Does the chosen configuration apply to library and all executables in the package description?

* What happens when multiple configurations apply?:

    Configuration: True
    Build-depends: foo-1.0

    Configuration: True
    Build-depends: foo-1.0

  I think that if more than one condition applies, then configuration should fail with an error.

* Are True and False really useful in cexp's? If a configuration is always selected (True) then the whole mechanism is not even needed, and if it is always False then it is never used. I think any combination of and's, or's, and not's with constants can be rewritten without the constants.

* You mentioned the case where a using(x) expression conflicts with a build-depends:
       Configuration: using(foo = 1.0)
       Build-depends: foo = 2.0
It seems to me that:
        using(foo = x) == !(available foo > x),
        using(foo > x) == (available foo > x),
        using(foo < x) == !(available foo >= x),
because of Cabal's "use the latest available version" policy. If all usages of using(x) can be replaced with available(f(x)), then I think it would be better to just get rid of using(x) and allow available(x) in both fexp's and cexp's, for consistency. However, I know that you do not want to do that, because you don't want available(x) allowed in cexp's. As you noted previously in the thread, using(x) seems to cause a lot of complications--is it really necessary? I think your example of using(x) is easily rewritten to not require it:

    flag: require-fps
    default: !available(base >= 2)

    configuration: require-fps
    build-depends: fps >= 0.8

* Why not use [ os="linux" ] instead of [ os(linux) ]? Since we already have (=) for comparing package versions, it seems to be sensible to overload (=) to compare these flags as well.

* Your example used [ os(windows) ]. However, the value for System.Info.os is usually "mingw32" or "cygwin" (or similar) on Windows. I think that the os() and arch() values should be consistent with System.Info whenever possible.

* Finally, I suggest that we create some package descriptions for complicated packages, to use as "use case" scenerios. In particular, I think that at least GHC, lhs2tex, wxHaskell, and network-alt would be cases to study. By having such use cases, you will have a clearer idea of exactly what is needed in practical usage. You can also use these cases to delineate the scope of Cabal's configuration mechanism. I have a Cabal files for GHC (stage2 only) that you can use if you think this is a good idea (actually, I can probably write the Cabal file for both stages of the GHC build, sans usages of features that Cabal doesn't have).

Please let me know if this feedback is helpful. I am thinking to embed Cabal in two different tools, which is why I am so interested in these little details.

Regards,
Brian