Skip to content

Old: Cabal 2

Edward Z. Yang edited this page May 1, 2017 · 1 revision

Imported from Trac wiki; be wary of outdated information or markup mishaps.

Cabal 2.0

This page is to collect ideas for the design of Cabal 2.

Goals

  • Cleaner design.
  • More flexible
  • Handle bigger packages
  • Handle multiple packages

Important interfaces

The .cabal file format.

The API for loading, parsing and manipulating .cabal files. This is perhaps more important than the actual .cabal file format since the format can be extended, but the API for handling them should be easier to track.

The command line interface to packages using custom build systems. This has to be used by package managers like native package build scripts and cabal-install. This needs to be clearly defined because it is the interface that allows multiple build system implementations. It is important that the interface be usable by programs not just human users. For example sdist directly calling tar is a convenience for humans but causes problems for automatic tools like cabal-install which must call tar itself. See Custom build interface.

Use cases

Building a bunch of related packages

For example having several .cabal files in a single directory, or having a subdir per-package.

For example the gtk2hs project consists of several packages, each in a subdirectory:

gtk2hs/
gtk2hs/glib
gtk2hs/gtk
gtk2hs/...

Then from the top level gtk2hs directory we want to be able to cabal build and build all the packages. We also want to be able to rebuild after editing any files in any of the packages. Of course we also want to be able to build specific targets like (lists of) modules or packages, eg cabal build gtk.

This implies:

  • tracking dependencies across all the pakcages
  • registering libraries in a local package db
  • some mechanism to specify the search path for packages

In the case of several .cabal files in a single directory we can assume that all of the packages are related and to be built together. In more complex cases we probably need a more explicit way of specifying where to find packages. The fallback is always to existing pre-installed packages (ie from the global or per-user package db). A "metapackage" file could be used for this purpose, to list the paths to the packages we want to build together.

It is vital however that any stuff we add to make it easier for developers to hack on multi-package projects does not end up with having to build them together in a single build tree. The package must remain the unit of distribution so different packages have to be able to be distributed as independent tarballs and built and installed separately on other machines.

Note this is not the same thing as "shipments", see #35.

Restructuring

One thing that might help to clarify the design is to change the way we partition the functionality into packages. Currently we have these packages:

  • Cabal.

    • Contains the declarative parts, types, parsers, pretty printers and pure utils.
    • Also contains the 'Simple' build system and 'Make' build system for delegating to make-based build systems.
    • Also contains the command line interface to the above two build systems.
  • cabal-install

    • Extra command line interface features
    • Primitive package management features.
    • Hackage client functionality
    • Package dependency constraint solver.
    • Depends on Cabal, zlib, HTTP
  • cabal2native tools (for arch, rpm, deb, ebuild).

    • Translates cabal descriptions into native package descriptions
    • Some tools also include hackage client functionality
    • Depends on Cabal

There are a number of criticisms of this organisation. The declarative part of Cabal is included in the same package as the 'Simple' build system. The declarative part is an important API and is relatively stable. The 'Simple' build system has no real stable API. Also, keeping them in the same package leads to confusion over whether the 'Simple' build system is the only one that can be used.

Another criticism is that the names are confusing. The 'cabal' command line program is contained in the 'cabal-install' package, not the 'Cabal' package.

So one option would be to split the Cabal package into at least two parts, one for the declarative part and one for the 'Simple' build system.

  • cabal-lib

    • Contain only the declarative parts, the .cabal file data structures, parser and pure functions for manipulating them.
    • Strictly no IO!!
  • cabal-build

    • Contain the 'Simple' build system API
    • Also contain the command line interface for it (but there should be a strict internal separation).
    • Depends on cabal-lib
  • hackage-client

    • library for working with the hackage server and packages
    • functionality for package repositories, downloading
    • Package dependency constraint solver.
  • cabal

    • The primary user command line tool.
    • Package managment functionality.
    • Depends on cabal-lib, cabal-build and hackage-client
  • cabal2native tools.

    • Depend on cabal-lib

Command line interfaces

The command line interface for users would be only the cabal command, from the cabal package.

The Setup.hs command line interface would be exclusively for tools like package manager scripts, custom build systems, cabal etc.

Related resources

TODO: links to relevant mailing list discussions, particularly criticisms of the existing design.

Misc ideas / notes

  • Specify the lexical structure of fields, a limited number of lexical field types, so that the whole field does not need to be parsed. Examples: free-form (description), list of tokens (flags), list of multi-tokens (deps)

  • Related to above, allow layout for lists of tokens, to make the comma optional in lists of deps if they're on separate lines. Allow trailing commas?

  • Should document clearly what we expect from Haskell packages, e.g. if we expect to be able to link multiple versions into a single package. Means we ought to check and enforce no symbol clashes, see issue #693.