Cabal Configurations - Beta-Testers Wanted
Thomas Schilling
nominolo at googlemail.com
Wed Jun 27 21:12:03 EDT 2007
Hello Cafe!
Cabal configurations are an often-requested new feature of Haskell's
packaging system Cabal. As part of my Google Summer of Code project
I implemented it with the feature set of the latest proposal[1]. I
would now like people to try it out and give some feedback if it
solves their problems, if there are bugs with the current
implementation, or if it breaks any install scripts.
So, if you have written a package and think your package could profit
from Cabal configurations, please adjust your package description and
try to build it on as many systems as possible and report any
problems (or successes).
Following are some instructions to get started.
Thanks,
/ Thomas
INSTALLING
[Note: The following build instructions are for a recent GHC. If you
have another Haskell compiler/interpreter you'll probably have to
adjust these steps a bit. Please report any problems you encounter.]
You should be able to get Cabal with configurations via:
$ darcs get --partial http://code.haskell.org/~nominolo/src/cabal
+configs/
Before installing you might want to hide the current cabal package
using (tt shouldn't be necessary, though) via
$ ghc-pkg hide Cabal
or
$ sudo ghc-pkg hide Cabal
depending on where Cabal is installed.
Installing the new Cabal should be as simple as:
$ cd cabal+configs
$ make install user=y PREF=~/sw
This will build Cabal with version 1.1.7, register it in the current
user's package database, and install it to the "sw" directory of the
current user home directory. Adjust the parameters to your needs.
To remove use:
$ make remove user=y PREF=~/sw
NEW FEATURES
The new constructs didn't integrate well with the conventional
syntax, so I changed it to a C-style block-style syntax. (This is
consistent with Haskell's use of { .. } in do-blocks; adding or
replacing this with an indentation-based approach is thinkable and
might actually integrate better with the rest of Cabal file syntax.
So yell if you want it--but no bike sheds please! ;)
The new syntax structures cabal files like this:
global properties
optional flags descriptions
Library {
library build properties and conditionals
}
Executable name {
executable build properties and conditionals
}
For an example, see below.
Inside the Library and executable sections you can now use
conditionals with the syntax:
body: cabal_stanza "\n" body
| "if" conditional "{" body "}" [ "else" "{" body
"}" ] body
| <nothing>
conditional: "os(" string ")"
| "arch(" string ")"
| "flag(" flagname ")"
| "True"
| "False"
| "!" conditional
| conditional "||" conditional
| conditional "&&" conditional
| "(" conditional ")"
Note that you cannot test for dependencies directly. The user either
specifies certain features she wants by switching flags on or off
during the configure step or Cabal picks a suitable flag assignment
for you, depending on which dependencies are available. Unless
specified otherwise, flag assignments default to True.
ATM, the only field specifying dependencies is "build-depends".
Options specified inside a conditional are (mostly) added to the
values specified outside. E.g.
GHC-Options: -Wall
if flag(debug) {
GHC-Options: -DDEBUG
}
when built with flag "debug" set to True will be built with
GHC-Options: -Wall -DDEBUG
For a more detailed description see[1]. The following example .cabal-
file should demonstrate the features (it is also available and
updated at[2]):
Name: Test1
Version: 0.0.1
Cabal-Version: >= 1.1.7
License: BSD3
-- License-File: LICENSE
Author: Thomas Schilling <notme at nospam.com>
Maintainer: Thomas Schilling <notme at nospam.com>
--Homepage: http://www.example.com/
Synopsis: Test package to test configurations
Description:
See synopsis.
.
Really.
Category: Useless
Flag Debug {
Description: Enable debug support
Default: False
}
Flag NoBuild {
Description: Inhibit building this package.
-- defaults to True
}
Library {
Build-Depends: base
Exposed-Modules: Testing.Test1
Extensions: CPP
-- flag names are case insensitive
if flag(debuG) {
CC-Options: "-DDEBUG"
GHC-Options: -DDEBUG
}
if flag(NoBuild) {
Build-Depends: nonexistentpackage
}
}
Executable test1e {
Main-is: T1.hs
Other-modules: Testing.Test1
if flag(debug) {
CC-Options: "-DDEBUG"
GHC-Options: -DDEBUG
}
}
When configuring it with the usual command line, you now get an
additional line, showing which flags were chosen:
$ ./Setup.lhs configure
configure: Reading installed packages...
Configuring Test1-0.0.1...
configure: Flags chosen: nobuild=False, debug=False
Setup.lhs: Warning: No license-file field.
configure: Dependency base-any: using base-2.1.1
[...]
Note that, even though the default for the "nobuild" flag was True,
the required dependencies weren't present, so it was forced to False.
If you want to force flags to certain values you can do so by giving
the --flags or -f flag to configure. Listing the (case-insensitive)
name forces it to True, putting a "-" in front of the name forces it
to False. For example:
$ ./Setup.lhs configure -fdebug
configure: Reading installed packages...
Configuring Test1-0.0.1...
configure: Flags chosen: nobuild=False, debug=True
Setup.lhs: Warning: No license-file field.
[...]
or
$ ./Setup.lhs configure --flags="-debug nobuild"
configure: Reading installed packages...
Configuring Test1-0.0.1...
Setup.lhs: At least the following dependencies are missing:
nonexistentpackage -any
$
Note that if you want to change the configuration of a package, you
have to ./Setup.lhs clean first, to make sure everything gets
recompiled.
Good Luck!
[1] http://www.mail-archive.com/cabal-devel@haskell.org/msg00282.html
[2] http://hackage.haskell.org/trac/hackage/wiki/CabalConfigurations
More information about the cabal-devel
mailing list