[Haskell-cafe] 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.


/ Thomas


[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 

Before installing you might want to hide the current cabal package  
using (tt shouldn't be necessary, though) via

   $ ghc-pkg hide Cabal


   $ 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


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
         See synopsis.
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.


$ ./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  

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 Haskell-Cafe mailing list