-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathnix-hs.nix
171 lines (154 loc) · 5.48 KB
/
nix-hs.nix
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
################################################################################
#
# This file is part of the package nix-hs. It is subject to the license
# terms in the LICENSE file found in the top-level directory of this
# distribution and at:
#
# https://code.devalot.com/open/nix-hs
#
# No part of this package, including this file, may be copied, modified,
# propagated, or distributed except according to the terms contained in
# the LICENSE file.
#
{ pkgs
}:
{
# Path to one or more Cabal files. May be a single path or an attr
# set of package names and paths to cabal files:
cabal
# Cabal `-f' flags to use:
, flags ? [ ]
# A nixpkgs version string for GHC, or "default":
, compiler ? "default"
# Optional: Override `haskellPackages' with a function. The
# function takes three arguments and returns a new Haskell package
# set.
#
# The arguments are:
#
# 1. `pkgs.haskell.lib` with some additions (see below).
# 2. `self`: The package set you are currently building.
# 3. `super`: The existing Haskell package set.
#
# For a list of additional functions that are available in the `lib`
# argument, see `lib/haskell.nix`.
#
# Also, one additional attribute will be available in `lib`: pkgs,
# the final nixpkgs set after all Haskell overrides have been
# applied. This is important for passing on to other invocations of
# nix-hs for any dependencies so they pick up the already patched
# dependencies from this overrides function.
#
# An example overrides function can be found in:
#
# test/overrides/default.nix
, overrides ? (lib: self: super: { })
# Extra nixpkgs packages that your Haskell package depend on:
, buildInputs ? [ ]
# Shell fragment to run after the `patchPhase':
, postPatch ? ""
# If not null, it should be a function that takes a path to the data
# directory and returns shell code to install extra files.
#
# Note: The argument given to this function contains shell variables
# so it can only be used in a shell snippet.
#
# Example:
#
# addDataFiles = path: ''
# mkdir -p "${path}/www"
# for file in ${ui}/*.js; do
# install -m 0444 "$file" "${path}/www"
# done
# '';
, addDataFiles ? null
}:
let
nix-hs = import ./lib { inherit pkgs compiler; };
# Create a derivation for the given cabal file.
singlePackage = cabalFile: packages:
let
drv =
nix-hs.packages.derivationFromCabal {
inherit flags postPatch addDataFiles buildInputs packages;
cabal = cabalFile;
};
in
nix-hs.haskell.appendPassthru
{
bin = nix-hs.haskell.justStaticExecutables drv;
interactive = makeInteractive packages drv;
}
drv;
# When we have more than one cabal file so we build an attribute set
# of derivations where the keys are package names and the values are
# the Haskell derivations.
multiPackage = fileSet: packages:
pkgs.lib.mapAttrs
(_name: cabalFile: singlePackage cabalFile packages)
fileSet;
# Returns an attribute set that contains the generated Haskell packages.
generatedPackages = packages:
if builtins.isAttrs cabal
then multiPackage cabal packages
else { ${nix-hs.packages.nameFromCabal cabal} = singlePackage cabal packages; };
# Generates an interactive shell environment for the given Haskell
# derivation (or derivations).
makeInteractive = packages: drv:
let
shellDrv = import ./shell { inherit compiler; };
# Use the Hoogle package from the interactive shell environment
# and not the one from the current package set since this is the
# hoogle binary we want in the interactive shell. Bonus
# feature: we automatically pick up any patches that make hoogle
# work with the selected compiler.
withPatchedHoogle =
nix-hs.packages.overrideHaskellPackages
(_self: _super: { hoogle = shellDrv.haskell.hoogle; })
packages;
shellFor = inputs:
withPatchedHoogle.shellFor {
packages = _: inputs;
withHoogle = true;
doBenchmark = true;
buildInputs = buildInputs ++ shellDrv.buildInputs;
};
in
if pkgs.lib.isDerivation drv
then shellFor [ drv ]
else shellFor (builtins.attrValues drv);
# Extract the generated Haskell packages out of the final package set.
extractPackages = packages:
let
drvs =
pkgs.lib.mapAttrs
(name: _value: packages.${name})
cabal;
in
if builtins.isAttrs cabal
then { interactive = makeInteractive packages drvs; } // drvs
else packages.${nix-hs.packages.nameFromCabal cabal};
# The haskell package set after applying the requested overrides and
# adding in the package generated from the cabal file(s):
haskellPackages =
let
# Augmented overrides function that accepts the final nixpkgs
# set for the `pkgs` attribute which is passed in the Haskell
# library functions attrset.
overrides_ = self:
overrides ({
pkgs = self;
} // nix-hs.haskell);
# Jump through some hoops to generate a patched Haskell package
# set from the given nixpkgs set, passing along the final
# nixpkgs set to the overriding function.
packages =
(nix-hs.packages.overrideHaskellPackagesIn
overrides_
pkgs).haskell.packages.${nix-hs.ghc.attrName};
in
nix-hs.packages.overrideHaskellPackages
(_self: _super: generatedPackages packages)
packages;
in
extractPackages haskellPackages