Sunday, November 6, 2011

Virtual Haskell Environment

I am pleased to announce the first public release of the virthualenv tool.

virthualenv is a tool (inspired by Python's virtualenv) to create isolated Haskell environments, similar in purpose to tools like cabal-dev. You can read more about it on hackage, or in README, available on github.

Why did I bother with writing it, when there's already cabal-dev available? Back in July, I decided to start writing in Haskell again, so I picked up one of my projects and tried to build it. But as usual, too many installed packages and it failed. I knew, I needed something to keep separate environments for every project, something like Python's virtualenv. There were two such tools for Haskell: capri and cabal-dev. capri was just a toy. cabal-dev was unusable on two (all of them) of my projects, for two different reasons (I have to mention, that cabal-dev >= 0.8 works fine). But even if cabal-dev would work back then, I hated the way it worked/works. Before I understood why it wouldn't work with my project (no cabal configure flag switches), I had to consult the readme file, seek help on #haskell. Python's virtualenv was simpler, I had to learn two commands and the environment was ready and activated, then I could work as I worked with Python code before using virtualenv. No new commands, no new switches, no manual reading — it just worked. I wanted something like this for Haskell. After reading capri sources I realized, that it was really easy (and cabal-dev was overcomplicated) and I could create a bash script to do it in a couple of hours. And I did. Then I rewrote it in Haskell, made it user-friendly and added new features. The only thing missing was a README file. Unfortunately (for the project, for me it was very fortunate), some things happened and I didn't have the time and/or motivation to finish the project. But I was tired of having so many dead projects and decided to finally release it.

Is it still needed when cabal-dev-0.8 is in a usable state? I think so. Here's why:

* It's simpler than cabal-dev so there's less code.
* It's simpler to use, regular user can create an environment with a single word command, activate it using another, provided command and then can work just like he's used to. "How do I install a package?" — "Use 'cabal install'.". "How do I check what packages are installed?" — "Use 'ghc-pkg list'.". "How do I ...?" — "Like you always did".
* It will be familiar to people coming from Python.
* Because of its nature (manipulating environment vars), you continue to use the same binaries (or wrappers). This means things like bash completion continue to work without any extra setup.
* There's a simple emacs mode included (virthualenv.el). It was trivial to write, even for such an elisp-noob like me. It was simple because of how simple setting two env vars is, there was no need to modify haskell-mode at all. Emacs integration is very important for me, maybe other emacs people are ok with using cabal-dev only from the terminal, but I prefer typechecking my code using simple keyboard shortcut from emacs, with the regular things like jumping to error locations and other goodies. ghci embedded in emacs also works just fine. I don't know what vimers do with Haskell code, but it's probably equally trivial to write a vim plugin for virthualenv (just fork a virtualenv plugin and you'll be 80% done).
* There's a nice feature, not available in cabal-dev — using external GHC from compiled tarball. It's the easiest way (or so I believe) to do things like testing your code with a different version of GHC (even nightly builds!).

Are there any disadvantages to using this over cabal-dev? Unfortunately yes. First, it's a new project, it hasn't been tested by anyone beside me, so there can be bugs (please report them on github). The bigger disadvantage is portability. I've tested it only on i386 Linux and FreeBSD (a little). It should work on every Linux, if it doesn't, I can probably fix it. Other unices like *BSD, Solaris and whatever else is there should also work, but I haven't tested it, due to no available machines with those OSes. It could work on MacOS X using system's GHC (already installed one) (at least I think so, since it's derived from BSD). MacOS X and GHC from tarball will probably not work, since it doesn't use regular tarballs, and I have no idea how those .dmg files work. As usual, Windows works completely different, so it would need some research and probably a lot of new code to make it work there.

What will I do with this project? Currently, it satisfies all my needs, so I can focus on other projects. But, if other people (it means you!) start to use it, I will try to fix all bugs, develop some new features (I have a few ideas on github, but you can tell me yours as well) and work on porting it to MacOS X and Windows (I'd need access to such machines though).


  1. A small usage example would be nice I think. Could you post an example session, please?

  2. I don't know if this is what you want, but there are examples in the readme file on github:

  3. Can we use virtualenv for projects which include ghc itself?

    IOW if I am hacking inside ghc sources but there are other projects that require a stable ghc?

  4. I have no idea how hacking on a ghc works. do you install it with "configure --prefix=PATH; make install"? and you want to test that version, but without affecting other projects? currently, virthualenv can only install ghc from a tarball, but if you need this feautre, I'll try to add an option to use already installed, custom ghc version.

  5. I should perhaps mention that it goes something like
    1. some pre-preparations for libraries etc (dunno exactly what)

    2. ./configure --prefix=...

    3. make

    4. make install

    Between 3 and 4 ghc is made but not installed in the path specified in 2
    Often one wants to use that newly made ghc which sits in /path/to/ghc/inplace/bin/ghc-stage2 without installing