Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at release-19.03 420 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 markBrokenVersion = version: drv: assert drv.version == version; markBroken drv; 165 166 enableLibraryProfiling = drv: overrideCabal drv (drv: { enableLibraryProfiling = true; }); 167 disableLibraryProfiling = drv: overrideCabal drv (drv: { enableLibraryProfiling = false; }); 168 169 enableExecutableProfiling = drv: overrideCabal drv (drv: { enableExecutableProfiling = true; }); 170 disableExecutableProfiling = drv: overrideCabal drv (drv: { enableExecutableProfiling = false; }); 171 172 enableSharedExecutables = drv: overrideCabal drv (drv: { enableSharedExecutables = true; }); 173 disableSharedExecutables = drv: overrideCabal drv (drv: { enableSharedExecutables = false; }); 174 175 enableSharedLibraries = drv: overrideCabal drv (drv: { enableSharedLibraries = true; }); 176 disableSharedLibraries = drv: overrideCabal drv (drv: { enableSharedLibraries = false; }); 177 178 enableDeadCodeElimination = drv: overrideCabal drv (drv: { enableDeadCodeElimination = true; }); 179 disableDeadCodeElimination = drv: overrideCabal drv (drv: { enableDeadCodeElimination = false; }); 180 181 enableStaticLibraries = drv: overrideCabal drv (drv: { enableStaticLibraries = true; }); 182 disableStaticLibraries = drv: overrideCabal drv (drv: { enableStaticLibraries = false; }); 183 184 enableSeparateBinOutput = drv: overrideCabal drv (drv: { enableSeparateBinOutput = true; }); 185 186 appendPatch = drv: x: appendPatches drv [x]; 187 appendPatches = drv: xs: overrideCabal drv (drv: { patches = (drv.patches or []) ++ xs; }); 188 189 doHyperlinkSource = drv: overrideCabal drv (drv: { hyperlinkSource = true; }); 190 dontHyperlinkSource = drv: overrideCabal drv (drv: { hyperlinkSource = false; }); 191 192 disableHardening = drv: flags: overrideCabal drv (drv: { hardeningDisable = flags; }); 193 194 /* Let Nix strip the binary files. 195 * This removes debugging symbols. 196 */ 197 doStrip = drv: overrideCabal drv (drv: { dontStrip = false; }); 198 199 /* Stop Nix from stripping the binary files. 200 * This keeps debugging symbols. 201 */ 202 dontStrip = drv: overrideCabal drv (drv: { dontStrip = true; }); 203 204 /* Useful for debugging segfaults with gdb. 205 * This includes dontStrip. 206 */ 207 enableDWARFDebugging = drv: 208 # -g: enables debugging symbols 209 # --disable-*-stripping: tell GHC not to strip resulting binaries 210 # dontStrip: see above 211 appendConfigureFlag (dontStrip drv) "--ghc-options=-g --disable-executable-stripping --disable-library-stripping"; 212 213 /* Create a source distribution tarball like those found on hackage, 214 instead of building the package. 215 */ 216 sdistTarball = pkg: lib.overrideDerivation pkg (drv: { 217 name = "${drv.pname}-source-${drv.version}"; 218 # Since we disable the haddock phase, we also need to override the 219 # outputs since the separate doc output will not be produced. 220 outputs = ["out"]; 221 buildPhase = "./Setup sdist"; 222 haddockPhase = ":"; 223 checkPhase = ":"; 224 installPhase = "install -D dist/${drv.pname}-*.tar.gz $out/${drv.pname}-${drv.version}.tar.gz"; 225 fixupPhase = ":"; 226 }); 227 228 /* Use the gold linker. It is a linker for ELF that is designed 229 "to run as fast as possible on modern systems" 230 */ 231 linkWithGold = drv : appendConfigureFlag drv 232 "--ghc-option=-optl-fuse-ld=gold --ld-option=-fuse-ld=gold --with-ld=ld.gold"; 233 234 /* link executables statically against haskell libs to reduce 235 closure size 236 */ 237 justStaticExecutables = drv: overrideCabal drv (drv: { 238 enableSharedExecutables = false; 239 enableLibraryProfiling = false; 240 isLibrary = false; 241 doHaddock = false; 242 postFixup = "rm -rf $out/lib $out/nix-support $out/share/doc"; 243 }); 244 245 /* Build a source distribution tarball instead of using the source files 246 directly. The effect is that the package is built as if it were published 247 on hackage. This can be used as a test for the source distribution, 248 assuming the build fails when packaging mistakes are in the cabal file. 249 */ 250 buildFromSdist = pkg: overrideCabal pkg (drv: { 251 src = "${sdistTarball pkg}/${pkg.pname}-${pkg.version}.tar.gz"; 252 253 # Revising and jailbreaking the cabal file has been handled in sdistTarball 254 revision = null; 255 editedCabalFile = null; 256 jailbreak = false; 257 }); 258 259 /* Build the package in a strict way to uncover potential problems. 260 This includes buildFromSdist and failOnAllWarnings. 261 */ 262 buildStrictly = pkg: buildFromSdist (failOnAllWarnings pkg); 263 264 /* Disable core optimizations, significantly speeds up build time */ 265 disableOptimization = pkg: appendConfigureFlag pkg "--disable-optimization"; 266 267 /* Turn on most of the compiler warnings and fail the build if any 268 of them occur. */ 269 failOnAllWarnings = drv: appendConfigureFlag drv "--ghc-option=-Wall --ghc-option=-Werror"; 270 271 /* Add a post-build check to verify that dependencies declared in 272 the cabal file are actually used. 273 274 The first attrset argument can be used to configure the strictness 275 of this check and a list of ignored package names that would otherwise 276 cause false alarms. 277 */ 278 checkUnusedPackages = 279 { ignoreEmptyImports ? false 280 , ignoreMainModule ? false 281 , ignorePackages ? [] 282 } : drv : 283 overrideCabal (appendConfigureFlag drv "--ghc-option=-ddump-minimal-imports") (_drv: { 284 postBuild = with lib; 285 let args = concatStringsSep " " ( 286 optional ignoreEmptyImports "--ignore-empty-imports" ++ 287 optional ignoreMainModule "--ignore-main-module" ++ 288 map (pkg: "--ignore-package ${pkg}") ignorePackages 289 ); 290 in "${pkgs.haskellPackages.packunused}/bin/packunused" + 291 optionalString (args != "") " ${args}"; 292 }); 293 294 buildStackProject = pkgs.callPackage ./generic-stack-builder.nix { }; 295 296 /* Add a dummy command to trigger a build despite an equivalent 297 earlier build that is present in the store or cache. 298 */ 299 triggerRebuild = drv: i: overrideCabal drv (drv: { postUnpack = ": trigger rebuild ${toString i}"; }); 300 301 /* Override the sources for the package and optionaly the version. 302 This also takes of removing editedCabalFile. 303 */ 304 overrideSrc = drv: { src, version ? drv.version }: 305 overrideCabal drv (_: { inherit src version; editedCabalFile = null; }); 306 307 # Get all of the build inputs of a haskell package, divided by category. 308 getBuildInputs = p: p.getBuildInputs; 309 310 # Extract the haskell build inputs of a haskell package. 311 # This is useful to build environments for developing on that 312 # package. 313 getHaskellBuildInputs = p: (getBuildInputs p).haskellBuildInputs; 314 315 # Under normal evaluation, simply return the original package. Under 316 # nix-shell evaluation, return a nix-shell optimized environment. 317 shellAware = p: if lib.inNixShell then p.env else p; 318 319 ghcInfo = ghc: 320 rec { isCross = (ghc.cross or null) != null; 321 isGhcjs = ghc.isGhcjs or false; 322 nativeGhc = if isCross || isGhcjs 323 then ghc.bootPkgs.ghc 324 else ghc; 325 }; 326 327 ### mkDerivation helpers 328 # These allow external users of a haskell package to extract 329 # information about how it is built in the same way that the 330 # generic haskell builder does, by reusing the same functions. 331 # Each function here has the same interface as mkDerivation and thus 332 # can be called for a given package simply by overriding the 333 # mkDerivation argument it used. See getHaskellBuildInputs above for 334 # an example of this. 335 336 # Some information about which phases should be run. 337 controlPhases = ghc: let inherit (ghcInfo ghc) isCross; in 338 { doCheck ? !isCross && (lib.versionOlder "7.4" ghc.version) 339 , doBenchmark ? false 340 , ... 341 }: { inherit doCheck doBenchmark; }; 342 343 # Utility to convert a directory full of `cabal2nix`-generated files into a 344 # package override set 345 # 346 # packagesFromDirectory : { directory : Directory, ... } -> HaskellPackageOverrideSet 347 packagesFromDirectory = 348 { directory, ... }: 349 350 self: super: 351 let 352 haskellPaths = builtins.attrNames (builtins.readDir directory); 353 354 toKeyVal = file: { 355 name = builtins.replaceStrings [ ".nix" ] [ "" ] file; 356 357 value = self.callPackage (directory + "/${file}") { }; 358 }; 359 360 in 361 builtins.listToAttrs (map toKeyVal haskellPaths); 362 363 addOptparseApplicativeCompletionScripts = exeName: pkg: 364 builtins.trace "addOptparseApplicativeCompletionScripts is deprecated in favor of generateOptparseApplicativeCompletion. Please change ${pkg.name} to use the latter or its plural form." 365 (generateOptparseApplicativeCompletion exeName pkg); 366 367 /* 368 Modify a Haskell package to add shell completion scripts for the 369 given executable produced by it. These completion scripts will be 370 picked up automatically if the resulting derivation is installed, 371 e.g. by `nix-env -i`. 372 373 Invocation: 374 generateOptparseApplicativeCompletions command pkg 375 376 377 command: name of an executable 378 pkg: Haskell package that builds the executables 379 */ 380 generateOptparseApplicativeCompletion = exeName: pkg: overrideCabal pkg (drv: { 381 postInstall = (drv.postInstall or "") + '' 382 bashCompDir="$out/share/bash-completion/completions" 383 zshCompDir="$out/share/zsh/vendor-completions" 384 fishCompDir="$out/share/fish/vendor_completions.d" 385 mkdir -p "$bashCompDir" "$zshCompDir" "$fishCompDir" 386 "$out/bin/${exeName}" --bash-completion-script "$out/bin/${exeName}" >"$bashCompDir/${exeName}" 387 "$out/bin/${exeName}" --zsh-completion-script "$out/bin/${exeName}" >"$zshCompDir/_${exeName}" 388 "$out/bin/${exeName}" --fish-completion-script "$out/bin/${exeName}" >"$fishCompDir/${exeName}.fish" 389 390 # Sanity check 391 grep -F ${exeName} <$bashCompDir/${exeName} >/dev/null || { 392 echo 'Could not find ${exeName} in completion script.' 393 exit 1 394 } 395 ''; 396 }); 397 398 /* 399 Modify a Haskell package to add shell completion scripts for the 400 given executables produced by it. These completion scripts will be 401 picked up automatically if the resulting derivation is installed, 402 e.g. by `nix-env -i`. 403 404 Invocation: 405 generateOptparseApplicativeCompletions commands pkg 406 407 408 commands: name of an executable 409 pkg: Haskell package that builds the executables 410 */ 411 generateOptparseApplicativeCompletions = commands: pkg: 412 pkgs.lib.foldr generateOptparseApplicativeCompletion pkg commands; 413 414 # Don't fail at configure time if there are multiple versions of the 415 # same package in the (recursive) dependencies of the package being 416 # built. Will delay failures, if any, to compile time. 417 allowInconsistentDependencies = drv: overrideCabal drv (drv: { 418 allowInconsistentDependencies = true; 419 }); 420}