So here's a strawman proposal to address some of the use cases raised
recently[1] that Cabal doesn't currently support well. This is just a
first attempt; I expect we'll need to make changes or start over if we
discover cases that it doesn't handle.
[1] http://www.haskell.org//pipermail/libraries/2005-July/004152.htmlhttp://www.haskell.org//pipermail/libraries/2005-July/004133.html
Firstly, we define certain pseudo-packages on which dependencies can be
expressed. The pseudo packages would consist of the compilers and
pre-processors that Cabal understands, and any other tools required by
the build process. eg.
build-depends: ghc>=6.4 happy>=1.5 base>=1.0
Now, I suggest we expand the language of dependencies to include
disjunction and optional stanzas. The syntax I have in mind is this:
deps ::= adep*
dep-expr ::= deps '||' dep-expr
adep ::= pkg version-range
| '(' dep-expr ')'
| '[' stanza ']'
The idea is that Cabal evaluates the dependencies trying disjunctions
left-to-right, where optional stanzas [foo] are assumed to be satisfied.
When a set of satisfying dependencies has been found, Cabal processes
all the optional stanzas it contains. We now need to be able to
accumulate values from fields specified multiple times, rather than
require each field to be specified at most once.
Note that a list of dependencies can be empty, so an optional dependency
is specified as (|| dep).
Here's an example where a library can be built by multiple compilers,
where each compiler requires different modules to be compiled:
----------------
name: mylib
version: 1.0
exposed-modules: My.Lib
build-depends:
base>=1.0
(ghc>=6.4 || ghc>=6.2 [ghc62] || hugs-any [hugs])
[ghc62]
other-modules: Compat.Ghc62
[hugs]
other-modules: Compat.Hugs
-----------------
This covers Duncan's requirements, and Brian Smith's
1(a),1(b),1(d),2(a). 1(c) is not covered yet:
> (c) Cabal depends on HUnit if DEBUG is set, but it doesn't depend on
> HUnit if DEBUG is not set. (The dependency isn't controlled by the
> existence of a package, but by a configuration option.)
This is related to the concept of "configurations", which we need in
Visual Studio too. The idea is that a package can be built in one of
several different ways, where each way specifies different compiler
options or other settings. A common use is to have "debug" and
"release" configurations, where in the former we #define DEBUG, and in
the latter we turn on -O.
How might we include configurations in Cabal? A configuration selection
behaves rather like a dependency that is satisfied by the environment -
perhaps as a command line option to Setup.lhs. We could extend the
dependency syntax to include a new kind of dependency:
adep ::= ...
| config
Perhaps the concrete syntax for config is a string (eg. "DEBUG"). We
can express the HUnit example now:
----------------
build-depends:
base>=1.0
("DEBUG" HUnit>=1.0 [debug] || [release])
[debug]
other-modules: Tests
ghc-options: -DDEBUG -Onot
[release]
ghc-options: -O
----------------
Comments?
Cheers,
Simon