Table of Contents
When tinc
is installed under /nix
or the environment variable TINC_USE_NIX
is set to yes
, it operates in Nix mode. Everything is installed under /nix
including:
- System dependencies for GHC
- GHC
- System and Haskell dependencies for your project (cabal packages)
- Your project
Essentially, tinc
does the following:
- Use
cabal
to generate an install plan from your.cabal
file. - Use
cabal2nix
to generate Nix derivations for all dependencies in the install plan. These Nix derivations are stored in$HOME/.tinc/cache/nix
. - Use
cabal2nix
to generate Nix derivation from the project.cabal
. - Incorporate the previous Nix derivations and create the final project Nix files, including
default.nix
andshell.nix
. These files can be used as-is withouttinc
installed.
With the Nix files, you can:
- Run
nix-shell
to enter an environment with all the dependencies in scope, which allows you to runghci
,cabal configure
,cabal build
,cabal test
, etc. - Run
nix-build
to build your project in/nix
.
It is probably not feasible to follow these steps perfectly because your cabal package index or nixpkgs will not be exactly the same, but the following describes the general steps for using tinc
to build a sample project:
- Imagine it is the end of May 2016. The latest version of QuickCheck is 2.8.2 when we update our cabal package index.
cabal update
- We checkout the state of our sample project at this time (any Haskell project should work):
git clone /~https://github.com/robbinch/tinc
cd tinc
git reset --hard 405af997c182b89edfc9656612c32616e98c7862
- We pretend we do not have any
.nix
ortinc.freeze
files:
rm -f *.nix tinc.freeze
- Let
tinc
generate the Nix files:
export TINC_USE_NIX=yes
tinc
- We can now use
nix-shell
to configure, build or test the project:
nix-shell
cabal configure --enable-tests
cabal build
cabal test
exit
-
As it is common to run
nix-shell
right aftertinc
, the plugintinc shell
can be used to do this in one step. -
We can also use
nix-build
ornix-env
:
nix-build # will build project in /nix
nix-env -i tinc -f default.nix # will build and install project in profile
-
Instead of directly installing using
nix-env
, the plugintinc install
can and should be used. It does the extra steps of packaging usingcabal sdist
, extracting the tarball and resetting the file modification times before runningnix-env
. This creates a consistent derivation (Nix checksum) untainted by extraneous files in the development directory. -
It is recommended to keep all
.nix
files andtinc.freeze
under version control. That way, distributing them with your project gives users the best chance of building your Haskell project with Nix. They can simply donix-build
ornix-env
without havingtinc
installed. They can even use the same commit ofnixpkgs
for better reproducibility. -
When you wish to update your project to use the latest cabal packages:
cabal update
rm *.nix tinc.freeze
tinc shell
- If anything goes wrong, you can revert back to the old
.nix
files to build your project again.
Sometimes, we get missing dependencies. Let's see the problem:
- Update to a more recent cabal package index (it's early November 2016 now). The latest version of QuickCheck at this time is 2.9.2.
cabal update
- Checkout a more recent project:
git clone /~https://github.com/robbinch/tinc
cd tinc
git reset --hard 411d0f319717d01dc71bd5c1faef8035656eaf3d
- Again, we pretend we do not have any
.nix
ortinc.freeze
files:
rm -f *.nix tinc.freeze
- Run
tinc shell
to generate Nix files and enter the build environment:
tinc shell
- We get a build error for QuickCheck. It needs the
semigroups
package but our Nix derivation$HOME/.tinc/cache/nix/QuickCheck-2.9.2.nix
does not have it. This is probably due tocabal2nix
not working properly with QuickCheck-2.9.2. Addsemigroups
to the list of dependencies:
{ mkDerivation, base, containers, random, stdenv, template-haskell
, test-framework, tf-random, transformers
, semigroups # <-- add here
}:
mkDerivation {
pname = "QuickCheck";
version = "2.9.2";
sha256 = "119np67qvx8hyp9vkg4gr2wv3lj3j6ay2vl4hxspkg43ymb1cp0m";
libraryHaskellDepends = [
base containers random template-haskell tf-random transformers
semigroups # <-- add here
];
testHaskellDepends = [
base containers template-haskell test-framework
semigroups # <-- add here
];
homepage = "/~https://github.com/nick8325/quickcheck";
description = "Automatic testing of Haskell programs";
license = stdenv.lib.licenses.bsd3;
doCheck = false;
doHaddock = false;
}
-
Run
tinc shell
again. This time, we encounter similar problems withattoparsec
, among others. Fix them the same way in$HOME/.tinc/cache/nix
. -
After all the missing dependencies are added,
tinc shell
will hopefully be successful and we get working Nix derivations again. Put the.nix
files under version control so we do not need to repeat this in future.
Plugins are simply shell scripts named like tinc-shell
or tinc-install
in $HOME/.tinc/plugins
. They are executed with commands like tinc shell
or tinc install
. The standard plugins are provided in the plugins
directory of the source code and can be copied or symlink-ed to $HOME/.tinc/plugins
.
To override attributes (like doCheck
, configureFlags
, postInstall
, etc) in the generated default.nix
, create the file default-override.nix
. tinc
will never overwrite this file but default.nix
will use it if it exists. See example in tinc
repository.
Instead of using cabal's solver to generate the install plan, you can opt for curated packages from Stack. Just download cabal.config
from one of the LTS resolvers and place it beside your project .cabal
.
wget https://www.stackage.org/lts-7.16/cabal.config
tinc shell