Example

Dan Burton edited this page Apr 9, 2015 · 1 revision
Clone this wiki locally

Example

Let's say I want to see if I can compile my project against the latest in the LTS 1 series. For the sake of demonstration, let's pretend that semigroups is my project. :P

$ cabal unpack semigroups-0.16.2.2
$ cd semigroups-0.16.2.2
$ stackage sandbox init lts/1
Writing a default package environment file to
/home/dan/semigroups-0.16.2.2/cabal.sandbox.config
Using an existing sandbox located at
/home/dan/.stackage/sandboxes/ghc-7.8.4/lts-1.15

stackage sandbox init wrote a cabal.config and a cabal.sandbox.config for us.

The latest in the lts/1 series is lts-1.15, and I've already installed some things in that sandbox before.

$ cabal install --only-dependencies
Resolving dependencies...
Notice: installing into a sandbox located at
/home/dan/.stackage/sandboxes/ghc-7.8.4/lts-1.15
Configuring nats-1...
Building nats-1...
Installed nats-1

Some of the dependencies of my project were already installed in the sandbox. But nats was not. Cabal gives us a nice notice about where the sandbox is located when it performs the install. Note that it picked nats-1 because that's what our generated cabal.config told it to pick.

$ cat cabal.config | grep nats
             nats ==1,

When working with shared sandboxes, I recommend using cabal build and avoiding cabal install. Semigroups is actually already part of stackage. What happens if we cabal install it?

$ cabal install
...
Installed semigroups-0.16.2.2

As it happens, the version number in my local semigroups.cabal matches the constraint in cabal.config.

$ cat cabal.config | grep semigroups
             semigroups ==0.16.2.2,

So if you try to cabal install a local project into a shared sandbox, it will work, as long as the local cabal.config constraint agrees with the version number found in yourproject.cabal. You probably don't want to install local modifications into your shared sandbox, which is why I recommend using cabal build instead of cabal install to build your local projects.

Let's go ahead and remove that from our sandbox db.

$ stackage sandbox unregister semigroups

stackage sandbox unregister is just a wrapper around ghc-pkg unregister that conveniently detects the location of your sandbox package-db and passes it in as an argument for you. You can see what's in the sandbox with stackage sandbox list:

$ stackage sandbox list
/home/dan/.stackage/sandboxes/ghc-7.8.4/lts-1.15/x86_64-linux-ghc-7.8.4-packages.conf.d
   hashable-1.2.3.2
   nats-1
   text-1.2.0.4
   unordered-containers-0.2.5.1

Again, just a light wrapper around ghc-pkg.

Let's see what happens when we try to install an older version of semigroups:

$ cd ..
$ cabal unpack semigroups-0.16.2.1
$ cd semigroups-0.16.2.1
$ stackage sandbox init lts-1.15
Writing a default package environment file to
/home/dan/semigroups-0.16.2.1/cabal.sandbox.config
Using an existing sandbox located at
/home/dan/.stackage/sandboxes/ghc-7.8.4/lts-1.15
$ # notice it reused the same lts-1.15 sandbox
$ cabal install --only-dependencies
...
rejecting: semigroups-0.16.2.2/installed-c36..., 0.16.2.2 (global constraint
requires ==0.16.2.1)
rejecting: semigroups-0.16.2.1 (global constraint requires ==0.16.2.2)
...

First of all, cabal install --only-dependencies failed, because even though I specified only dependencies, cabal is mad at me for trying to install the wrong version of semigroups. Which I'm not... but whatever.

I can use cabal install dep1 dep2 dep3 to manually install the dependencies I need. But since this is a shared sandbox, I already have those dependencies installed from last time.

Thankfully, cabal isn't as annoying about cabal build.

$ cabal build

It builds! But if you try to install...

$ cabal install
...
rejecting: semigroups-0.16.2.2/installed-c36..., 0.16.2.2 (global constraint
requires ==0.16.2.1)
rejecting: semigroups-0.16.2.1 (global constraint requires ==0.16.2.2)
...

It will stop you, because you're trying to install a version of semigroups that differs from the constraint in lts-1.15, which your local cabal.config is enforcing for you. This is good. We don't want to mess up the shared lts-1.15 sandbox.

Notice that stackage is allowing us to do something that has traditionally been quite difficult: running a build as though we had rolled back hackage to some point in the past. We can select a stackage snapshot from any point in time, and build stuff against it. Like cabal freeze, we can use stackage snapshots as a reference point to share build strategies with other people. Unlike cabal freeze, stackage snapshots are predetermined and public. If you and I both develop our projects against the same stackage snapshot, then we can prevent the "cabal butterfly effect".

Sandbox management via stackage sandbox extends these benefits of stackage to shared sandboxes. By sharing sandboxes, we can strike a balance between the extremes of installing everything in userspace, and installing everything in a new sandbox for every project. Of course, if you are doing weird stuff with your sandbox for a given project, you might not want to share that sandbox with your other projects. But for projects that you simply want to build against a given stackage snapshot, stackage sandbox is for you!