Reproducible Development Environments with GNU Guix

November 08, 2014

If you’re a software developer, then you probably know very well that setting up a project’s development environment for the first time can be a real pain. Installing all of the necessary dependencies using your system’s package manager can be very tedious. To "solve" this problem, we have resorted to inventing new package managers and dependency bundlers for pretty much every programming language. Ruby has rubygems and bundler, Python has pip and virtualenv, PHP has composer, node.js has npm, and so on. Wouldn’t it be nice to instead have a single package manager that can handle it all? Enter GNU Guix, a purely functional package manager and GNU/Linux distribution. Using Guix, you can easily create a development environment for any software project using the guix environment tool.

guix environment is a new utility added in Guix 0.8, which should be released in a few weeks. It accepts one or more packages as input and produces a new shell environment in which all of the dependencies for those packages are made available. For example, guix environment emacs will get you everything you need to build GNU Emacs from a source release tarball. By default, your $SHELL is spawned, but you may opt to use any arbitrary shell command instead. If you’ve used Nix before, you may notice that this sounds exactly like nix-shell, and that’s because it was what inspired me to write guix environment.

Now, let’s take a look at an example. One of my hobby projects is Sly, a game engine written in Guile Scheme. Here’s the relevant Guix code that will produce a complete development environment:

    ;;; Copyright (C) 2014 David Thompson <>
    ;;; Sly is free software: you can redistribute it and/or modify it
    ;;; under the terms of the GNU General Public License as published by
    ;;; the Free Software Foundation, either version 3 of the License, or
    ;;; (at your option) any later version.

    (use-modules (guix packages)
                 (guix licenses)
                 (guix build-system gnu)
                 (gnu packages)
                 (gnu packages autotools)
                 (gnu packages guile)
                 (gnu packages gl)
                 (gnu packages pkg-config)
                 (gnu packages sdl)
                 (gnu packages maths)
                 (gnu packages image))

    ;; The development environment needs a tweaked LTDL_LIBRARY_PATH
    ;; for finding libfreeimage.
    (define freeimage
      (package (inherit freeimage)
         (list (search-path-specification
                (variable "LTDL_LIBRARY_PATH")
                (directories '("lib")))))))

      (name "sly")
      (version "0.0")
      (source #f)
      (build-system gnu-build-system)
       `(("pkg-config" ,pkg-config)
         ("autoconf" ,autoconf)
         ("automake" ,automake)
         ("guile" ,guile-2.0)
         ("guile-sdl" ,guile-sdl)
         ("guile-opengl" ,guile-opengl)
         ("gsl" ,gsl)
         ("freeimage" ,freeimage)
         ("mesa" ,mesa)))
      (synopsis "2D/3D game engine for GNU Guile")
      (description "Sly is a 2D/3D game engine written in Guile Scheme.
    Sly differs from most game engines in that it emphasizes functional
    reactive programming and live coding.")
      (home-page "")
      (license gpl3+))

You may have noticed that the source field has been set to false. This is because the package is not for building and installing. It’s sole purpose is to provide the necessary software needed to build Sly from a fresh git checkout.

Assuming this code is in a file called package.scm, you can simply run guix environment -l package.scm to spawn a shell for hacking on Sly. By default, the environment created is an augmented version of your pre-existing shell’s environment. This is convenient when you want to use your installed software in the new environment, such as git. However, it’s important to make sure that the environment really does have everything needed for development without relying on any impurities introduced by your existing environment. Without verifying this, new developers might be frustrated to find out that the environment provided to them is incomplete. To verify, pass the --pure flag and build from scratch.

So, guix environment is a pretty nice way to acquire all the dependencies you need to work on a project, but there is still a lot of room for improvement. What if you were working on a web application that required a running PostgreSQL database, Redis server, and XMPP server? It would be really great if Guix could handle setting this up for you, too, a la Vagrant. To do so, guix environment could use the existing features of guix system to spawn a new virtual machine that shares the host system’s package store and the project’s source tree, and then spawn a shell with your development environment. I hope to implement this in the not-too-distant future. Until next time, happy hacking!

Read the discussion about this post on Hacker News.