Skip to content

Latest commit

 

History

History
145 lines (116 loc) · 6.22 KB

README.md

File metadata and controls

145 lines (116 loc) · 6.22 KB

UPDATE: We recommend that people move away from cabal-dev, now that cabal-install supports sandboxes natively (in versions >= 1.18). Here's a blog post that describes how to use cabal-install sandboxes: http://chromaticleaves.com/posts/cabal-sandbox-workflow.html

Cabal Dev

Motivation

Performing consistent builds is critical in software development, but the current system of per-user and per-system GHC package databases interferes with this need for consistency. It is difficult to precisely identify the dependencies of a given project, and changes necessary to enable one project to build may render another project inoperable. If each project had a separate package database, each project could be built in a sandbox.

Usage

Cabal-dev is simple to use:

$ cd <cabalized project dir>
$ cabal-dev install

Cabal-dev will create a default sandbox named cabal-dev in the current directory. This will be populated with the project dependencies, which are built and installed into a package database within the sandbox. The first cabal-dev build of a project typically takes substantially longer than subsequent builds--don't worry, the artifacts created will be re-used on subsequent builds unless you remove the sandbox, or specify a different sandbox (with --sandbox= at the command line or the CABAL_SANDBOX environment variable; the command line flag takes precedence).

The project is then built, utilizing the sandboxed package database rather than the user database. (The GHC system database is still used. We recommend that only the core packages be installed to the system package database to reduce the potential for conflicts.)

cabal-dev install uses cabal-install to issue build and installation commands that place the project's build artifacts in the cabal-dev sandbox, as well as leaving the binaries in the familiar dist directory.

If you are developing multiple interdependent packages together, see the section below about building with private dependencies.

See cabal-dev --help for detailed usage information.

Ghci with cabal-dev

Cabal-dev 0.7.3.1 and greater are capable of launching ghci with the project's package database and local modules (if the package under development exposes a library).

# First, you must cabal-dev install the package to populate the
# package database:
$ cabal-dev install
....
<snip>
....
$ cabal-dev ghci
GHCi, version 6.12.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package ffi-1.0 ... linking ... done.
Prelude>

The ghci shell should have access to all the libraries your application/library is using, as well as any modules that your library exposes.

Note that this is not quite as natural as your traditional ghci shell, namely: Source modifications are not visible without exiting, re-issuing cabal-dev install and cabal-dev ghci. This will eventually get better, but that's where things are right now. The reason for this is that cabal-dev ghci just issues ghci with the cabal-dev package database (and excluding the user package db, to best reflect what cabal-dev does when it causes compilation).

Building with private dependencies

Cabal-dev supports two different workflows for using un-released packages. The first makes the dependencies available in a sandbox-local Hackage. The second rebuilds the dependent package every time. If any of your private dependencies are unchanging (e.g. you had to patch a dependency to relax a package constraint) you will probably want to use add-source. If you are actively developing two packages that have dependencies on each other, you probably will prefer the second. You can mix and match these techniques seamlessly.

Using a sandbox-local Hackage

Cabal-dev also allows you to use un-released packages as though they were on hackage with cabal-dev add-source.

For example, the linux-ptrace and posix-waitpid packages were only recently uploaded to hackage. Previously, cabal-dev was used to build applications that depended on these two packages:

$ ls
linux-ptrace/  myProject/  posix-waitpid/
$ cd myProject
$ cabal-dev add-source ../linux-ptrace ../posix-waitpid
$ cabal-dev install

Note that cabal-dev add-source accepts a list of source locations.

Be careful, however, because packages that have been added are not tied to their original source locations any more. Changes to the linux-ptrace source in the above example will not be used by myProject unless the user issues cabal-dev add-source with the path to the linux-ptrace source again. This is similar to the cabal install step you may do now to enable a project to make use of changes to a dependency.

There is currently one additional requirement when using cabal-dev add-source. The projects that are add-source'd must generate sdists that will build. Cabal-dev currently uses sdists to transport the dependencies into the sandbox, so the project will not build if critical files are left out of the sdist. Note that the packages do not need to sdist cleanly, most warnings are acceptable, so this is rarely a problem.

Building multiple packages together

For packages that are being actively developed together, recent cabal-install (> 0.10) provides another option: specify all of the source directories together on the cabal-install command line. For example, say we're developing a Web application that depends on a helper package that we use for other Web projects as well. We keep making changes to both the application and its helper package. To build both packages together:

$ ls
my-webapp/  webapp-helpers/
$ cabal-dev install my-webapp/ webapp-helpers/

Note that this is a feature of newer cabal-install and is not limited to use with cabal-dev, but cabal-dev makes it more useful by keeping the development code isolated from other builds.

The disadvantage of this approach is that it can be slow. When you have not made changes to a dependency, cabal-install will re-link and reinstall it anyway (although it does avoid recompilation when it's not necessary). Use the add-source mechanism if you have a dependency that changes very infrequently.