Building Haskell projects for Nix
Similar to the last post on building a C project, today I quickly cover how to build a Haskell project.
You might ask why? I got asked about that stuff by my friendly office colleague Samuel. By the way, without him I would have never installed/used Nixos in the first place. Good fella, go checkout his blog.
#packaging #coding #nix #haskell
The goal was to package oama
. Oama helps you to renew OAuth2 tokens from the command line. To be honest, I haven't checked the details on how it works yet, I was only interested in packaging it for Nix.
I was reading a bit on how it can be used with my favorite msmtp
client.
Then I read some of the Nix documentation on how to build and use Haskell packages. They describe how to quickly bootstrap development environments (i.e., a Nix shell) using the handy cabal2nix
utility.
The first step for packaging was also to convert the cabal
description of the package into a valid Nix expression which already proved useful for development purposes.
git clone https://github.com/pdobsan/oama.git oama.git
cd oama.git
cabal2nix . > oama.nix
Create default.nix
:
# Retrieve nixpkgs impurely from NIX_PATH for now, you can pin it instead, of course.
{ pkgs ? import <nixpkgs> {} }:
# use the nixpkgs default haskell package set
pkgs.haskellPackages.callPackage ./oama.nix { }
If you have a look at oama.nix
it contains a lot of references to Haskell packages (.e.g, haskellPackages.aeson
). The callPackage
takes care of the name resolution in this case. haskellPackages.mkDerivation
is a wrapper around stdenv.mkDerivation
(see last post building a C project), but works without the standard Haskell build tool cabal-install
.
To build oama
and quickly run it in a shell:
nix-shell -p cabal-install
nix-build default.nix
./result/bin/oama
I did not look further into shellFor
at this point, because I was interested in creating a Nix package that I can install globally.
For this, I took the “stdenv template” from the last post and merged 😻 it with the oama.nix
output from cabal2nix
. The result:
let
pkgs = import <nixpkgs> { };
hpkgs = pkgs.haskellPackages;
in
hpkgs.mkDerivation {
pname = "oama";
version = "0.10.1";
src = pkgs.fetchgit {
url = "https://github.com/pdobsan/oama.git";
rev = "refs/tags/0.10.1";
hash = "sha256-mQBlCrF9rvFOfSOxhMi6JUKDJocFmO4Hhc3Zy7AqiXk=";
};
isLibrary = true;
isExecutable = true;
libraryHaskellDepends = with hpkgs; [
aeson base bytestring containers directory hsyslog http-conduit
network-uri optparse-applicative pretty-simple process string-qq
strings text time twain unix utf8-string warp yaml
];
executableHaskellDepends = with hpkgs; [
aeson base bytestring containers directory hsyslog http-conduit
network-uri optparse-applicative pretty-simple process string-qq
strings text time twain unix utf8-string warp yaml
];
mainProgram = "oama";
license = pkgs.lib.licenses.bsd3;
}
Essentially, I only had to use nix-prefetch-git
to get the shasum of the git revision and make sure I use the pkgs
and hpkgs
(reference to pkgs.haskellPackages
) correctly in the right places.
Afterwards, again, building and installing oama
globally was a peace of cake 🧁:
nix-build oama.nix
nix-env -i -f oama.nix
Now I only have to figure out what to do with this tool 🤔 but this is left for another post.