nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at 20.03 422 lines 18 kB view raw
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}