Installing and Running Multiple GHC Versions
Posted on July 9, 2018In my roles both as a library author and as a Hackage Trustee, I find myself needing to run builds against multiple versions of the Glasgow Haskell Compiler on a daily basis. I thought it would be worth putting together a post on how I manage my installations of GHC and associated tools like cabal-install.
Ubuntu
The easiest distribution on which to install multiple GHC versions is Ubuntu. I have an Ubuntu virtual machine on a server, onto which I offload some slow builds so as not to tie up my local work machine. Herbert Valerio Riedel has set up an Ubuntu PPA from which one can install multiple GHC, cabal, happy, and alex versions. These will happily sit side-by-side, and the PPA page offers documentation on switching what the ghc
symlink points to.
After adding the PPA to my repositories by following the instructions, I installed the software I needed with a command something like the following:
sudo apt install ghc-8.4.3 ghc-8.2.2 ghc-8.0.2 ghc-7.10.3 ghc-7.8.4 ghc-7.6.3 ghc-7.4.2 ghc-7.2.2 ghc-7.0.4 alex-3.1.7 cabal-install-2.2 happy-1.19.5
Update (2018-07-11) Herbert has informed me that he also has a repository for Debian.
NixOS
On our work stations, my team and I run NixOS, a Linux distribution managed using the functional programming language Nix. In my configuration.nix
file, I have two pinned snapshots of nixpkgs - one for providing rather old GHC versions, and one for providing bleeding-edge GHC versions.
The following is an excerpt of my configuration.nix
file:
{ config, pkgs, ... }:
let
oldghcs = import (fetchTarball https://github.com/NixOS/nixpkgs/archive/83b35508c6491103cd16a796758e07417a28698b.tar.gz) {
config = config // { allowBroken = true; };
};
newghcs = import (fetchTarball https://github.com/NixOS/nixpkgs/archive/f682ff93a2778f101d93b68c97278f902523758a.tar.gz) {
config = config // { allowBroken = true; };
};
in {
environment.systemPackages = with pkgs; [
oldghcs.haskell.compiler.ghc704
oldghcs.haskell.compiler.ghc722
oldghcs.haskell.compiler.ghc742
oldghcs.haskell.compiler.ghc763
oldghcs.haskell.compiler.ghc784
haskell.compiler.ghc7103
haskell.compiler.ghc802
haskell.compiler.ghc822
newghcs.haskell.compiler.ghc843
newghcs.haskell.compiler.ghc861
# other entries...
];
# other configuration...
}
This setup gives me every major compiler version back to GHC 7.0. newghcs
was simply the most recent commit in nixpkgs when I set it up, and that is where I get GHC 8.4.3 and GHC 8.6 alpha, since they are not in my main nixpkgs, which is nixos-18.03. oldghcs
is a commit carefully chosen from history, as the following commit dropped GHC 7.2.2 from nixpkgs, and I wanted to have the latest release in the GHC 7.2 series installed. nixos-18.03 gives me 7.10.3
, 8.0.2
, and 8.2.2
Using these GHC versions
Using either of the above methods, we will find our GHC versions on the PATH
. To run GHC version 7.10.3, we run ghc-7.10.3
, and the same pattern works for other versions.
When I want to build one of my projects using a particular GHC version, I configure cabal using the the -w
flag (or its long form --with-compiler
). I use cabal’s nix-style local builds for all my Haskelling. This is also known as the cabal new-build workflow, and it was added in cabal 1.24. My invocations look like this:
cabal new-configure -w ghc-8.2.2
This writes a cabal.project.local
file, so subsequent calls to cabal new-build
, cabal new-test
and so on will use the configured GHC version. To change to another GHC version, we can run cabal new-configure
again with a different GHC version specified. This way, I can install all my GHCs side-by-side, and choose whichever I need to for what I want to build.
A GHC version can also be fixed on a per-project basis using a cabal.project
file. For example, if we want to use ghc-8.0.2
for our project, we can include this cabal.project
file:
and cabal will use ghc-8.0.2
without us needing to specify via -w
.
Conclusion
That’s how I install and run multiple different GHC versions on my systems.
Happy Haskell Hacking!
We’re using functional programming to set up the infrastructure that we use from day to day.
> George Wilson
George Wilson is an enthusiastic programmer at the Queensland Functional Programming Lab. George enjoys writing code, and speaking and writing about Haskell and functional programming.