
On Wed, 2006-10-25 at 22:19 -0500, Brian Smith wrote:
On 10/24/06, Duncan Coutts
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?
that's not quite clear yet. I invite suggestions. It might be useful to have executable stanzas inside conditional stanzas, and it may be useful to have conditional stanzas inside executable stanzas.
* 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.
I think it's important that mutliple configurations can apply at once. So then the question is how do we interpret additions to fields, eg do we interpret them as sets or multi-sets. I think we'll have to say that the order in which the flags are added is undefined (eg for things like cc-options).
* 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're right that they're not directly useful but they can easily be expresses using and or & not. We do need convenient True and False in fexps so for consistency I would allow them in cexps, as they do no harm.
* 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.
They're not the same. If the latest versions of each package do not satisfy the constraints then Cabal may have to pick different versions and then the above do not hold. Additionally, there's no reason why Cabal should not be extended to allow users to build against older versions of libs they have installed, eg for testing purposes or because they know only the older version is available on some site where they intend to deploy.
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:
But even if using is equal to some available expression in normal circumstances, there's still a reason for using rather than available, which is that using is less expressive. It doesn't allow packages to automatically pick up dependencies merely because they're available in the environment. This is one of the main points of the design. Anything like that has to go via a flag, which is then controllable by the user or package manager.
* 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.
Yeah, I don't mind. It was just for consistency with the other tests. Convince everyone else.
* 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.
You're probably right, though that in it self needs resolving since people do need reliable tests for being on windows. (os(mingw32) || os(mingw64) || os (cygwin)) starts to get a little unwieldy.
* 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).
Very good idea.
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.
Lots of interesting points. Good stuff. Duncan