Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at release-18.03 385 lines 17 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: overrideCabal drv (drv: { configureFlags = (drv.configureFlags or []) ++ [x]; }); 133 134 /* removeConfigureFlag drv x is a Haskell package like drv, but with 135 all cabal configure arguments that are equal to x removed. 136 137 > haskell.lib.removeConfigureFlag haskellPackages.servant "--verbose" 138 */ 139 removeConfigureFlag = drv: x: overrideCabal drv (drv: { configureFlags = lib.remove x (drv.configureFlags or []); }); 140 141 addBuildTool = drv: x: addBuildTools drv [x]; 142 addBuildTools = drv: xs: overrideCabal drv (drv: { buildTools = (drv.buildTools or []) ++ xs; }); 143 144 addExtraLibrary = drv: x: addExtraLibraries drv [x]; 145 addExtraLibraries = drv: xs: overrideCabal drv (drv: { extraLibraries = (drv.extraLibraries or []) ++ xs; }); 146 147 addBuildDepend = drv: x: addBuildDepends drv [x]; 148 addBuildDepends = drv: xs: overrideCabal drv (drv: { buildDepends = (drv.buildDepends or []) ++ xs; }); 149 150 addPkgconfigDepend = drv: x: addPkgconfigDepends drv [x]; 151 addPkgconfigDepends = drv: xs: overrideCabal drv (drv: { pkgconfigDepends = (drv.pkgconfigDepends or []) ++ xs; }); 152 153 addSetupDepend = drv: x: addSetupDepends drv [x]; 154 addSetupDepends = drv: xs: overrideCabal drv (drv: { setupHaskellDepends = (drv.setupHaskellDepends or []) ++ xs; }); 155 156 enableCabalFlag = drv: x: appendConfigureFlag (removeConfigureFlag drv "-f-${x}") "-f${x}"; 157 disableCabalFlag = drv: x: appendConfigureFlag (removeConfigureFlag drv "-f${x}") "-f-${x}"; 158 159 markBroken = drv: overrideCabal drv (drv: { broken = true; hydraPlatforms = []; }); 160 markBrokenVersion = version: drv: assert drv.version == version; markBroken drv; 161 162 enableLibraryProfiling = drv: overrideCabal drv (drv: { enableLibraryProfiling = true; }); 163 disableLibraryProfiling = drv: overrideCabal drv (drv: { enableLibraryProfiling = false; }); 164 165 enableSharedExecutables = drv: overrideCabal drv (drv: { enableSharedExecutables = true; }); 166 disableSharedExecutables = drv: overrideCabal drv (drv: { enableSharedExecutables = false; }); 167 168 enableSharedLibraries = drv: overrideCabal drv (drv: { enableSharedLibraries = true; }); 169 disableSharedLibraries = drv: overrideCabal drv (drv: { enableSharedLibraries = false; }); 170 171 enableDeadCodeElimination = drv: overrideCabal drv (drv: { enableDeadCodeElimination = true; }); 172 disableDeadCodeElimination = drv: overrideCabal drv (drv: { enableDeadCodeElimination = false; }); 173 174 enableStaticLibraries = drv: overrideCabal drv (drv: { enableStaticLibraries = true; }); 175 disableStaticLibraries = drv: overrideCabal drv (drv: { enableStaticLibraries = false; }); 176 177 appendPatch = drv: x: appendPatches drv [x]; 178 appendPatches = drv: xs: overrideCabal drv (drv: { patches = (drv.patches or []) ++ xs; }); 179 180 doHyperlinkSource = drv: overrideCabal drv (drv: { hyperlinkSource = true; }); 181 dontHyperlinkSource = drv: overrideCabal drv (drv: { hyperlinkSource = false; }); 182 183 disableHardening = drv: flags: overrideCabal drv (drv: { hardeningDisable = flags; }); 184 185 /* Let Nix strip the binary files. 186 * This removes debugging symbols. 187 */ 188 doStrip = drv: overrideCabal drv (drv: { dontStrip = false; }); 189 190 /* Stop Nix from stripping the binary files. 191 * This keeps debugging symbols. 192 */ 193 dontStrip = drv: overrideCabal drv (drv: { dontStrip = true; }); 194 195 /* Useful for debugging segfaults with gdb. 196 * This includes dontStrip. 197 */ 198 enableDWARFDebugging = drv: 199 # -g: enables debugging symbols 200 # --disable-*-stripping: tell GHC not to strip resulting binaries 201 # dontStrip: see above 202 appendConfigureFlag (dontStrip drv) "--ghc-options=-g --disable-executable-stripping --disable-library-stripping"; 203 204 /* Create a source distribution tarball like those found on hackage, 205 instead of building the package. 206 */ 207 sdistTarball = pkg: lib.overrideDerivation pkg (drv: { 208 name = "${drv.pname}-source-${drv.version}"; 209 # Since we disable the haddock phase, we also need to override the 210 # outputs since the separate doc output will not be produced. 211 outputs = ["out"]; 212 buildPhase = "./Setup sdist"; 213 haddockPhase = ":"; 214 checkPhase = ":"; 215 installPhase = "install -D dist/${drv.pname}-*.tar.gz $out/${drv.pname}-${drv.version}.tar.gz"; 216 fixupPhase = ":"; 217 }); 218 219 /* Use the gold linker. It is a linker for ELF that is designed 220 "to run as fast as possible on modern systems" 221 */ 222 linkWithGold = drv : appendConfigureFlag drv 223 "--ghc-option=-optl-fuse-ld=gold --ld-option=-fuse-ld=gold --with-ld=ld.gold"; 224 225 /* link executables statically against haskell libs to reduce 226 closure size 227 */ 228 justStaticExecutables = drv: overrideCabal drv (drv: { 229 enableSharedExecutables = false; 230 isLibrary = false; 231 doHaddock = false; 232 postFixup = "rm -rf $out/lib $out/nix-support $out/share/doc"; 233 } // lib.optionalAttrs (pkgs.hostPlatform.isDarwin) { 234 configureFlags = (drv.configureFlags or []) ++ ["--ghc-option=-optl=-dead_strip"]; 235 }); 236 237 /* Build a source distribution tarball instead of using the source files 238 directly. The effect is that the package is built as if it were published 239 on hackage. This can be used as a test for the source distribution, 240 assuming the build fails when packaging mistakes are in the cabal file. 241 */ 242 buildFromSdist = pkg: lib.overrideDerivation pkg (drv: { 243 unpackPhase = let src = sdistTarball pkg; tarname = "${pkg.pname}-${pkg.version}"; in '' 244 echo "Source tarball is at ${src}/${tarname}.tar.gz" 245 tar xf ${src}/${tarname}.tar.gz 246 cd ${pkg.pname}-* 247 ''; 248 }); 249 250 /* Build the package in a strict way to uncover potential problems. 251 This includes buildFromSdist and failOnAllWarnings. 252 */ 253 buildStrictly = pkg: buildFromSdist (failOnAllWarnings pkg); 254 255 /* Turn on most of the compiler warnings and fail the build if any 256 of them occur. */ 257 failOnAllWarnings = drv: appendConfigureFlag drv "--ghc-option=-Wall --ghc-option=-Werror"; 258 259 /* Add a post-build check to verify that dependencies declared in 260 the cabal file are actually used. 261 262 The first attrset argument can be used to configure the strictness 263 of this check and a list of ignored package names that would otherwise 264 cause false alarms. 265 */ 266 checkUnusedPackages = 267 { ignoreEmptyImports ? false 268 , ignoreMainModule ? false 269 , ignorePackages ? [] 270 } : drv : 271 overrideCabal (appendConfigureFlag drv "--ghc-option=-ddump-minimal-imports") (_drv: { 272 postBuild = with lib; 273 let args = concatStringsSep " " ( 274 optional ignoreEmptyImports "--ignore-empty-imports" ++ 275 optional ignoreMainModule "--ignore-main-module" ++ 276 map (pkg: "--ignore-package ${pkg}") ignorePackages 277 ); 278 in "${pkgs.haskellPackages.packunused}/bin/packunused" + 279 optionalString (args != "") " ${args}"; 280 }); 281 282 buildStackProject = pkgs.callPackage ./generic-stack-builder.nix { }; 283 284 /* Add a dummy command to trigger a build despite an equivalent 285 earlier build that is present in the store or cache. 286 */ 287 triggerRebuild = drv: i: overrideCabal drv (drv: { postUnpack = ": trigger rebuild ${toString i}"; }); 288 289 /* Override the sources for the package and optionaly the version. 290 This also takes of removing editedCabalFile. 291 */ 292 overrideSrc = drv: { src, version ? drv.version }: 293 overrideCabal drv (_: { inherit src version; editedCabalFile = null; }); 294 295 # Get all of the build inputs of a haskell package, divided by category. 296 getBuildInputs = p: 297 (overrideCabal p (args: { 298 passthru = (args.passthru or {}) // { 299 _getBuildInputs = extractBuildInputs p.compiler args; 300 }; 301 }))._getBuildInputs; 302 303 # Extract the haskell build inputs of a haskell package. 304 # This is useful to build environments for developing on that 305 # package. 306 getHaskellBuildInputs = p: (getBuildInputs p).haskellBuildInputs; 307 308 # Under normal evaluation, simply return the original package. Under 309 # nix-shell evaluation, return a nix-shell optimized environment. 310 shellAware = p: if lib.inNixShell then p.env else p; 311 312 ghcInfo = ghc: 313 rec { isCross = (ghc.cross or null) != null; 314 isGhcjs = ghc.isGhcjs or false; 315 nativeGhc = if isCross || isGhcjs 316 then ghc.bootPkgs.ghc 317 else ghc; 318 }; 319 320 ### mkDerivation helpers 321 # These allow external users of a haskell package to extract 322 # information about how it is built in the same way that the 323 # generic haskell builder does, by reusing the same functions. 324 # Each function here has the same interface as mkDerivation and thus 325 # can be called for a given package simply by overriding the 326 # mkDerivation argument it used. See getHaskellBuildInputs above for 327 # an example of this. 328 329 # Some information about which phases should be run. 330 controlPhases = ghc: let inherit (ghcInfo ghc) isCross; in 331 { doCheck ? !isCross && (lib.versionOlder "7.4" ghc.version) 332 , doBenchmark ? false 333 , ... 334 }: { inherit doCheck doBenchmark; }; 335 336 # Divide the build inputs of the package into useful sets. 337 extractBuildInputs = ghc: 338 { setupHaskellDepends ? [], extraLibraries ? [] 339 , librarySystemDepends ? [], executableSystemDepends ? [] 340 , pkgconfigDepends ? [], libraryPkgconfigDepends ? [] 341 , executablePkgconfigDepends ? [], testPkgconfigDepends ? [] 342 , benchmarkPkgconfigDepends ? [], testDepends ? [] 343 , testHaskellDepends ? [], testSystemDepends ? [] 344 , testToolDepends ? [], benchmarkDepends ? [] 345 , benchmarkHaskellDepends ? [], benchmarkSystemDepends ? [] 346 , benchmarkToolDepends ? [], buildDepends ? [] 347 , libraryHaskellDepends ? [], executableHaskellDepends ? [] 348 , ... 349 }@args: 350 let inherit (ghcInfo ghc) isGhcjs nativeGhc; 351 inherit (controlPhases ghc args) doCheck doBenchmark; 352 isHaskellPkg = x: x ? isHaskellLibrary; 353 allPkgconfigDepends = 354 pkgconfigDepends ++ libraryPkgconfigDepends ++ 355 executablePkgconfigDepends ++ 356 lib.optionals doCheck testPkgconfigDepends ++ 357 lib.optionals doBenchmark benchmarkPkgconfigDepends; 358 otherBuildInputs = 359 setupHaskellDepends ++ extraLibraries ++ 360 librarySystemDepends ++ executableSystemDepends ++ 361 allPkgconfigDepends ++ 362 lib.optionals doCheck ( testDepends ++ testHaskellDepends ++ 363 testSystemDepends ++ testToolDepends 364 ) ++ 365 # ghcjs's hsc2hs calls out to the native hsc2hs 366 lib.optional isGhcjs nativeGhc ++ 367 lib.optionals doBenchmark ( benchmarkDepends ++ 368 benchmarkHaskellDepends ++ 369 benchmarkSystemDepends ++ 370 benchmarkToolDepends 371 ); 372 propagatedBuildInputs = 373 buildDepends ++ libraryHaskellDepends ++ 374 executableHaskellDepends; 375 allBuildInputs = propagatedBuildInputs ++ otherBuildInputs; 376 isHaskellPartition = 377 lib.partition isHaskellPkg allBuildInputs; 378 in 379 { haskellBuildInputs = isHaskellPartition.right; 380 systemBuildInputs = isHaskellPartition.wrong; 381 inherit propagatedBuildInputs otherBuildInputs 382 allPkgconfigDepends; 383 }; 384 385}