nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1# TODO(@Ericson2314): Remove `pkgs` param, which is only used for
2# `buildStackProject`, `justStaticExecutables` and `checkUnusedPackages`
3{ pkgs, lib }:
4
5rec {
6 /* This function takes a file like `hackage-packages.nix` and constructs
7 a full package set out of that.
8 */
9 makePackageSet = import ./make-package-set.nix;
10
11 /* The function overrideCabal lets you alter the arguments to the
12 mkDerivation function.
13
14 Example:
15
16 First, note how the aeson package is constructed in hackage-packages.nix:
17
18 "aeson" = callPackage ({ mkDerivation, attoparsec, <snip>
19 }:
20 mkDerivation {
21 pname = "aeson";
22 <snip>
23 homepage = "https://github.com/bos/aeson";
24 })
25
26 The mkDerivation function of haskellPackages will take care of putting
27 the homepage in the right place, in meta.
28
29 > haskellPackages.aeson.meta.homepage
30 "https://github.com/bos/aeson"
31
32 > x = haskell.lib.overrideCabal haskellPackages.aeson (old: { homepage = old.homepage + "#readme"; })
33 > x.meta.homepage
34 "https://github.com/bos/aeson#readme"
35
36 */
37 overrideCabal = drv: f: (drv.override (args: args // {
38 mkDerivation = drv: (args.mkDerivation drv).override f;
39 })) // {
40 overrideScope = scope: overrideCabal (drv.overrideScope scope) f;
41 };
42
43 # : Map Name (Either Path VersionNumber) -> HaskellPackageOverrideSet
44 # Given a set whose values are either paths or version strings, produces
45 # a package override set (i.e. (self: super: { etc. })) that sets
46 # the packages named in the input set to the corresponding versions
47 packageSourceOverrides =
48 overrides: self: super: pkgs.lib.mapAttrs (name: src:
49 let isPath = x: builtins.substring 0 1 (toString x) == "/";
50 generateExprs = if isPath src
51 then self.callCabal2nix
52 else self.callHackage;
53 in generateExprs name src {}) overrides;
54
55 /* doCoverage modifies a haskell package to enable the generation
56 and installation of a coverage report.
57
58 See https://wiki.haskell.org/Haskell_program_coverage
59 */
60 doCoverage = drv: overrideCabal drv (drv: { doCoverage = true; });
61
62 /* dontCoverage modifies a haskell package to disable the generation
63 and installation of a coverage report.
64 */
65 dontCoverage = drv: overrideCabal drv (drv: { doCoverage = false; });
66
67 /* doHaddock modifies a haskell package to enable the generation and
68 installation of API documentation from code comments using the
69 haddock tool.
70 */
71 doHaddock = drv: overrideCabal drv (drv: { doHaddock = true; });
72
73 /* dontHaddock modifies a haskell package to disable the generation and
74 installation of API documentation from code comments using the
75 haddock tool.
76 */
77 dontHaddock = drv: overrideCabal drv (drv: { doHaddock = false; });
78
79 /* doJailbreak enables the removal of version bounds from the cabal
80 file. You may want to avoid this function.
81
82 This is useful when a package reports that it can not be built
83 due to version mismatches. In some cases, removing the version
84 bounds entirely is an easy way to make a package build, but at
85 the risk of breaking software in non-obvious ways now or in the
86 future.
87
88 Instead of jailbreaking, you can patch the cabal file.
89 */
90 doJailbreak = drv: overrideCabal drv (drv: { jailbreak = true; });
91
92 /* dontJailbreak restores the use of the version bounds the check
93 the use of dependencies in the package description.
94 */
95 dontJailbreak = drv: overrideCabal drv (drv: { jailbreak = false; });
96
97 /* doCheck enables dependency checking, compilation and execution
98 of test suites listed in the package description file.
99 */
100 doCheck = drv: overrideCabal drv (drv: { doCheck = true; });
101 /* dontCheck disables dependency checking, compilation and execution
102 of test suites listed in the package description file.
103 */
104 dontCheck = drv: overrideCabal drv (drv: { doCheck = false; });
105
106 /* doBenchmark enables dependency checking, compilation and execution
107 for benchmarks listed in the package description file.
108 */
109 doBenchmark = drv: overrideCabal drv (drv: { doBenchmark = true; });
110 /* dontBenchmark disables dependency checking, compilation and execution
111 for benchmarks listed in the package description file.
112 */
113 dontBenchmark = drv: overrideCabal drv (drv: { doBenchmark = false; });
114
115 /* doDistribute enables the distribution of binaries for the package
116 via hydra.
117 */
118 doDistribute = drv: overrideCabal drv (drv: { hydraPlatforms = drv.platforms or ["i686-linux" "x86_64-linux" "x86_64-darwin"]; });
119 /* dontDistribute disables the distribution of binaries for the package
120 via hydra.
121 */
122 dontDistribute = drv: overrideCabal drv (drv: { hydraPlatforms = []; });
123
124 /* appendConfigureFlag adds a single argument that will be passed to the
125 cabal configure command, after the arguments that have been defined
126 in the initial declaration or previous overrides.
127
128 Example:
129
130 > haskell.lib.appendConfigureFlag haskellPackages.servant "--profiling-detail=all-functions"
131 */
132 appendConfigureFlag = drv: x: appendConfigureFlags drv [x];
133 appendConfigureFlags = drv: xs: overrideCabal drv (drv: { configureFlags = (drv.configureFlags or []) ++ xs; });
134
135 appendBuildFlag = drv: x: overrideCabal drv (drv: { buildFlags = (drv.buildFlags or []) ++ [x]; });
136 appendBuildFlags = drv: xs: overrideCabal drv (drv: { buildFlags = (drv.buildFlags or []) ++ xs; });
137
138 /* removeConfigureFlag drv x is a Haskell package like drv, but with
139 all cabal configure arguments that are equal to x removed.
140
141 > haskell.lib.removeConfigureFlag haskellPackages.servant "--verbose"
142 */
143 removeConfigureFlag = drv: x: overrideCabal drv (drv: { configureFlags = lib.remove x (drv.configureFlags or []); });
144
145 addBuildTool = drv: x: addBuildTools drv [x];
146 addBuildTools = drv: xs: overrideCabal drv (drv: { buildTools = (drv.buildTools or []) ++ xs; });
147
148 addExtraLibrary = drv: x: addExtraLibraries drv [x];
149 addExtraLibraries = drv: xs: overrideCabal drv (drv: { extraLibraries = (drv.extraLibraries or []) ++ xs; });
150
151 addBuildDepend = drv: x: addBuildDepends drv [x];
152 addBuildDepends = drv: xs: overrideCabal drv (drv: { buildDepends = (drv.buildDepends or []) ++ xs; });
153
154 addPkgconfigDepend = drv: x: addPkgconfigDepends drv [x];
155 addPkgconfigDepends = drv: xs: overrideCabal drv (drv: { pkgconfigDepends = (drv.pkgconfigDepends or []) ++ xs; });
156
157 addSetupDepend = drv: x: addSetupDepends drv [x];
158 addSetupDepends = drv: xs: overrideCabal drv (drv: { setupHaskellDepends = (drv.setupHaskellDepends or []) ++ xs; });
159
160 enableCabalFlag = drv: x: appendConfigureFlag (removeConfigureFlag drv "-f-${x}") "-f${x}";
161 disableCabalFlag = drv: x: appendConfigureFlag (removeConfigureFlag drv "-f${x}") "-f-${x}";
162
163 markBroken = drv: overrideCabal drv (drv: { broken = true; hydraPlatforms = []; });
164 unmarkBroken = drv: overrideCabal drv (drv: { broken = false; });
165 markBrokenVersion = version: drv: assert drv.version == version; markBroken drv;
166 markUnbroken = drv: overrideCabal drv (drv: { broken = false; });
167
168 enableLibraryProfiling = drv: overrideCabal drv (drv: { enableLibraryProfiling = true; });
169 disableLibraryProfiling = drv: overrideCabal drv (drv: { enableLibraryProfiling = false; });
170
171 enableExecutableProfiling = drv: overrideCabal drv (drv: { enableExecutableProfiling = true; });
172 disableExecutableProfiling = drv: overrideCabal drv (drv: { enableExecutableProfiling = false; });
173
174 enableSharedExecutables = drv: overrideCabal drv (drv: { enableSharedExecutables = true; });
175 disableSharedExecutables = drv: overrideCabal drv (drv: { enableSharedExecutables = false; });
176
177 enableSharedLibraries = drv: overrideCabal drv (drv: { enableSharedLibraries = true; });
178 disableSharedLibraries = drv: overrideCabal drv (drv: { enableSharedLibraries = false; });
179
180 enableDeadCodeElimination = drv: overrideCabal drv (drv: { enableDeadCodeElimination = true; });
181 disableDeadCodeElimination = drv: overrideCabal drv (drv: { enableDeadCodeElimination = false; });
182
183 enableStaticLibraries = drv: overrideCabal drv (drv: { enableStaticLibraries = true; });
184 disableStaticLibraries = drv: overrideCabal drv (drv: { enableStaticLibraries = false; });
185
186 enableSeparateBinOutput = drv: overrideCabal drv (drv: { enableSeparateBinOutput = true; });
187
188 appendPatch = drv: x: appendPatches drv [x];
189 appendPatches = drv: xs: overrideCabal drv (drv: { patches = (drv.patches or []) ++ xs; });
190
191 doHyperlinkSource = drv: overrideCabal drv (drv: { hyperlinkSource = true; });
192 dontHyperlinkSource = drv: overrideCabal drv (drv: { hyperlinkSource = false; });
193
194 disableHardening = drv: flags: overrideCabal drv (drv: { hardeningDisable = flags; });
195
196 /* Let Nix strip the binary files.
197 * This removes debugging symbols.
198 */
199 doStrip = drv: overrideCabal drv (drv: { dontStrip = false; });
200
201 /* Stop Nix from stripping the binary files.
202 * This keeps debugging symbols.
203 */
204 dontStrip = drv: overrideCabal drv (drv: { dontStrip = true; });
205
206 /* Useful for debugging segfaults with gdb.
207 * This includes dontStrip.
208 */
209 enableDWARFDebugging = drv:
210 # -g: enables debugging symbols
211 # --disable-*-stripping: tell GHC not to strip resulting binaries
212 # dontStrip: see above
213 appendConfigureFlag (dontStrip drv) "--ghc-options=-g --disable-executable-stripping --disable-library-stripping";
214
215 /* Create a source distribution tarball like those found on hackage,
216 instead of building the package.
217 */
218 sdistTarball = pkg: lib.overrideDerivation pkg (drv: {
219 name = "${drv.pname}-source-${drv.version}";
220 # Since we disable the haddock phase, we also need to override the
221 # outputs since the separate doc output will not be produced.
222 outputs = ["out"];
223 buildPhase = "./Setup sdist";
224 haddockPhase = ":";
225 checkPhase = ":";
226 installPhase = "install -D dist/${drv.pname}-*.tar.gz $out/${drv.pname}-${drv.version}.tar.gz";
227 fixupPhase = ":";
228 });
229
230 /* Use the gold linker. It is a linker for ELF that is designed
231 "to run as fast as possible on modern systems"
232 */
233 linkWithGold = drv : appendConfigureFlag drv
234 "--ghc-option=-optl-fuse-ld=gold --ld-option=-fuse-ld=gold --with-ld=ld.gold";
235
236 /* link executables statically against haskell libs to reduce
237 closure size
238 */
239 justStaticExecutables = drv: overrideCabal drv (drv: {
240 enableSharedExecutables = false;
241 enableLibraryProfiling = false;
242 isLibrary = false;
243 doHaddock = false;
244 postFixup = "rm -rf $out/lib $out/nix-support $out/share/doc";
245 });
246
247 /* Build a source distribution tarball instead of using the source files
248 directly. The effect is that the package is built as if it were published
249 on hackage. This can be used as a test for the source distribution,
250 assuming the build fails when packaging mistakes are in the cabal file.
251 */
252 buildFromSdist = pkg: overrideCabal pkg (drv: {
253 src = "${sdistTarball pkg}/${pkg.pname}-${pkg.version}.tar.gz";
254
255 # Revising and jailbreaking the cabal file has been handled in sdistTarball
256 revision = null;
257 editedCabalFile = null;
258 jailbreak = false;
259 });
260
261 /* Build the package in a strict way to uncover potential problems.
262 This includes buildFromSdist and failOnAllWarnings.
263 */
264 buildStrictly = pkg: buildFromSdist (failOnAllWarnings pkg);
265
266 /* Disable core optimizations, significantly speeds up build time */
267 disableOptimization = pkg: appendConfigureFlag pkg "--disable-optimization";
268
269 /* Turn on most of the compiler warnings and fail the build if any
270 of them occur. */
271 failOnAllWarnings = drv: appendConfigureFlag drv "--ghc-option=-Wall --ghc-option=-Werror";
272
273 /* Add a post-build check to verify that dependencies declared in
274 the cabal file are actually used.
275
276 The first attrset argument can be used to configure the strictness
277 of this check and a list of ignored package names that would otherwise
278 cause false alarms.
279 */
280 checkUnusedPackages =
281 { ignoreEmptyImports ? false
282 , ignoreMainModule ? false
283 , ignorePackages ? []
284 } : drv :
285 overrideCabal (appendConfigureFlag drv "--ghc-option=-ddump-minimal-imports") (_drv: {
286 postBuild = with lib;
287 let args = concatStringsSep " " (
288 optional ignoreEmptyImports "--ignore-empty-imports" ++
289 optional ignoreMainModule "--ignore-main-module" ++
290 map (pkg: "--ignore-package ${pkg}") ignorePackages
291 );
292 in "${pkgs.haskellPackages.packunused}/bin/packunused" +
293 optionalString (args != "") " ${args}";
294 });
295
296 buildStackProject = pkgs.callPackage ./generic-stack-builder.nix { };
297
298 /* Add a dummy command to trigger a build despite an equivalent
299 earlier build that is present in the store or cache.
300 */
301 triggerRebuild = drv: i: overrideCabal drv (drv: { postUnpack = ": trigger rebuild ${toString i}"; });
302
303 /* Override the sources for the package and optionaly the version.
304 This also takes of removing editedCabalFile.
305 */
306 overrideSrc = drv: { src, version ? drv.version }:
307 overrideCabal drv (_: { inherit src version; editedCabalFile = null; });
308
309 # Get all of the build inputs of a haskell package, divided by category.
310 getBuildInputs = p: p.getBuildInputs;
311
312 # Extract the haskell build inputs of a haskell package.
313 # This is useful to build environments for developing on that
314 # package.
315 getHaskellBuildInputs = p: (getBuildInputs p).haskellBuildInputs;
316
317 # Under normal evaluation, simply return the original package. Under
318 # nix-shell evaluation, return a nix-shell optimized environment.
319 shellAware = p: if lib.inNixShell then p.env else p;
320
321 ghcInfo = ghc:
322 rec { isCross = (ghc.cross or null) != null;
323 isGhcjs = ghc.isGhcjs or false;
324 nativeGhc = if isCross || isGhcjs
325 then ghc.bootPkgs.ghc
326 else ghc;
327 };
328
329 ### mkDerivation helpers
330 # These allow external users of a haskell package to extract
331 # information about how it is built in the same way that the
332 # generic haskell builder does, by reusing the same functions.
333 # Each function here has the same interface as mkDerivation and thus
334 # can be called for a given package simply by overriding the
335 # mkDerivation argument it used. See getHaskellBuildInputs above for
336 # an example of this.
337
338 # Some information about which phases should be run.
339 controlPhases = ghc: let inherit (ghcInfo ghc) isCross; in
340 { doCheck ? !isCross && (lib.versionOlder "7.4" ghc.version)
341 , doBenchmark ? false
342 , ...
343 }: { inherit doCheck doBenchmark; };
344
345 # Utility to convert a directory full of `cabal2nix`-generated files into a
346 # package override set
347 #
348 # packagesFromDirectory : { directory : Directory, ... } -> HaskellPackageOverrideSet
349 packagesFromDirectory =
350 { directory, ... }:
351
352 self: super:
353 let
354 haskellPaths = builtins.attrNames (builtins.readDir directory);
355
356 toKeyVal = file: {
357 name = builtins.replaceStrings [ ".nix" ] [ "" ] file;
358
359 value = self.callPackage (directory + "/${file}") { };
360 };
361
362 in
363 builtins.listToAttrs (map toKeyVal haskellPaths);
364
365 addOptparseApplicativeCompletionScripts = exeName: pkg:
366 builtins.trace "addOptparseApplicativeCompletionScripts is deprecated in favor of generateOptparseApplicativeCompletion. Please change ${pkg.name} to use the latter or its plural form."
367 (generateOptparseApplicativeCompletion exeName pkg);
368
369 /*
370 Modify a Haskell package to add shell completion scripts for the
371 given executable produced by it. These completion scripts will be
372 picked up automatically if the resulting derivation is installed,
373 e.g. by `nix-env -i`.
374
375 Invocation:
376 generateOptparseApplicativeCompletions command pkg
377
378
379 command: name of an executable
380 pkg: Haskell package that builds the executables
381 */
382 generateOptparseApplicativeCompletion = exeName: pkg: overrideCabal pkg (drv: {
383 postInstall = (drv.postInstall or "") + ''
384 bashCompDir="$out/share/bash-completion/completions"
385 zshCompDir="$out/share/zsh/vendor-completions"
386 fishCompDir="$out/share/fish/vendor_completions.d"
387 mkdir -p "$bashCompDir" "$zshCompDir" "$fishCompDir"
388 "$out/bin/${exeName}" --bash-completion-script "$out/bin/${exeName}" >"$bashCompDir/${exeName}"
389 "$out/bin/${exeName}" --zsh-completion-script "$out/bin/${exeName}" >"$zshCompDir/_${exeName}"
390 "$out/bin/${exeName}" --fish-completion-script "$out/bin/${exeName}" >"$fishCompDir/${exeName}.fish"
391
392 # Sanity check
393 grep -F ${exeName} <$bashCompDir/${exeName} >/dev/null || {
394 echo 'Could not find ${exeName} in completion script.'
395 exit 1
396 }
397 '';
398 });
399
400 /*
401 Modify a Haskell package to add shell completion scripts for the
402 given executables produced by it. These completion scripts will be
403 picked up automatically if the resulting derivation is installed,
404 e.g. by `nix-env -i`.
405
406 Invocation:
407 generateOptparseApplicativeCompletions commands pkg
408
409
410 commands: name of an executable
411 pkg: Haskell package that builds the executables
412 */
413 generateOptparseApplicativeCompletions = commands: pkg:
414 pkgs.lib.foldr generateOptparseApplicativeCompletion pkg commands;
415
416 # Don't fail at configure time if there are multiple versions of the
417 # same package in the (recursive) dependencies of the package being
418 # built. Will delay failures, if any, to compile time.
419 allowInconsistentDependencies = drv: overrideCabal drv (drv: {
420 allowInconsistentDependencies = true;
421 });
422}