Skip to content
This repository

A somewhat different approach to cabal hell problem.

branch: master

Fetching latest commit…


Cannot retrieve the latest commit at this time

Octocat-spinner-32 Hellno
Octocat-spinner-32 .gitignore
Octocat-spinner-32 Hellno.hs
Octocat-spinner-32 Main.hs
Octocat-spinner-32 README
Octocat-spinner-32 hellno.cabal

Please bear with me. The approach is different from the numerous sandboxing
tools we have in that it aims to avoid recompilation by keeping a database of
precompiled packages. The database can hold several variants of the same package
version compiled against different dependencies.

Generally, with hellno you'll get the same result as for blowing away your user
package database and doing a nice clean install but without having to recompile
everything and with ability to easily revert back and change between projects.

For example, suppose you have a project that uses yesod- and you want to
upgrade to the latest You change your project.cabal, run hellno setup
and get:
$ hellno setup
61 fixed packages, 98 other packages required.
Using 60 precompiled packages, installing 38
Which says that you will only compile 38 packages instead of the 98 you would
have to wait to finish building if you just had deleted your sandbox/user db.

One might argue that with a sandbox you can force reinstalls and get basically
the same result, but this would result in lots of broken packages cluttering
your sandbox (and after a couple upgrades it will become big and messy so you
will probably delete it to start over anyway) and, more importantly, this can't
be safely done to a shared sandbox without fearing of something breaking. You
can still get away by using per-project sandboxes, though each one can be up to
about 100M in size.

When you ask hellno to setup the environment for a project it will run
cabal --dry-run to determine the required dependencies and then put the symlinks
to .conf files in ~/.ghc/i386-linux-7.4.1/package.conf.d/ (or wherever your
GHC keeps them) and links to the lib directories in $user_install_prefix/lib.


Hellno has a set of packages it calls "fixed", those are usually the core
libraries that are installed globally. Any package that wasn't installed by
hellno is treated as fixed. That means that you should strip your package
database to the bare minimum. Blow away (or backup if you care about it) your
user database (rm -f ~/.ghc/i386-linux-7.4.1/package.conf.d/* &&
rm -rf ~/.cabal/lib/*). Then run ghc-pkg check to ensure that your fixed
packages are in consistent state. Now you're ready to run hellno.


In a nutshell, use "hellno setup" to switch between projects,
"hellno local-install" to install local packages and "hellno depclean" to clean
up the hellno package storage. In more detail:

Let's say your project doesn't depend on any local packages (local meaning not
on Hackage). In your project directory just run
$ hellno setup
This will bring in all required dependencies, possibly using precompiled
packages. If you already ran "hellno setup" for this project (and didn't change
the cabal file or run cabal update), this won't have to compile anything.
Alternatively, you can pass the list of cabal files to hellno setup like you
would to cabal-install and work on several projects without having to switch,
but if their dependencies can't coexist, it will fail.

Now suppose you have a local lib named foo. Go into its directory and run
$ hellno local-install
(this will require cabal-install-src being in your PATH). Now you can run
hellno setup for projects depending on foo.
After you change something in foo you have to run local-install again, as hellno
(and cabal) has no way of knowing that foo changed.

With time you'll likely decide that your ~/.cabal/hellno/ has grown way too big.
To deal with this, you can use "hellno depclean", passing it the projects you're
currently working on (unless you want to compile their dependencies again).


Hellno will take care of a package's executables, but only if it also has a
library. This is done to simplify the code a bit, under the assumption that an
executable-only package cannot be a dependency. Even cabal info won't tell you
whether an executable-only package is intalled, since it only tracks libraries.

Some of the known issues/limitations:
 - Version tags not supported.
 - Error handling is bad.
 - Since cabal --dry-run tries to use the latest package versions, you get
   different results from "hellno setup" after running "cabal update", which
   is actually not that bad a way to update your deps, so maybe this is not
   an issue after all.

 - Rewrite this README so that I stop feeling the urge to put
   *** LATE NIGHT WRITITNG ALERT *** on top of it.
Something went wrong with that request. Please try again.