This project now depends on the turtle
package in order to illustrate some
dependency management basics. The Main.hs
executable is a contrived program
that uses turtle
gratuitously for the echo
function:
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Turtle
main :: IO ()
main = echo "Hello, world!"
The release0.nix
file is the same as for the previous project except that we
now name our package project1
instead of project0
, and we've changed the
name of the corresponding nix file to project1.nix
rather than project0.nix
:
let
pkgs = import <nixpkgs> { };
in
{ project1 = pkgs.haskellPackages.callPackage ./project1.nix { };
}
... the contents of our project1.nix
file have changed as well. This is because our
project1.cabal
file now has a new turtle
dependency:
name: project1
version: 1.0.0
license: BSD3
license-file: LICENSE
cabal-version: >= 1.18
build-type: Simple
executable project1
build-depends: base < 5, turtle
main-is: Main.hs
default-language: Haskell2010
We'll see the corresponding change in the project1.nix
generated by
cabal2nix
:
{ mkDerivation, base, lib, turtle }:
mkDerivation {
pname = "project1";
version = "1.0.0";
src = ./.;
isLibrary = false;
isExecutable = true;
executableHaskellDepends = [ base turtle ];
license = lib.licenses.bsd3;
}
Notice how neither file specifies what version of turtle
to depend on. This
is because Nix resembles stack
and provides a curated package set of
Haskell packages that build together. If you don't specify a version then Nix
will pick a version for you.
You can find the latest curated package set here:
... which corresponds roughly to the nixpkgs-unstable
release. If you would
like to see what package versions Nix selects for a stable release such as
nixos-18.09
, then change the branch name in the URL from master
to
release-18.09
, like this:
These curated package sets correspond roughly to Stackage resolvers. Stable
releases like nixos-18.09
correspond to Stackage LTS resolvers, and
the nixpkgs-unstable
release corresponds roughly to a Stackage nightly
resolver. The main difference is that Nix's package set curation extends beyond
Haskell packages: nixpkgs
also curates non-Haskell dependencies, too.
We can also see which version our project selects if we build our project
using nix-build
:
$ nix-build --attr project1 release0.nix
these derivations will be built:
/nix/store/8g54hjpim7l9s41c9wpcn1h2q8m254m5-project1-1.0.0.drv
building path(s) ‘/nix/store/pi47yvw46xv346brajyrblwqhjmglhaj-project1-1.0.0’
...
Configuring project1-1.0.0...
Dependency base <5: using base-4.9.0.0
Dependency turtle -any: using turtle-1.2.8
...
/nix/store/pi47yvw46xv346brajyrblwqhjmglhaj-project1-1.0.0
The log output from nix-build
notes that turtle-1.2.8
was chosen for this
build. Your results might vary depending on which version of the nixpkgs
channel that you have installed.
Note that nixpkgs
only curates the Haskell package set to build against the
default version of the GHC compiler. You can display the default compiler version
by running the following command:
$ nix-instantiate --eval --expr '(import <nixpkgs> { }).ghc.version'
If you try to change the compiler (as described below) you may need to modify the Haskell package set to get them to build correctly.
Suppose that we want to build against turtle-1.3.0
for whatever reason. This
requires a much larger change to our project derivation which we can see in
release1.nix
:
# Note: This should fail to build
let
config = {
packageOverrides = pkgs: rec {
haskellPackages = pkgs.haskellPackages.override {
overrides = haskellPackagesNew: haskellPackagesOld: rec {
project1 =
haskellPackagesNew.callPackage ./project1.nix { };
turtle =
haskellPackagesNew.callPackage ./turtle.nix { };
};
};
};
};
pkgs = import <nixpkgs> { inherit config; };
in
{ project1 = pkgs.haskellPackages.project1;
}
By default, import <nixpkgs> { }
will implicitly use an empty or user-defined
configuration in ~/.nixpkgs/config.nix
or $NIXPKGS_CONFIG
. The above
configuration overrides that behavior with an explicit config
defined within
the same file.
This new derivation now references a turtle.nix
file generated from
cabal2nix
by running:
$ cabal2nix cabal://turtle-1.3.2 > turtle.nix
If you try to run that and the command fails with this error message:
cabal2nix: ~/.cabal/packages/hackage.haskell.org/00-index.tar: openBinaryFile: does not exist (No such file or directory)
... then run cabal update
and then the error should disappear.
The generated turtle.nix
file looks like this:
{ mkDerivation, ansi-wl-pprint, async, base, bytestring, clock
, directory, doctest, foldl, hostname, managed, optional-args
, optparse-applicative, process, lib, stm, system-fileio
, system-filepath, temporary, text, time, transformers, unix
, unix-compat
}:
mkDerivation {
pname = "turtle";
version = "1.3.2";
sha256 = "0pbvkqqhiaddyhlqcrk48w7li81dijw92wwhchwqh1my1363n5pq";
libraryHaskellDepends = [
ansi-wl-pprint async base bytestring clock directory foldl hostname
managed optional-args optparse-applicative process stm
system-fileio system-filepath temporary text time transformers unix
unix-compat
];
testHaskellDepends = [ base doctest ];
description = "Shell programming, Haskell-style";
license = lib.licenses.bsd3;
}
nixpkgs
uses a callPackage
utility function to "tie the knot" when updating
dependencies. When we changeturtle
this way every package that depends on
turtle
(including our project1
package) will pick up this new version of
turtle
.
The nixpkgs
manual suggests an alternative approach of specifying package
overrides in a shared ~/.nixpkgs/config.nix
configuration file. However, I do
not recommend this approach: project build instructions should be checked into
version control alongside the project so that they stay in sync with the
project.
At the time of this writing, if you try to build release1.nix
then you will
get the following build error:
$ nix-build --attr project1 release1.nix
these derivations will be built:
/nix/store/r780xwf197a2gxn3008raq5k6xxid8mh-turtle-1.3.0.drv
/nix/store/y6g5ya8lis6250fcj0mrw1kybjdara9i-project1-1.0.0.drv
building path(s) ‘/nix/store/qmyqayhvy4rxhfkxpdvc1ayc1vyp8nmw-turtle-1.3.0’
...
Configuring turtle-1.3.0...
Setup: Encountered missing dependencies:
optparse-applicative ==0.13.*
builder for ‘/nix/store/r780xwf197a2gxn3008raq5k6xxid8mh-turtle-1.3.0.drv’ failed with exit code 1
cannot build derivation ‘/nix/store/y6g5ya8lis6250fcj0mrw1kybjdara9i-project1-1.0.0.drv’: 1 dependencies couldn't be built
error: build of ‘/nix/store/y6g5ya8lis6250fcj0mrw1kybjdara9i-project1-1.0.0.drv’ failed
This error indicates that we can't upgrade turtle-1.3.0
alone because
turtle-1.3.0
depends on optparse-applicative-0.13.*
and the default version
of optparse-applicative
that Nix selects is not in this range. At the
time of this writing, Nix picks optparse-applicative-0.12.1.0
as the default
version.
We can override the optparse-applicative
version using the exact same trick
and release2.nix
contains this additional override:
# Note: This should also fail to build
let
config = {
packageOverrides = pkgs: rec {
haskellPackages = pkgs.haskellPackages.override {
overrides = haskellPackagesNew: haskellPackagesOld: rec {
optparse-applicative =
haskellPackagesNew.callPackage ./optparse-applicative.nix { };
project1 =
haskellPackagesNew.callPackage ./project1.nix { };
turtle =
haskellPackagesNew.callPackage ./turtle.nix { };
};
};
};
};
pkgs = import <nixpkgs> { inherit config; };
in
{ project1 = pkgs.haskellPackages.project1;
}
... where ./optparse-applicative.nix
is also generated by cabal2nix
:
$ cabal2nix cabal://optparse-applicative-0.13.0.0 > optparse-applicative.nix
Now that we've overriden optparse-applicative
, we'll run into a different
build failure if we are using a sufficiently new revision of nixpkgs
:
$ nix-build --attr project1 release2.nix
...
Configuring optparse-applicative-0.13.0.0...
Setup: Encountered missing dependencies:
QuickCheck ==2.8.*
...
Newer versions of nixpkgs
select a newer version of QuickCheck
than what
turtle-1.3.2
requires, so if we want to build against that specific version
of turtle
then we need to also pin QuickCheck
in the same way in
release2a.nix
:
# Note: This should also fail to build
let
config = {
packageOverrides = pkgs: rec {
haskellPackages = pkgs.haskellPackages.override {
overrides = haskellPackagesNew: haskellPackagesOld: rec {
optparse-applicative =
haskellPackagesNew.callPackage ./optparse-applicative.nix { };
QuickCheck =
haskellPackagesNew.callPackage ./QuickCheck.nix { };
project1 =
haskellPackagesNew.callPackage ./project1.nix { };
turtle =
haskellPackagesNew.callPackage ./turtle.nix { };
};
};
};
};
pkgs = import <nixpkgs> { inherit config; };
in
{ project1 = pkgs.haskellPackages.project1;
}
... where QuickCheck.nix
is generated by running:
$ cabal2nix cabal://QuickCheck-2.8.2 > QuickCheck.nix
However, that will still fail to build due to a test suite failure in
optparse-applicative-0.13.0.0
:
$ nix-build --attr project1 release2a.nix
these derivations will be built:
/nix/store/55b9hxwvknznfdqcksdfp8fqxifgw00p-optparse-applicative-0.13.0.0.drv
/nix/store/9m816lg47c6wcgmjqpfxsyml4hgc739d-turtle-1.3.0.drv
/nix/store/las95xi2lzn1lfc75k6acv05yvcw1cc2-project1-1.0.0.drv
building path(s) ‘/nix/store/bgam9vpvqx5j4x8fkasqwws54cqb0pbs-optparse-applicative-0.13.0.0’
...
Running 1 test suites...
Test suite optparse-applicative-tests: RUNNING...
...
=== prop_drops_back_contexts from tests/test.hs:153 ===
*** Failed! Exception: 'tests/dropback.err.txt: openFile: does not exist (No such file or directory)' (after 1 test):
=== prop_context_carry from tests/test.hs:162 ===
*** Failed! Exception: 'tests/carry.err.txt: openFile: does not exist (No such file or directory)' (after 1 test):
=== prop_help_on_empty from tests/test.hs:171 ===
*** Failed! Exception: 'tests/helponempty.err.txt: openFile: does not exist (No such file or directory)' (after 1 test):
=== prop_help_on_empty_sub from tests/test.hs:180 ===
*** Failed! Exception: 'tests/helponemptysub.err.txt: openFile: does not exist (No such file or directory)' (after 1 test):
...
Test suite optparse-applicative-tests: FAIL
Test suite logged to:
dist/test/optparse-applicative-0.13.0.0-optparse-applicative-tests.log
0 of 1 test suites (0 of 1 test cases) passed.
builder for ‘/nix/store/55b9hxwvknznfdqcksdfp8fqxifgw00p-optparse-applicative-0.13.0.0.drv’ failed with exit code 1
cannot build derivation ‘/nix/store/9m816lg47c6wcgmjqpfxsyml4hgc739d-turtle-1.3.0.drv’: 1 dependencies couldn't be built
cannot build derivation ‘/nix/store/las95xi2lzn1lfc75k6acv05yvcw1cc2-project1-1.0.0.drv’: 1 dependencies couldn't be built
error: build of ‘/nix/store/las95xi2lzn1lfc75k6acv05yvcw1cc2-project1-1.0.0.drv’ failed
However, we can instruct cabal2nix
to disable the test suite for our
optparse-applicative
applicative dependency by running:
$ cabal2nix --no-check cabal://optparse-applicative-0.13.0.0 > optparse-applicative-2.nix
release3.nix
uses this test-free optparse-applicative-2.nix
file:
let
config = {
packageOverrides = pkgs: rec {
haskellPackages = pkgs.haskellPackages.override {
overrides = haskellPackagesNew: haskellPackagesOld: rec {
optparse-applicative =
haskellPackagesNew.callPackage ./optparse-applicative-2.nix { };
project1 =
haskellPackagesNew.callPackage ./project1.nix { };
turtle =
haskellPackagesNew.callPackage ./turtle.nix { };
};
};
};
};
pkgs = import <nixpkgs> { inherit config; };
in
{ project1 = pkgs.haskellPackages.project1;
}
... and now the build succeeds:
$ nix-build --attr project1 release3.nix
these derivations will be built:
/nix/store/f17zxqqk582my4qfig78yvi6nv0vb588-turtle-1.3.0.tar.gz.drv
/nix/store/vn2m1agg92fbmwj1h9168jywy5wmarah-turtle-1.3.0.drv
/nix/store/c3vidydlyaa25kq2zs35kx80vv8sz1mk-project1-1.0.0.drv
these paths will be fetched (1.60 MiB download, 16.92 MiB unpacked):
/nix/store/9kyi7kr3gzpxns4qalda26ww6jfzbpc7-syb-0.6
/nix/store/9v640kglbndlrfpr6wpsq626gb2amx40-libssh2-1.7.0-dev
/nix/store/cm1561r3fs320571n7cicggmjlgy3rdi-unix-compat-0.4.2.0
/nix/store/hfy7dnf85gp1j8dqlhc2v0fdpsmc02vc-nghttp2-1.10.0
/nix/store/kmqlvjmkrg66f5pnbx5jknfiyqf09jgx-curl-7.51.0-dev
/nix/store/l06y84abvix2qmsxs5dbxllfsv9aznfk-hscolour-1.24.1
/nix/store/pq0dcikqwvxxpiknmwki77nyalba3n4a-doctest-0.11.0
/nix/store/v0wwvy3ygb52flq49z1yk445w2126rhs-base-compat-0.9.1
/nix/store/vxqdcfj9kf0k1qvladvxl6wm21np8czh-optparse-applicative-0.13.0.0
/nix/store/w5v8fjg704a5r38sk5dnf3zz7r8vapac-libev-4.22
/nix/store/wyvv44zpn9j2fn30m2k2kry2cycqqlqv-ghc-paths-0.1.0.9
/nix/store/xs8caklddfbmnvkgwcn38m0d7ivxdlq9-mirrors-list
/nix/store/zdkjkdq4fcc6cwnxddm5mxa64n4pavb8-nghttp2-1.10.0-dev
...
building path(s) ‘/nix/store/frdmdrpr7rgv24i8p5qs5ifvcxz2jm6d-turtle-1.3.0’
...
Configuring turtle-1.3.0...
Dependency ansi-wl-pprint ==0.6.*: using ansi-wl-pprint-0.6.7.3
Dependency async >=2.0.0.0 && <2.2: using async-2.1.0
Dependency base >=4.6 && <5: using base-4.9.0.0
Dependency bytestring >=0.9.1.8 && <0.11: using bytestring-0.10.8.1
Dependency clock >=0.4.1.2 && <0.8: using clock-0.7.2
Dependency directory >=1.0.7 && <1.3: using directory-1.2.6.2
Dependency doctest >=0.7 && <0.12: using doctest-0.11.0
Dependency foldl >=1.1 && <1.3: using foldl-1.2.1
Dependency hostname <1.1: using hostname-1.0
Dependency managed >=1.0.3 && <1.1: using managed-1.0.5
Dependency optional-args >=1.0 && <2.0: using optional-args-1.0.1
Dependency optparse-applicative ==0.13.*: using optparse-applicative-0.13.0.0
Dependency process >=1.0.1.1 && <1.5: using process-1.4.2.0
Dependency stm <2.5: using stm-2.4.4.1
Dependency system-fileio >=0.2.1 && <0.4: using system-fileio-0.3.16.3
Dependency system-filepath >=0.3.1 && <0.5: using system-filepath-0.4.13.4
Dependency temporary <1.3: using temporary-1.2.0.4
Dependency text <1.3: using text-1.2.2.1
Dependency time <1.7: using time-1.6.0.1
Dependency transformers >=0.2.0.0 && <0.6: using transformers-0.5.2.0
Dependency turtle -any: using turtle-1.3.0
Dependency unix >=2.5.1.0 && <2.8: using unix-2.7.2.0
Dependency unix-compat ==0.4.*: using unix-compat-0.4.2.0
...
Building turtle-1.3.0...
Preprocessing library turtle-1.3.0...
[ 1 of 10] Compiling Turtle.Internal ( src/Turtle/Internal.hs, dist/build/Turtle/Internal.o )
[ 2 of 10] Compiling Turtle.Line ( src/Turtle/Line.hs, dist/build/Turtle/Line.o )
[ 3 of 10] Compiling Turtle.Shell ( src/Turtle/Shell.hs, dist/build/Turtle/Shell.o )
[ 4 of 10] Compiling Turtle.Options ( src/Turtle/Options.hs, dist/build/Turtle/Options.o )
[ 5 of 10] Compiling Turtle.Pattern ( src/Turtle/Pattern.hs, dist/build/Turtle/Pattern.o )
[ 6 of 10] Compiling Turtle.Format ( src/Turtle/Format.hs, dist/build/Turtle/Format.o )
[ 7 of 10] Compiling Turtle.Prelude ( src/Turtle/Prelude.hs, dist/build/Turtle/Prelude.o )
[ 8 of 10] Compiling Turtle.Bytes ( src/Turtle/Bytes.hs, dist/build/Turtle/Bytes.o )
[ 9 of 10] Compiling Turtle ( src/Turtle.hs, dist/build/Turtle.o )
[10 of 10] Compiling Turtle.Tutorial ( src/Turtle/Tutorial.hs, dist/build/Turtle/Tutorial.o )
Preprocessing test suite 'tests' for turtle-1.3.0...
[1 of 1] Compiling Main ( test/Main.hs, dist/build/tests/tests-tmp/Main.dyn_o )
Linking dist/build/tests/tests ...
Preprocessing test suite 'regression-broken-pipe' for turtle-1.3.0...
[1 of 1] Compiling Main ( test/RegressionBrokenPipe.hs, dist/build/regression-broken-pipe/regression-broken-pipe-tmp/Main.dyn_o )
Linking dist/build/regression-broken-pipe/regression-broken-pipe ...
running tests
Running 2 test suites...
Test suite tests: RUNNING...
Test suite tests: PASS
Test suite logged to: dist/test/turtle-1.3.0-tests.log
Test suite regression-broken-pipe: RUNNING...
Test suite regression-broken-pipe: PASS
Test suite logged to: dist/test/turtle-1.3.0-regression-broken-pipe.log
2 of 2 test suites (2 of 2 test cases) passed.
...
Configuring project1-1.0.0...
Dependency base <5: using base-4.9.0.0
Dependency turtle -any: using turtle-1.3.0
...
/nix/store/dv0vxc8pwrl8sdrfhy4y2ajnb1nh6qqy-project1-1.0.0
We can look at the difference between optparse-applicative.nix
and
optparse-applicative-2.nix
to see what changed:
$ diff optparse-applicative.nix optparse-applicative-2.nix
11a12
> doCheck = false;
The latter file contains a doCheck = false;
directive which instructs Nix to
not build and run the test suite.
Suppose that we wish to retrieve our turtle
dependency from Github instead of
from Hackage. All we have to do is run:
$ cabal2nix https://github.com/Gabriel439/Haskell-Turtle-Library.git --revision ba9c992933ae625cef40a88ea16ee857d1b93e13 > turtle-2.nix
... replacing ba9c992933ae625cef40a88ea16ee857d1b93e13
with the revision we
wish to use. You can omit the revision if you want cabal2nix
to select the
revision of the current master
branch.
Result looks like this turtle-2.nix
:
{ mkDerivation, ansi-wl-pprint, async, base, bytestring, clock
, directory, doctest, fetchgit, foldl, hostname, managed
, optional-args, optparse-applicative, process, lib, stm
, system-fileio, system-filepath, temporary, text, time
, transformers, unix, unix-compat
}:
mkDerivation {
pname = "turtle";
version = "1.3.2";
src = fetchgit {
url = "https://github.com/Gabriel439/Haskell-Turtle-Library.git";
sha256 = "0cbs3yi4glqhv3419hxihvpsgcj2h2sirbgym5d45hz4d32n9i67";
rev = "21b50f09e04b4e149b3c5a5f12405ed608cda2ab";
};
libraryHaskellDepends = [
ansi-wl-pprint async base bytestring clock directory foldl hostname
managed optional-args optparse-applicative process stm
system-fileio system-filepath temporary text time transformers unix
unix-compat
];
testHaskellDepends = [ base doctest ];
description = "Shell programming, Haskell-style";
license = lib.licenses.bsd3;
}
release4.nix
shows an example of depending on turtle
from Github. The only
difference is that we now depend on the turtle-2.nix
file:
diff release3.nix release4.nix
13c13
< haskellPackagesNew.callPackage ./turtle.nix { };
---
> haskellPackagesNew.callPackage ./turtle-2.nix { };
... and the difference between turtle.nix
and turtle-2.nix
is that the
dependency list changed and there is a new src
field pointing to the Github
repository:
2,5c2,5
< , directory, doctest, foldl, hostname, managed, optional-args
< , optparse-applicative, process, lib, stm, system-fileio
< , system-filepath, temporary, text, time, transformers, unix
< , unix-compat
---
> , directory, doctest, fetchgit, foldl, hostname, managed
> , optional-args, optparse-applicative, process, lib, stm
> , system-fileio, system-filepath, temporary, text, time
> , transformers, unix, unix-compat
10c10,14
< sha256 = "0pbvkqqhiaddyhlqcrk48w7li81dijw92wwhchwqh1my1363n5pq";
---
> src = fetchgit {
> url = "https://github.com/Gabriel439/Haskell-Turtle-Library.git";
> sha256 = "0cbs3yi4glqhv3419hxihvpsgcj2h2sirbgym5d45hz4d32n9i67";
> rev = "21b50f09e04b4e149b3c5a5f12405ed608cda2ab";
> };
You can also depend on local source checkouts of a given dependency. For
example, if you checkout the turtle
repository in some other directory then
all you have to do is run:
$ cabal2nix /path/to/turtle > turtle.nix
... and then reference ./turtle.nix
in your release.nix
file. Now your
build will automatically pull in any changes you make to your source checkout of
turtle
.
You can also override the GHC version used to compile your project, which
release5.nix
illustrates:
{ compiler ? "ghc802" }:
let
config = {
packageOverrides = pkgs: rec {
haskell = pkgs.haskell // {
packages = pkgs.haskell.packages // {
"${compiler}" = pkgs.haskell.packages."${compiler}".override {
overrides = haskellPackagesNew: haskellPackagesOld: rec {
optparse-applicative =
haskellPackagesNew.callPackage ./optparse-applicative-2.nix { };
project1 =
haskellPackagesNew.callPackage ./project1.nix { };
turtle =
haskellPackagesNew.callPackage ./turtle-2.nix { };
};
};
};
};
};
};
pkgs = import <nixpkgs> { inherit config; };
in
{ project1 = pkgs.haskell.packages.${compiler}.project1;
}
By default, the above project is built using GHC 8.0.2:
$ nix-build --attr project1 release5.nix
...
Using ghc version 8.0.2 found on system at:
/nix/store/7nl6dii88xd761nnz3xyh11qcnrqvqri-ghc-8.0.2/bin/ghc
Using ghc-pkg version 8.0.2 found on system at:
/nix/store/7nl6dii88xd761nnz3xyh11qcnrqvqri-ghc-8.0.2/bin/ghc-pkg
...
/nix/store/0mw2v9h6f3fz1p9bwy48qxsr5637550s-project1-1.0.0
... but you can now override the compiler on the command line like this:
$ nix-build --argstr compiler ghc7103 --attr project1 release5.nix
...
building path(s) ‘/nix/store/2c5w9j0dam8m2pn35jvbq2namf8y723f-optparse-applicative-0.13.0.0’
setupCompilerEnvironmentPhase
Build with /nix/store/ik664w3cxq2jzr5kby0gwmcm0k96xgmg-ghc-7.10.3.
unpacking sources
unpacking source archive /nix/store/b55m0akvijaxps1lzr424m8y4y4q6awv-optparse-applicative-0.13.0.0.tar.gz
source root is optparse-applicative-0.13.0.0
setting SOURCE_DATE_EPOCH to timestamp 1471231137 of file optparse-applicative-0.13.0.0/tests/test.hs
patching sources
compileBuildDriverPhase
setupCompileFlags: -package-db=/private/var/folders/c9/zf_25xbx7bx8yhsxm4q4vw6m0000gn/T/nix-build-optparse-applicative-0.13.0.0.drv-0/package.conf.d -j8 -threaded
[1 of 1] Compiling Main ( Setup.hs, /private/var/folders/c9/zf_25xbx7bx8yhsxm4q4vw6m0000gn/T/nix-build-optparse-applicative-0.13.0.0.drv-0/Main.o )
Linking Setup ...
configuring
configureFlags: --verbose --prefix=/nix/store/2c5w9j0dam8m2pn35jvbq2namf8y723f-optparse-applicative-0.13.0.0 --libdir=$prefix/lib/$compiler --libsubdir=$pkgid --with-gcc=clang --package-db=/private/var/folders/c9/zf_25xbx7bx8yhsxm4q4vw6m0000gn/T/nix-build-optparse-applicative-0.13.0.0.drv-0/package.conf.d --ghc-option=-optl=-Wl,-headerpad_max_install_names --disable-split-objs --disable-library-profiling --disable-executable-profiling --enable-shared --disable-coverage --enable-library-vanilla --enable-executable-dynamic --disable-tests
Configuring optparse-applicative-0.13.0.0...
Setup: At least the following dependencies are missing:
semigroups >=0.10 && <0.19
builder for ‘/nix/store/kz5ngjwspkky7677vfcjfkliglsxw8nq-optparse-applicative-0.13.0.0.drv’ failed with exit code 1
cannot build derivation ‘/nix/store/4ll08plvc8wmx31mvvsxs83fg6wp849j-turtle-1.3.2.drv’: 1 dependencies couldn't be built
cannot build derivation ‘/nix/store/q40kf7b4d5xwlrnyrflib3qzdc8vfqly-project1-1.0.0.drv’: 1 dependencies couldn't be built
error: build of ‘/nix/store/q40kf7b4d5xwlrnyrflib3qzdc8vfqly-project1-1.0.0.drv’ failed
Note that the build may fail when you downgrade the compiler. For example, this
build fails because of a missing semigroups
dependency. This is because of the
following clause in the optparse-applicative.cabal
file:
if !impl(ghc >= 8)
build-depends: semigroups >= 0.10 && < 0.19
... which cabal2nix
ignores because it assumes that the current GHC version is
GHC 8. However, we can tweak our optparse-applicative
dependency to manually
add the semigroups
dependency in release6.nix
:
{ compiler ? "ghc802" }:
let
config = {
packageOverrides = pkgs: rec {
haskell = pkgs.haskell // {
packages = pkgs.haskell.packages // {
"${compiler}" = pkgs.haskell.packages."${compiler}".override {
overrides = haskellPackagesNew: haskellPackagesOld: rec {
optparse-applicative =
pkgs.haskell.lib.addBuildDepend
(haskellPackagesNew.callPackage ./optparse-applicative-2.nix { })
haskellPackagesNew.semigroups;
project1 =
haskellPackagesNew.callPackage ./project1.nix { };
turtle =
haskellPackagesNew.callPackage ./turtle-2.nix { };
};
};
};
};
};
};
pkgs = import <nixpkgs> { inherit config; };
in
{ project1 = pkgs.haskell.packages.${compiler}.project1;
}
... and now the build succeeds:
$ nix-build --argstr compiler ghc7103 --attr project1 release6.nix
...
Using ghc version 7.10.3 found on system at:
/nix/store/ik664w3cxq2jzr5kby0gwmcm0k96xgmg-ghc-7.10.3/bin/ghc
Using ghc-pkg version 7.10.3 found on system at:
/nix/store/ik664w3cxq2jzr5kby0gwmcm0k96xgmg-ghc-7.10.3/bin/ghc-pkg
...
/nix/store/9fmspa6dz93vg84d2c5bl9y1hszxmk7v-project1-1.0.0
The fourth section of this tutorial contains more details on how to tweak Haskell builds.
This concludes basic dependency management in Nix. The next section covers using Nix to manage non-Haskell dependencies.