A package author must fulfil the specification of Section 4. In many cases, a Haskell package will consist of nothing more than a bunch of Haskell modules, with perhaps the odd C file. In that case, the Cabal provides a simple build infrastructure that fulfils the specification of Section 4, and provides some modest further facilities besides.
This simple build infrastructure is meant to automate the common case. (Think hmake.) The emphasis is on ``simple'': if you want something more elaborate, you can (a) modify the simple build infrastructure (which is written in Haskell) (b) use makefiles, or (c) implement something else entirely.
The simple build infrastructure works as follows. First, Angela puts the following Haskell file Setup.lhs in the root of her tree:
#! /usr/bin/env runghc > import Distribution.SimpleSecond, she writes a package description Setup.description in the syntax of Section 5.2, which describes the package and gives extra information to the simple build infrastructure.
Now Angela can build her package by saying
./Setup.lhs configure ./Setup.lhs buildShe can even install it on her own machine by saying
./Setup.lhs installShe can build a Cabal source distribution:
./Setup.lhs source-distThe full details are given in Section 5.3.
It is no coincidence that the interface is very similar to that for the setup script for an Cabal package distribution (Section 4). In fact, Distribution.Simple.defaultMain conforms to the specification of Section 4.2, and when it builds a distribution, it includes ./Setup.lhs in the tarball, ready to be run by Bob the Builder. However, Distribution.Simple.defaultMain of course implements a richer interface than that required by Section 4.2, because it's intended to support Angela as well as Bob. The full specification is in Section 5.3.
When using the simple build infrastructure, the package description file Setup.description contains not only the name of the package, its version and dependencies, but also a collection of information to explain to the simple build infrastructure how to build the package. This section gives the specific fields, and the syntax of those fields. For the general syntax of the file, please see Section 4.1.
Here is a sample package description file with all the fields understood by the simple build infrastructure:
-- Required Name: Cabal Version: 0.1.1.1.1-rain License: LGPL Copyright: Free Text String -- Optional - may be in source? Stability: Free Text String Build-Depends: haskell-src, HUnit>=1.0.0-rain Modules: Distribution.Package, Distribution.Version, Distribution.Simple.GHCPackageConfig C-Sources: not/even/rain.c, such/small/hands HS-Source-Dir: src Exposed-Modules: Distribution.Void, Foo.Bar Extensions: OverlappingInstances, TypeSynonymInstances Extra-Libs: libfoo, bar, bang Include-Dirs: your/slightest, look/will Includes: /easily/unclose, /me, "funky, path\\name" Options-ghc: -fTH -fglasgow-exts Options-hugs: +TH -- Next is an executable Executable: somescript Main-is: SomeFile.hs Modules: Foo1, Util, Main HS-Source-Dir: scripts Extensions: OverlappingInstancesThe Name, Version, License, and Copyright are compulsory.
All other fields, such as dependency-related fields, will be considered empty if they are absent. Any fields that the system does not understand will be ignored.
Note that in the future, though the Modules field will be available, it will not be necessary to provide it for building executables and libraries. Instead, the user will provide only the "Main-Is" field (for executables) and the "Exposed-Modules" field (for libraries). The system will chase down dependencies from those modules and include them in the library or source distributions.
The description file fields:
Table 3. Description File Fields
|version||[0-9.]+(-?)[-a-zA-Z]*: branch numbers, separated by dots, and optional tags separated by dashes.||188.8.131.52.5-foo-bar-bang|
|copyright||--FREE TEXT--||(c) 2004 Isaac Jones|
|license||GPL | LGPL | BSD3 | BSD4 | PublicDomain | AllRightsReserved||BSD3||If your license isn't on this list, use the license-file field.|
|license-file||--PATH--||doc/myLicense.txt||Specify the license you use as a relative path from the root of the source tree.|
|maintainer||--FREE TEXT--||T.S. Elliot <firstname.lastname@example.org>|
|stability||--FREE TEXT--||Don't hook this up to your coffee machine|
|executable||--FREE TEXT--||cpphs||For this Executable stanza, what is the name of the produced executable.|
|main-is||--PATH--||/foo/bar/bang/Baz.hs||The filename to look for the main module for this Executable stanza.|
|extra-libs||comma list of --FREE TEXT-- and spaces||libfoo, libbar , libbang||for non-haskell libraries that this package needs to link to|
|build-depends||package name (== | < | > | <= | >=) version||foo > 1.2, bar < 3.3.5, bang||If the version isn't listed, it's assumed any version is OK.|
|c-sources||--PATH--||/foo/bar/bang||C source files to build using the FFI.|
|include-dirs||--PATH--||"/foo/bar/ ,bang"||Not Yet Used|
|includes||--PATH--||/foo/bar/bang||Not Yet Used|
|hs-source-dir||--PATH--||src||A relative path from the root of your source tree. Look here for the Haskell modules.|
|modules||--MODULE LIST--||Foo.Bar, Bang.Baz, Boo||May not be necessary in the future, since we'll chase dependencies from exposed modules and main module.|
|exposed-modules||--MODULE LIST--||Foo.Bar, Bang.Baz, Boo||For a library package, which modules should be available for import by the end user?|
|extensions||OverlappingInstances | RecursiveDo | ParallelListComp | MultiParamTypeClasses | NoMonomorphismRestriction | FunctionalDependencies | RankNTypes | PolymorphicComponents | ExistentialQuantification | ScopedTypeVariables | ImplicitParams | FlexibleContexts | FlexibleInstances | EmptyDataDecls | TypeSynonymInstances | TemplateHaskell | ForeignFunctionInterface | AllowOverlappingInstances | AllowUndecidableInstances | AllowIncoherentInstances | InlinePhase | ContextStack | Arrows | Generics | NoImplicitPrelude | NamedFieldPuns | ExtensibleRecords | RestrictedTypeSynonyms | HereDocuments | UnsafeOverlappingInstances||ForeignFunctionInterface, Arrows||Not all extensions are understood by all Haskell Implementations|
|options-ghc||--OPTIONS--||-fth -cpp||For command-line options not covered under extensions, add them here, separated by whitespace.|
|options-nhc||--OPTIONS--||-P -t||For command-line options not covered under extensions, add them here, separated by whitespace.|
|options-hugs||--OPTIONS--||-98 +g||For command-line options not covered under extensions, add them here, separated by whitespace.|
Further details on some fields:
--PATH-- Paths are written in the Unix style, with directories separated by slashes, optionally ending in a filename. There are two kinds of paths supported: "Simple" and "Complex". "Simple" paths are alpha-numeric values separated by slashes (foo/bar/bang). More "Complex" paths such as those with spaces or non-alphanumeric characters must be put in quotes ("foo, /bar \//bang"). You should assume that the paths are case sensitive, though in practice this varies depending on the end user's file system.
--MODULE LIST-- A module list is a standard Haskell module name, without any file suffixes (.lhs or .hs). Each module should be separated by a comma.
--FREE TEXT-- You may put anything in these fields. For multi-line fields, start the subsequent lines with whitespace.
--OPTIONS--The exact syntax of the options field is dependent on the compiler you're using. Refer to your compiler's man page for details. Multiple options should be separated by whitespace.
On hidden modules: Hidden modules form part of the implementation of the package, but not its interface: a client of the package cannot import an internal module. The system still must derive their existence, or they must be listed explicity for two reasons: (a) to allow the global program invariant to be checked (see Section 2.2) and (b) to enable a build system or programming environment to find the source files.
This section gives the command line interface supported by Distribution.Simple.defaultMain. It supports all the commands described in Section 4.2, (except for "test" - FIX) and in addition the following:
Table 4. Extra commands supported by the simple build infrastructure setup script
Create a source tarball
Distribution.Simple.defaultMain provides interactive command-line help. For each command, a help string is available by typing "./Setup.lhs COMMAND --help".
The Haskell libraries that support the simple build infrastructure can, of course, also be re-used to make setup scripts that work quite differently. At one extreme is a setup script that immediately shells out into make, which does all the work.
To support this, Cabal provides a trivial setup library Distribution.Make, which simply parses the command line arguments and shells out into make. Marcus uses the following Setup.lhs
#! /usr/bin/env runhugs > module Main where > import Distribution.Make (defaultMain) > main = defaultMainAll the package description information is assumed to be known to the makefile system, and so does not appear in the setup script. Thus,
./Setup.lhs configure --ghcinvokes
./configure --with-hc=ghcSimilarly ./Setup.lhs build invokes make all And so on.
Marcus simply arranges that when his makefiles build a distribution, they include this simple setup script in the root of the distribution, where the Bob the Builder expects to find it.