Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at devShellTools-shell 1097 lines 42 kB view raw
1{ 2 lib, 3 stdenv, 4 buildPackages, 5 buildHaskellPackages, 6 ghc, 7 jailbreak-cabal, 8 hscolour, 9 cpphs, 10 runCommandCC, 11 ghcWithHoogle, 12 ghcWithPackages, 13 nodejs, 14 devShellTools, 15}: 16 17let 18 isCross = stdenv.buildPlatform != stdenv.hostPlatform; 19 20 # Note that ghc.isGhcjs != stdenv.hostPlatform.isGhcjs. 21 # ghc.isGhcjs implies that we are using ghcjs, a project separate from GHC. 22 # (mere) stdenv.hostPlatform.isGhcjs means that we are using GHC's JavaScript 23 # backend. The latter is a normal cross compilation backend and needs little 24 # special accommodation. 25 outputsJS = ghc.isGhcjs or false || stdenv.hostPlatform.isGhcjs; 26 27 # Pass the "wrong" C compiler rather than none at all so packages that just 28 # use the C preproccessor still work, see 29 # https://github.com/haskell/cabal/issues/6466 for details. 30 cc = 31 if stdenv.hasCC then 32 "$CC" 33 else if stdenv.hostPlatform.isGhcjs then 34 "${emscripten}/bin/emcc" 35 else 36 "$CC_FOR_BUILD"; 37 38 inherit (buildPackages) 39 fetchurl 40 removeReferencesTo 41 pkg-config 42 coreutils 43 glibcLocales 44 emscripten 45 ; 46 47in 48 49{ 50 pname, 51 dontStrip ? outputsJS, 52 version, 53 revision ? null, 54 sha256 ? null, 55 src ? fetchurl { 56 url = "mirror://hackage/${pname}-${version}.tar.gz"; 57 inherit sha256; 58 }, 59 sourceRoot ? null, 60 setSourceRoot ? null, 61 # Extra environment variables to set during the build. 62 # See: `../../../doc/languages-frameworks/haskell.section.md` 63 env ? { }, 64 buildDepends ? [ ], 65 setupHaskellDepends ? [ ], 66 libraryHaskellDepends ? [ ], 67 executableHaskellDepends ? [ ], 68 buildTarget ? "", 69 buildTools ? [ ], 70 libraryToolDepends ? [ ], 71 executableToolDepends ? [ ], 72 testToolDepends ? [ ], 73 benchmarkToolDepends ? [ ], 74 configureFlags ? [ ], 75 buildFlags ? [ ], 76 haddockFlags ? [ ], 77 description ? null, 78 doCheck ? !isCross, 79 doBenchmark ? false, 80 doHoogle ? true, 81 doHaddockQuickjump ? doHoogle, 82 doInstallIntermediates ? false, 83 editedCabalFile ? null, 84 enableLibraryProfiling ? !outputsJS, 85 enableExecutableProfiling ? false, 86 profilingDetail ? "exported-functions", 87 # TODO enable shared libs for cross-compiling 88 enableSharedExecutables ? false, 89 enableSharedLibraries ? 90 !stdenv.hostPlatform.isStatic 91 && (ghc.enableShared or false) 92 && !stdenv.hostPlatform.useAndroidPrebuilt, 93 enableDeadCodeElimination ? (!stdenv.hostPlatform.isDarwin), # TODO: use -dead_strip for darwin 94 # Disabling this for ghcjs prevents this crash: https://gitlab.haskell.org/ghc/ghc/-/issues/23235 95 enableStaticLibraries ? 96 !(stdenv.hostPlatform.isWindows || stdenv.hostPlatform.isWasm || stdenv.hostPlatform.isGhcjs), 97 enableHsc2hsViaAsm ? stdenv.hostPlatform.isWindows, 98 extraLibraries ? [ ], 99 librarySystemDepends ? [ ], 100 executableSystemDepends ? [ ], 101 # On macOS, statically linking against system frameworks is not supported; 102 # see https://developer.apple.com/library/content/qa/qa1118/_index.html 103 # They must be propagated to the environment of any executable linking with the library 104 libraryFrameworkDepends ? [ ], 105 executableFrameworkDepends ? [ ], 106 homepage ? "https://hackage.haskell.org/package/${pname}", 107 platforms ? with lib.platforms; all, # GHC can cross-compile 108 badPlatforms ? lib.platforms.none, 109 hydraPlatforms ? null, 110 hyperlinkSource ? true, 111 isExecutable ? false, 112 isLibrary ? !isExecutable, 113 jailbreak ? false, 114 license, 115 enableParallelBuilding ? true, 116 maintainers ? null, 117 teams ? null, 118 changelog ? null, 119 mainProgram ? null, 120 doCoverage ? false, 121 doHaddock ? !(ghc.isHaLVM or false) && (ghc.hasHaddock or true), 122 doHaddockInterfaces ? doHaddock && lib.versionAtLeast ghc.version "9.0.1", 123 passthru ? { }, 124 pkg-configDepends ? [ ], 125 libraryPkgconfigDepends ? [ ], 126 executablePkgconfigDepends ? [ ], 127 testPkgconfigDepends ? [ ], 128 benchmarkPkgconfigDepends ? [ ], 129 testDepends ? [ ], 130 testHaskellDepends ? [ ], 131 testSystemDepends ? [ ], 132 testFrameworkDepends ? [ ], 133 benchmarkDepends ? [ ], 134 benchmarkHaskellDepends ? [ ], 135 benchmarkSystemDepends ? [ ], 136 benchmarkFrameworkDepends ? [ ], 137 # testTarget is deprecated. Use testTargets instead. 138 testTarget ? "", 139 testTargets ? lib.strings.splitString " " testTarget, 140 testFlags ? [ ], 141 broken ? false, 142 preCompileBuildDriver ? null, 143 postCompileBuildDriver ? null, 144 preUnpack ? null, 145 postUnpack ? null, 146 patches ? null, 147 patchPhase ? null, 148 prePatch ? "", 149 postPatch ? "", 150 preConfigure ? null, 151 postConfigure ? null, 152 preBuild ? null, 153 postBuild ? null, 154 preHaddock ? null, 155 postHaddock ? null, 156 installPhase ? null, 157 preInstall ? null, 158 postInstall ? null, 159 checkPhase ? null, 160 preCheck ? null, 161 postCheck ? null, 162 preFixup ? null, 163 postFixup ? null, 164 shellHook ? "", 165 coreSetup ? false, # Use only core packages to build Setup.hs. 166 useCpphs ? false, 167 hardeningDisable ? null, 168 enableSeparateBinOutput ? false, 169 enableSeparateDataOutput ? false, 170 enableSeparateDocOutput ? doHaddock, 171 enableSeparateIntermediatesOutput ? false, 172 # Don't fail at configure time if there are multiple versions of the 173 # same package in the (recursive) dependencies of the package being 174 # built. Will delay failures, if any, to compile time. 175 allowInconsistentDependencies ? false, 176 maxBuildCores ? 16, # more cores usually don't improve performance: https://ghc.haskell.org/trac/ghc/ticket/9221 177 # If set to true, this builds a pre-linked .o file for this Haskell library. 178 # This can make it slightly faster to load this library into GHCi, but takes 179 # extra disk space and compile time. 180 enableLibraryForGhci ? false, 181 # Set this to a previous build of this same package to reuse the intermediate 182 # build products from that prior build as a starting point for accelerating 183 # this build 184 previousIntermediates ? null, 185 # References to these store paths are forbidden in the produced output. 186 disallowedRequisites ? [ ], 187 # Whether to allow the produced output to refer to `ghc`. 188 # 189 # This is used by `haskell.lib.justStaticExecutables` to help prevent static 190 # Haskell binaries from having erroneous dependencies on GHC. 191 # 192 # See https://nixos.org/manual/nixpkgs/unstable/#haskell-packaging-helpers 193 # or its source doc/languages-frameworks/haskell.section.md 194 disallowGhcReference ? false, 195 # Cabal 3.8 which is shipped by default for GHC >= 9.3 always calls 196 # `pkg-config --libs --static` as part of the configure step. This requires 197 # Requires.private dependencies of pkg-config dependencies to be present in 198 # PKG_CONFIG_PATH which is normally not the case in nixpkgs (except in pkgsStatic). 199 # Since there is no patch or upstream patch yet, we replicate the automatic 200 # propagation of dependencies in pkgsStatic for allPkgConfigDepends for 201 # GHC >= 9.3 by default. This option allows overriding this behavior manually 202 # if mismatching Cabal and GHC versions are used. 203 # See also <https://github.com/haskell/cabal/issues/8455>. 204 __propagatePkgConfigDepends ? lib.versionAtLeast ghc.version "9.3", 205 # Propagation can easily lead to the argv limit being exceeded in linker or C 206 # compiler invocations. To work around this we can only propagate derivations 207 # that are known to provide pkg-config modules, as indicated by the presence 208 # of `meta.pkgConfigModules`. This option defaults to false for now, since 209 # this metadata is far from complete in nixpkgs. 210 __onlyPropagateKnownPkgConfigModules ? false, 211}@args: 212 213assert editedCabalFile != null -> revision != null; 214 215# --enable-static does not work on windows. This is a bug in GHC. 216# --enable-static will pass -staticlib to ghc, which only works for mach-o and elf. 217assert stdenv.hostPlatform.isWindows -> enableStaticLibraries == false; 218assert stdenv.hostPlatform.isWasm -> enableStaticLibraries == false; 219 220let 221 222 inherit (lib) 223 optional 224 optionals 225 optionalString 226 versionAtLeast 227 concatStringsSep 228 enableFeature 229 optionalAttrs 230 ; 231 232 isGhcjs = ghc.isGhcjs or false; 233 isHaLVM = ghc.isHaLVM or false; 234 235 # GHC used for building Setup.hs 236 # 237 # Same as our GHC, unless we're cross, in which case it is native GHC with the 238 # same version, or ghcjs, in which case its the ghc used to build ghcjs. 239 nativeGhc = buildHaskellPackages.ghc; 240 241 # the target dir for haddock documentation 242 docdir = docoutput: docoutput + "/share/doc/" + pname + "-" + version; 243 244 binDir = if enableSeparateBinOutput then "$bin/bin" else "$out/bin"; 245 246 newCabalFileUrl = "mirror://hackage/${pname}-${version}/revision/${revision}.cabal"; 247 newCabalFile = fetchurl { 248 url = newCabalFileUrl; 249 sha256 = editedCabalFile; 250 name = "${pname}-${version}-r${revision}.cabal"; 251 }; 252 253 defaultSetupHs = builtins.toFile "Setup.hs" '' 254 import Distribution.Simple 255 main = defaultMain 256 ''; 257 258 # This awk expression transforms a package conf file like 259 # 260 # author: John Doe <john-doe@example.com> 261 # description: 262 # The purpose of this library is to do 263 # foo and bar among other things 264 # 265 # into a more easily processeable form: 266 # 267 # author: John Doe <john-doe@example.com> 268 # description: The purpose of this library is to do foo and bar among other things 269 unprettyConf = builtins.toFile "unpretty-cabal-conf.awk" '' 270 /^[^ ]+:/ { 271 # When the line starts with a new field, terminate the previous one with a newline 272 if (started == 1) print "" 273 # to strip leading spaces 274 $1=$1 275 printf "%s", $0 276 started=1 277 } 278 279 /^ +/ { 280 # to strip leading spaces 281 $1=$1 282 printf " %s", $0 283 } 284 285 # Terminate the final field with a newline 286 END { print "" } 287 ''; 288 289 crossCabalFlags = [ 290 "--with-ghc=${ghcCommand}" 291 "--with-ghc-pkg=${ghc.targetPrefix}ghc-pkg" 292 "--with-gcc=${cc}" 293 ] 294 ++ optionals stdenv.hasCC [ 295 "--with-ld=${stdenv.cc.bintools.targetPrefix}ld" 296 "--with-ar=${stdenv.cc.bintools.targetPrefix}ar" 297 # use the one that comes with the cross compiler. 298 "--with-hsc2hs=${ghc.targetPrefix}hsc2hs" 299 "--with-strip=${stdenv.cc.bintools.targetPrefix}strip" 300 ] 301 ++ optionals (!isHaLVM) [ 302 "--hsc2hs-option=--cross-compile" 303 (optionalString enableHsc2hsViaAsm "--hsc2hs-option=--via-asm") 304 ] 305 ++ optional (allPkgconfigDepends != [ ]) "--with-pkg-config=${pkg-config.targetPrefix}pkg-config"; 306 307 makeGhcOptions = opts: lib.concatStringsSep " " (map (opt: "--ghc-option=${opt}") opts); 308 309 buildFlagsString = optionalString (buildFlags != [ ]) (" " + concatStringsSep " " buildFlags); 310 311 defaultConfigureFlags = [ 312 "--verbose" 313 "--prefix=$out" 314 # Note: This must be kept in sync manually with mkGhcLibdir 315 ("--libdir=\\$prefix/lib/\\$compiler" + lib.optionalString (ghc ? hadrian) "/lib") 316 "--libsubdir=\\$abi/\\$libname" 317 (optionalString enableSeparateDataOutput "--datadir=$data/share/${ghcNameWithPrefix}") 318 (optionalString enableSeparateDocOutput "--docdir=${docdir "$doc"}") 319 ] 320 ++ optionals stdenv.hasCC [ 321 "--with-gcc=$CC" # Clang won't work without that extra information. 322 ] 323 ++ [ 324 "--package-db=$packageConfDir" 325 (optionalString ( 326 enableSharedExecutables && stdenv.hostPlatform.isLinux 327 ) "--ghc-option=-optl=-Wl,-rpath=$out/${ghcLibdir}/${pname}-${version}") 328 (optionalString ( 329 enableSharedExecutables && stdenv.hostPlatform.isDarwin 330 ) "--ghc-option=-optl=-Wl,-headerpad_max_install_names") 331 (optionalString enableParallelBuilding (makeGhcOptions [ 332 "-j$NIX_BUILD_CORES" 333 "+RTS" 334 "-A64M" 335 "-RTS" 336 ])) 337 (optionalString useCpphs ( 338 "--with-cpphs=${cpphs}/bin/cpphs " 339 + (makeGhcOptions [ 340 "-cpp" 341 "-pgmP${cpphs}/bin/cpphs" 342 "-optP--cpp" 343 ]) 344 )) 345 (enableFeature enableLibraryProfiling "library-profiling") 346 (optionalString ( 347 enableExecutableProfiling || enableLibraryProfiling 348 ) "--profiling-detail=${profilingDetail}") 349 (enableFeature enableExecutableProfiling "profiling") 350 (enableFeature enableSharedLibraries "shared") 351 (enableFeature doCoverage "coverage") 352 (enableFeature enableStaticLibraries "static") 353 (enableFeature enableSharedExecutables "executable-dynamic") 354 (enableFeature doCheck "tests") 355 (enableFeature doBenchmark "benchmarks") 356 "--enable-library-vanilla" # TODO: Should this be configurable? 357 (enableFeature enableLibraryForGhci "library-for-ghci") 358 (enableFeature enableDeadCodeElimination "split-sections") 359 (enableFeature (!dontStrip) "library-stripping") 360 (enableFeature (!dontStrip) "executable-stripping") 361 ] 362 ++ optionals isGhcjs [ 363 "--ghcjs" 364 ] 365 ++ optionals isCross ( 366 [ 367 "--configure-option=--host=${stdenv.hostPlatform.config}" 368 ] 369 ++ crossCabalFlags 370 ) 371 ++ optionals enableSeparateBinOutput [ 372 "--bindir=${binDir}" 373 ] 374 ++ optionals (doHaddockInterfaces && isLibrary) [ 375 "--ghc-option=-haddock" 376 ]; 377 378 postPhases = optional doInstallIntermediates "installIntermediatesPhase"; 379 380 setupCompileFlags = [ 381 (optionalString (!coreSetup) "-package-db=$setupPackageConfDir") 382 "-threaded" # https://github.com/haskell/cabal/issues/2398 383 ]; 384 385 isHaskellPkg = x: x ? isHaskellLibrary; 386 387 # Work around a Cabal bug requiring pkg-config --static --libs to work even 388 # when linking dynamically, affecting Cabal 3.8 and 3.9. 389 # https://github.com/haskell/cabal/issues/8455 390 # 391 # For this, we treat the runtime system/pkg-config dependencies of a Haskell 392 # derivation as if they were propagated from their dependencies which allows 393 # pkg-config --static to work in most cases. 394 allPkgconfigDepends = 395 let 396 # If __onlyPropagateKnownPkgConfigModules is set, packages without 397 # meta.pkgConfigModules will be filtered out, otherwise all packages in 398 # buildInputs and propagatePlainBuildInputs are propagated. 399 propagateValue = 400 drv: lib.isDerivation drv && (__onlyPropagateKnownPkgConfigModules -> drv ? meta.pkgConfigModules); 401 402 # Take list of derivations and return list of the transitive dependency 403 # closure, only taking into account buildInputs. Loosely based on 404 # closePropagationFast. 405 propagatePlainBuildInputs = 406 drvs: 407 builtins.map (i: i.val) ( 408 builtins.genericClosure { 409 startSet = builtins.map (drv: { 410 key = drv.outPath; 411 val = drv; 412 }) (builtins.filter propagateValue drvs); 413 operator = 414 { val, ... }: 415 builtins.concatMap ( 416 drv: 417 if propagateValue drv then 418 [ 419 { 420 key = drv.outPath; 421 val = drv; 422 } 423 ] 424 else 425 [ ] 426 ) (val.buildInputs or [ ] ++ val.propagatedBuildInputs or [ ]); 427 } 428 ); 429 in 430 431 if __propagatePkgConfigDepends then 432 propagatePlainBuildInputs allPkgconfigDepends' 433 else 434 allPkgconfigDepends'; 435 allPkgconfigDepends' = 436 pkg-configDepends 437 ++ libraryPkgconfigDepends 438 ++ executablePkgconfigDepends 439 ++ optionals doCheck testPkgconfigDepends 440 ++ optionals doBenchmark benchmarkPkgconfigDepends; 441 442 depsBuildBuild = [ 443 nativeGhc 444 ] 445 # CC_FOR_BUILD may be necessary if we have no C preprocessor for the host 446 # platform. See crossCabalFlags above for more details. 447 ++ lib.optionals (!stdenv.hasCC) [ buildPackages.stdenv.cc ]; 448 collectedToolDepends = 449 buildTools 450 ++ libraryToolDepends 451 ++ executableToolDepends 452 ++ optionals doCheck testToolDepends 453 ++ optionals doBenchmark benchmarkToolDepends; 454 nativeBuildInputs = [ 455 ghc 456 removeReferencesTo 457 ] 458 ++ optional (allPkgconfigDepends != [ ]) ( 459 assert pkg-config != null; 460 pkg-config 461 ) 462 ++ setupHaskellDepends 463 ++ collectedToolDepends 464 ++ optional stdenv.hostPlatform.isGhcjs nodejs; 465 propagatedBuildInputs = 466 buildDepends ++ libraryHaskellDepends ++ executableHaskellDepends ++ libraryFrameworkDepends; 467 otherBuildInputsHaskell = 468 optionals doCheck (testDepends ++ testHaskellDepends) 469 ++ optionals doBenchmark (benchmarkDepends ++ benchmarkHaskellDepends); 470 otherBuildInputsSystem = 471 extraLibraries 472 ++ librarySystemDepends 473 ++ executableSystemDepends 474 ++ executableFrameworkDepends 475 ++ allPkgconfigDepends 476 ++ optionals doCheck (testSystemDepends ++ testFrameworkDepends) 477 ++ optionals doBenchmark (benchmarkSystemDepends ++ benchmarkFrameworkDepends); 478 # TODO next rebuild just define as `otherBuildInputsHaskell ++ otherBuildInputsSystem` 479 otherBuildInputs = 480 extraLibraries 481 ++ librarySystemDepends 482 ++ executableSystemDepends 483 ++ executableFrameworkDepends 484 ++ allPkgconfigDepends 485 ++ optionals doCheck ( 486 testDepends ++ testHaskellDepends ++ testSystemDepends ++ testFrameworkDepends 487 ) 488 ++ optionals doBenchmark ( 489 benchmarkDepends ++ benchmarkHaskellDepends ++ benchmarkSystemDepends ++ benchmarkFrameworkDepends 490 ); 491 492 setupCommand = "./Setup"; 493 494 ghcCommand' = if isGhcjs then "ghcjs" else "ghc"; 495 ghcCommand = "${ghc.targetPrefix}${ghcCommand'}"; 496 497 ghcNameWithPrefix = "${ghc.targetPrefix}${ghc.haskellCompilerName}"; 498 mkGhcLibdir = 499 ghc: 500 "lib/${ghc.targetPrefix}${ghc.haskellCompilerName}" + lib.optionalString (ghc ? hadrian) "/lib"; 501 ghcLibdir = mkGhcLibdir ghc; 502 503 nativeGhcCommand = "${nativeGhc.targetPrefix}ghc"; 504 505 buildPkgDb = thisGhc: packageConfDir: '' 506 # If this dependency has a package database, then copy the contents of it, 507 # unless it is one of our GHCs. These can appear in our dependencies when 508 # we are doing native builds, and they have package databases in them, but 509 # we do not want to copy them over. 510 # 511 # We don't need to, since those packages will be provided by the GHC when 512 # we compile with it, and doing so can result in having multiple copies of 513 # e.g. Cabal in the database with the same name and version, which is 514 # ambiguous. 515 if [ -d "$p/${mkGhcLibdir thisGhc}/package.conf.d" ] && [ "$p" != "${ghc}" ] && [ "$p" != "${nativeGhc}" ]; then 516 cp -f "$p/${mkGhcLibdir thisGhc}/package.conf.d/"*.conf ${packageConfDir}/ 517 continue 518 fi 519 ''; 520 521 intermediatesDir = "share/haskell/${ghc.version}/${pname}-${version}/dist"; 522 523 # On old ghcjs, the jsexe directories are the output but on the js backend they seem to be treated as intermediates 524 jsexe = rec { 525 shouldUseNode = isGhcjs; 526 shouldAdd = stdenv.hostPlatform.isGhcjs && isExecutable; 527 shouldCopy = shouldAdd && !doInstallIntermediates; 528 shouldSymlink = shouldAdd && doInstallIntermediates; 529 }; 530 531 # This is a script suitable for --test-wrapper of Setup.hs' test command 532 # (https://cabal.readthedocs.io/en/3.12/setup-commands.html#cmdoption-runhaskell-Setup.hs-test-test-wrapper). 533 # We use it to set some environment variables that the test suite may need, 534 # e.g. GHC_PACKAGE_PATH to invoke GHC(i) at runtime with build dependencies 535 # available. See the comment accompanying checkPhase below on how to customize 536 # this behavior. We need to use a wrapper script since Cabal forbids setting 537 # certain environment variables since they can alter GHC's behavior (e.g. 538 # GHC_PACKAGE_PATH) and cause failures. While building, Cabal will set 539 # GHC_ENVIRONMENT to make the packages picked at configure time available to 540 # GHC, but unfortunately not at test time. The test wrapper script will be 541 # executed after such environment checks, so we can take some liberties which 542 # is unproblematic since we know our synthetic package db matches what Cabal 543 # will see at configure time exactly. See also 544 # <https://github.com/haskell/cabal/issues/7792>. 545 testWrapperScript = buildPackages.writeShellScript "haskell-generic-builder-test-wrapper.sh" '' 546 set -eu 547 548 # We expect this to be either empty or set by checkPhase 549 if [[ -n "''${NIX_GHC_PACKAGE_PATH_FOR_TEST}" ]]; then 550 export GHC_PACKAGE_PATH="''${NIX_GHC_PACKAGE_PATH_FOR_TEST}" 551 fi 552 553 exec "$@" 554 ''; 555 556 testTargetsString = 557 lib.warnIf (testTarget != "") 558 "haskellPackages.mkDerivation: testTarget is deprecated. Use testTargets instead" 559 (lib.concatStringsSep " " testTargets); 560 561 env' = { 562 LANG = "en_US.UTF-8"; # GHC needs the locale configured during the Haddock phase. 563 } 564 // env 565 # Implicit pointer to integer conversions are errors by default since clang 15. 566 # Works around https://gitlab.haskell.org/ghc/ghc/-/issues/23456. 567 // optionalAttrs (stdenv.hasCC && stdenv.cc.isClang) { 568 NIX_CFLAGS_COMPILE = 569 "-Wno-error=int-conversion" 570 + lib.optionalString (env ? NIX_CFLAGS_COMPILE) (" " + env.NIX_CFLAGS_COMPILE); 571 }; 572 573in 574lib.fix ( 575 drv: 576 577 stdenv.mkDerivation ( 578 { 579 inherit pname version; 580 581 outputs = [ 582 "out" 583 ] 584 ++ (optional enableSeparateDataOutput "data") 585 ++ (optional enableSeparateDocOutput "doc") 586 ++ (optional enableSeparateBinOutput "bin") 587 ++ (optional enableSeparateIntermediatesOutput "intermediates"); 588 589 setOutputFlags = false; 590 591 pos = builtins.unsafeGetAttrPos "pname" args; 592 593 prePhases = [ "setupCompilerEnvironmentPhase" ]; 594 preConfigurePhases = [ "compileBuildDriverPhase" ]; 595 preInstallPhases = [ "haddockPhase" ]; 596 597 inherit src; 598 599 inherit depsBuildBuild nativeBuildInputs; 600 buildInputs = 601 otherBuildInputs 602 ++ optionals (!isLibrary) propagatedBuildInputs 603 # For patchShebangsAuto in fixupPhase 604 ++ optionals stdenv.hostPlatform.isGhcjs [ nodejs ]; 605 propagatedBuildInputs = optionals isLibrary propagatedBuildInputs; 606 607 env = 608 optionalAttrs (stdenv.buildPlatform.libc == "glibc") { 609 LOCALE_ARCHIVE = "${glibcLocales}/lib/locale/locale-archive"; 610 } 611 // env'; 612 613 prePatch = 614 optionalString (editedCabalFile != null) '' 615 echo "Replace Cabal file with edited version from ${newCabalFileUrl}." 616 cp ${newCabalFile} ${pname}.cabal 617 '' 618 + prePatch; 619 620 postPatch = 621 optionalString jailbreak '' 622 echo "Run jailbreak-cabal to lift version restrictions on build inputs." 623 ${jailbreak-cabal}/bin/jailbreak-cabal ${pname}.cabal 624 '' 625 + postPatch; 626 627 setupCompilerEnvironmentPhase = '' 628 NIX_BUILD_CORES=$(( NIX_BUILD_CORES < ${toString maxBuildCores} ? NIX_BUILD_CORES : ${toString maxBuildCores} )) 629 runHook preSetupCompilerEnvironment 630 631 echo "Build with ${ghc}." 632 ${optionalString (isLibrary && hyperlinkSource) "export PATH=${hscolour}/bin:$PATH"} 633 634 builddir="$(mktemp -d)" 635 setupPackageConfDir="$builddir/setup-package.conf.d" 636 mkdir -p $setupPackageConfDir 637 packageConfDir="$builddir/package.conf.d" 638 mkdir -p $packageConfDir 639 640 setupCompileFlags="${concatStringsSep " " setupCompileFlags}" 641 configureFlags="${concatStringsSep " " defaultConfigureFlags} $configureFlags" 642 '' 643 # We build the Setup.hs on the *build* machine, and as such should only add 644 # dependencies for the build machine. 645 # 646 # pkgs* arrays defined in stdenv/setup.hs 647 + '' 648 for p in "''${pkgsBuildBuild[@]}" "''${pkgsBuildHost[@]}" "''${pkgsBuildTarget[@]}"; do 649 ${buildPkgDb nativeGhc "$setupPackageConfDir"} 650 done 651 ${nativeGhcCommand}-pkg --package-db="$setupPackageConfDir" recache 652 '' 653 # For normal components 654 + '' 655 for p in "''${pkgsHostHost[@]}" "''${pkgsHostTarget[@]}"; do 656 ${buildPkgDb ghc "$packageConfDir"} 657 if [ -d "$p/include" ]; then 658 appendToVar configureFlags "--extra-include-dirs=$p/include" 659 fi 660 if [ -d "$p/lib" ]; then 661 appendToVar configureFlags "--extra-lib-dirs=$p/lib" 662 fi 663 if [[ -d "$p/Library/Frameworks" ]]; then 664 appendToVar configureFlags "--extra-framework-dirs=$p/Library/Frameworks" 665 fi 666 '' 667 + '' 668 done 669 '' 670 + (optionalString stdenv.hostPlatform.isGhcjs '' 671 export EM_CACHE="$(realpath "$(mktemp -d emcache.XXXXXXXXXX)")" 672 cp -Lr ${emscripten}/share/emscripten/cache/* "$EM_CACHE/" 673 chmod u+rwX -R "$EM_CACHE" 674 '') 675 # only use the links hack if we're actually building dylibs. otherwise, the 676 # "dynamic-library-dirs" point to nonexistent paths, and the ln command becomes 677 # "ln -s $out/lib/links", which tries to recreate the links dir and fails 678 # 679 # Note: We need to disable this work-around when using intermediate build 680 # products from a prior build because otherwise Nix will change permissions on 681 # the `$out/lib/links` directory to read-only when the build is done after the 682 # dist directory has already been exported, which triggers an unnecessary 683 # rebuild of modules included in the exported dist directory. 684 + (optionalString 685 ( 686 stdenv.hostPlatform.isDarwin 687 && (enableSharedLibraries || enableSharedExecutables) 688 && !enableSeparateIntermediatesOutput 689 ) 690 '' 691 # Work around a limit in the macOS Sierra linker on the number of paths 692 # referenced by any one dynamic library: 693 # 694 # Create a local directory with symlinks of the *.dylib (macOS shared 695 # libraries) from all the dependencies. 696 local dynamicLinksDir="$out/lib/links" 697 mkdir -p $dynamicLinksDir 698 699 # Unprettify all package conf files before reading/writing them 700 for d in "$packageConfDir/"*; do 701 # gawk -i inplace seems to strip the last newline 702 gawk -f ${unprettyConf} "$d" > tmp 703 mv tmp "$d" 704 done 705 706 for d in $(grep '^dynamic-library-dirs:' "$packageConfDir"/* | cut -d' ' -f2- | tr ' ' '\n' | sort -u); do 707 for lib in "$d/"*.{dylib,so}; do 708 # Allow overwriting because C libs can be pulled in multiple times. 709 ln -sf "$lib" "$dynamicLinksDir" 710 done 711 done 712 # Edit the local package DB to reference the links directory. 713 for f in "$packageConfDir/"*.conf; do 714 sed -i "s,dynamic-library-dirs: .*,dynamic-library-dirs: $dynamicLinksDir," "$f" 715 done 716 '' 717 ) 718 + '' 719 ${ghcCommand}-pkg --package-db="$packageConfDir" recache 720 721 runHook postSetupCompilerEnvironment 722 ''; 723 724 compileBuildDriverPhase = '' 725 runHook preCompileBuildDriver 726 727 for i in Setup.hs Setup.lhs ${defaultSetupHs}; do 728 test -f $i && break 729 done 730 731 echo setupCompileFlags: $setupCompileFlags 732 ${nativeGhcCommand} $setupCompileFlags --make -o Setup -odir $builddir -hidir $builddir $i 733 734 runHook postCompileBuildDriver 735 ''; 736 737 # Cabal takes flags like `--configure-option=--host=...` instead 738 configurePlatforms = [ ]; 739 inherit configureFlags; 740 741 # Note: the options here must be always added, regardless of whether the 742 # package specifies `hardeningDisable`. 743 hardeningDisable = 744 lib.optionals (args ? hardeningDisable) hardeningDisable 745 ++ lib.optional (ghc.isHaLVM or false) "all" 746 # Static libraries (ie. all of pkgsStatic.haskellPackages) fail to build 747 # because by default Nix adds `-pie` to the linker flags: this 748 # conflicts with the `-r` and `-no-pie` flags added by GHC (see 749 # https://gitlab.haskell.org/ghc/ghc/-/issues/19580). hardeningDisable 750 # changes the default Nix behavior regarding adding "hardening" flags. 751 ++ lib.optional enableStaticLibraries "pie"; 752 753 configurePhase = '' 754 runHook preConfigure 755 756 echo configureFlags: $configureFlags 757 ${setupCommand} configure $configureFlags 2>&1 | ${coreutils}/bin/tee "$NIX_BUILD_TOP/cabal-configure.log" 758 ${lib.optionalString (!allowInconsistentDependencies) '' 759 if grep -E -q -z 'Warning:.*depends on multiple versions' "$NIX_BUILD_TOP/cabal-configure.log"; then 760 echo >&2 "*** abort because of serious configure-time warning from Cabal" 761 exit 1 762 fi 763 ''} 764 765 runHook postConfigure 766 ''; 767 768 buildPhase = '' 769 runHook preBuild 770 '' 771 + lib.optionalString (previousIntermediates != null) '' 772 mkdir -p dist; 773 rm -r dist/build 774 cp -r ${previousIntermediates}/${intermediatesDir}/build dist/build 775 find dist/build -exec chmod u+w {} + 776 find dist/build -exec touch -d '1970-01-01T00:00:00Z' {} + 777 '' 778 + '' 779 ${setupCommand} build ${buildTarget}${buildFlagsString} 780 runHook postBuild 781 ''; 782 783 inherit doCheck; 784 785 # Run test suite(s) and pass `checkFlags` as well as `checkFlagsArray`. 786 # `testFlags` are added to `checkFlagsArray` each prefixed with 787 # `--test-option`, so Cabal passes it to the underlying test suite binary. 788 # 789 # We also take care of setting GHC_PACKAGE_PATH during test suite execution, 790 # so it can run GHC(i) with build dependencies available: 791 # - If NIX_GHC_PACKAGE_PATH_FOR_TEST is set, it become the value of GHC_PACKAGE_PATH 792 # while the test suite is executed. 793 # - If it is empty, it'll be unset during test suite execution. 794 # - Otherwise GHC_PACKAGE_PATH will have the package db used for configuring 795 # plus GHC's core packages. 796 checkPhase = '' 797 runHook preCheck 798 checkFlagsArray+=( 799 "--show-details=streaming" 800 "--test-wrapper=${testWrapperScript}" 801 ${lib.escapeShellArgs (builtins.map (opt: "--test-option=${opt}") testFlags)} 802 ) 803 export NIX_GHC_PACKAGE_PATH_FOR_TEST="''${NIX_GHC_PACKAGE_PATH_FOR_TEST:-$packageConfDir:}" 804 ${setupCommand} test ${testTargetsString} $checkFlags ''${checkFlagsArray:+"''${checkFlagsArray[@]}"} 805 runHook postCheck 806 ''; 807 808 haddockPhase = '' 809 runHook preHaddock 810 ${optionalString (doHaddock && isLibrary) '' 811 ${setupCommand} haddock --html \ 812 ${optionalString doHoogle "--hoogle"} \ 813 ${optionalString doHaddockQuickjump "--quickjump"} \ 814 ${optionalString (isLibrary && hyperlinkSource) "--hyperlink-source"} \ 815 ${lib.concatStringsSep " " haddockFlags} 816 ''} 817 runHook postHaddock 818 ''; 819 820 installPhase = '' 821 runHook preInstall 822 823 ${ 824 if !isLibrary && buildTarget == "" then 825 "${setupCommand} install" 826 # ^^ if the project is not a library, and no build target is specified, we can just use "install". 827 else if !isLibrary then 828 "${setupCommand} copy ${buildTarget}" 829 # ^^ if the project is not a library, and we have a build target, then use "copy" to install 830 # just the target specified; "install" will error here, since not all targets have been built. 831 else 832 '' 833 ${setupCommand} copy ${buildTarget} 834 local packageConfDir="$out/${ghcLibdir}/package.conf.d" 835 local packageConfFile="$packageConfDir/${pname}-${version}.conf" 836 mkdir -p "$packageConfDir" 837 ${setupCommand} register --gen-pkg-config=$packageConfFile 838 if [ -d "$packageConfFile" ]; then 839 mv "$packageConfFile/"* "$packageConfDir" 840 rmdir "$packageConfFile" 841 fi 842 for packageConfFile in "$packageConfDir/"*; do 843 local pkgId=$(gawk -f ${unprettyConf} "$packageConfFile" \ 844 | grep '^id:' | cut -d' ' -f2) 845 mv "$packageConfFile" "$packageConfDir/$pkgId.conf" 846 done 847 848 # delete confdir if there are no libraries 849 find $packageConfDir -maxdepth 0 -empty -delete; 850 '' 851 } 852 853 ${optionalString jsexe.shouldUseNode '' 854 for exeDir in "${binDir}/"*.jsexe; do 855 exe="''${exeDir%.jsexe}" 856 printWords '#!${nodejs}/bin/node' > "$exe" 857 echo >> "$exe" 858 cat "$exeDir/all.js" >> "$exe" 859 chmod +x "$exe" 860 done 861 ''} 862 ${optionalString doCoverage "mkdir -p $out/share && cp -r dist/hpc $out/share"} 863 864 ${optionalString jsexe.shouldCopy '' 865 for jsexeDir in dist/build/*/*.jsexe; do 866 bn=$(basename $jsexeDir) 867 exe="''${bn%.jsexe}" 868 cp -r dist/build/$exe/$exe.jsexe ${binDir} 869 done 870 ''} 871 872 ${optionalString enableSeparateDocOutput '' 873 for x in ${docdir "$doc"}"/html/src/"*.html; do 874 remove-references-to -t $out $x 875 done 876 mkdir -p $doc 877 ''} 878 ${optionalString enableSeparateDataOutput "mkdir -p $data"} 879 880 runHook postInstall 881 ''; 882 883 ${if doInstallIntermediates then "installIntermediatesPhase" else null} = '' 884 runHook preInstallIntermediates 885 intermediatesOutput=${if enableSeparateIntermediatesOutput then "$intermediates" else "$out"} 886 installIntermediatesDir="$intermediatesOutput/${intermediatesDir}" 887 mkdir -p "$installIntermediatesDir" 888 cp -r dist/build "$installIntermediatesDir" 889 runHook postInstallIntermediates 890 891 ${optionalString jsexe.shouldSymlink '' 892 for jsexeDir in $installIntermediatesDir/build/*/*.jsexe; do 893 bn=$(basename $jsexeDir) 894 exe="''${bn%.jsexe}" 895 (cd ${binDir} && ln -s $installIntermediatesDir/build/$exe/$exe.jsexe) 896 done 897 ''} 898 ''; 899 900 passthru = passthru // rec { 901 902 inherit pname version disallowGhcReference; 903 904 compiler = ghc; 905 906 # All this information is intended just for `shellFor`. It should be 907 # considered unstable and indeed we knew how to keep it private we would. 908 getCabalDeps = { 909 inherit 910 buildDepends 911 buildTools 912 executableFrameworkDepends 913 executableHaskellDepends 914 executablePkgconfigDepends 915 executableSystemDepends 916 executableToolDepends 917 extraLibraries 918 libraryFrameworkDepends 919 libraryHaskellDepends 920 libraryPkgconfigDepends 921 librarySystemDepends 922 libraryToolDepends 923 pkg-configDepends 924 setupHaskellDepends 925 ; 926 } 927 // lib.optionalAttrs doCheck { 928 inherit 929 testDepends 930 testFrameworkDepends 931 testHaskellDepends 932 testPkgconfigDepends 933 testSystemDepends 934 testToolDepends 935 ; 936 } 937 // lib.optionalAttrs doBenchmark { 938 inherit 939 benchmarkDepends 940 benchmarkFrameworkDepends 941 benchmarkHaskellDepends 942 benchmarkPkgconfigDepends 943 benchmarkSystemDepends 944 benchmarkToolDepends 945 ; 946 }; 947 948 # Attributes for the old definition of `shellFor`. Should be removed but 949 # this predates the warning at the top of `getCabalDeps`. 950 getBuildInputs = rec { 951 inherit propagatedBuildInputs otherBuildInputs allPkgconfigDepends; 952 haskellBuildInputs = isHaskellPartition.right; 953 systemBuildInputs = isHaskellPartition.wrong; 954 isHaskellPartition = lib.partition isHaskellPkg ( 955 propagatedBuildInputs ++ otherBuildInputs ++ depsBuildBuild ++ nativeBuildInputs 956 ); 957 }; 958 959 isHaskellLibrary = isLibrary; 960 961 # TODO: ask why the split outputs are configurable at all? 962 # TODO: include tests for split if possible 963 # Given the haskell package, returns 964 # the directory containing the haddock documentation. 965 # `null' if no haddock documentation was built. 966 # TODO: fetch the self from the fixpoint instead 967 haddockDir = self: if doHaddock then "${docdir self.doc}/html" else null; 968 969 # Creates a derivation containing all of the necessary dependencies for building the 970 # parent derivation. The attribute set that it takes as input can be viewed as: 971 # 972 # { withHoogle } 973 # 974 # The derivation that it builds contains no outpaths because it is meant for use 975 # as an environment 976 # 977 # # Example use 978 # # Creates a shell with all of the dependencies required to build the "hello" package, 979 # # and with python: 980 # 981 # > nix-shell -E 'with (import <nixpkgs> {}); \ 982 # > haskell.packages.ghc865.hello.envFunc { buildInputs = [ python ]; }' 983 envFunc = 984 { 985 withHoogle ? false, 986 }: 987 let 988 name = "ghc-shell-for-${drv.name}"; 989 990 withPackages = if withHoogle then ghcWithHoogle else ghcWithPackages; 991 992 # We use the `ghcWithPackages` function from `buildHaskellPackages` if we 993 # want a shell for the sake of cross compiling a package. In the native case 994 # we don't use this at all, and instead put the setupDepends in the main 995 # `ghcWithPackages`. This way we don't have two wrapper scripts called `ghc` 996 # shadowing each other on the PATH. 997 ghcEnvForBuild = 998 assert isCross; 999 buildHaskellPackages.ghcWithPackages (_: setupHaskellDepends); 1000 1001 ghcEnv = withPackages ( 1002 _: otherBuildInputsHaskell ++ propagatedBuildInputs ++ lib.optionals (!isCross) setupHaskellDepends 1003 ); 1004 1005 ghcCommandCaps = lib.toUpper ghcCommand'; 1006 in 1007 runCommandCC name { 1008 inherit shellHook; 1009 1010 depsBuildBuild = lib.optional isCross ghcEnvForBuild; 1011 nativeBuildInputs = [ 1012 ghcEnv 1013 ] 1014 ++ optional (allPkgconfigDepends != [ ]) pkg-config 1015 ++ collectedToolDepends; 1016 buildInputs = otherBuildInputsSystem; 1017 1018 env = { 1019 "NIX_${ghcCommandCaps}" = "${ghcEnv}/bin/${ghcCommand}"; 1020 "NIX_${ghcCommandCaps}PKG" = "${ghcEnv}/bin/${ghcCommand}-pkg"; 1021 # TODO: is this still valid? 1022 "NIX_${ghcCommandCaps}_DOCDIR" = "${ghcEnv}/share/doc/ghc/html"; 1023 "NIX_${ghcCommandCaps}_LIBDIR" = 1024 if ghc.isHaLVM or false then "${ghcEnv}/lib/HaLVM-${ghc.version}" else "${ghcEnv}/${ghcLibdir}"; 1025 } 1026 // optionalAttrs (stdenv.buildPlatform.libc == "glibc") { 1027 # TODO: Why is this written in terms of `buildPackages`, unlike 1028 # the outer `env`? 1029 # 1030 # According to @sternenseemann [1]: 1031 # 1032 # > The condition is based on `buildPlatform`, so it needs to 1033 # > match. `LOCALE_ARCHIVE` is set to accompany `LANG` which 1034 # > concerns things we execute on the build platform like 1035 # > `haddock`. 1036 # > 1037 # > Arguably the outer non `buildPackages` one is incorrect and 1038 # > probably works by accident in most cases since the locale 1039 # > archive is not platform specific (the trouble is that it 1040 # > may sometimes be impossible to cross-compile). At least 1041 # > that would be my assumption. 1042 # 1043 # [1]: https://github.com/NixOS/nixpkgs/pull/424368#discussion_r2202683378 1044 LOCALE_ARCHIVE = "${buildPackages.glibcLocales}/lib/locale/locale-archive"; 1045 } 1046 // env'; 1047 } "echo $nativeBuildInputs $buildInputs > $out"; 1048 1049 # Specialise the devShell attribute, so we get our improved shell. 1050 devShell = env.devShell; 1051 env = envFunc { }; 1052 1053 }; 1054 1055 meta = { 1056 inherit homepage license platforms; 1057 } 1058 // optionalAttrs (args ? broken) { inherit broken; } 1059 // optionalAttrs (args ? description) { inherit description; } 1060 // optionalAttrs (args ? maintainers) { inherit maintainers; } 1061 // optionalAttrs (args ? teams) { inherit teams; } 1062 // optionalAttrs (args ? hydraPlatforms) { inherit hydraPlatforms; } 1063 // optionalAttrs (args ? badPlatforms) { inherit badPlatforms; } 1064 // optionalAttrs (args ? changelog) { inherit changelog; } 1065 // optionalAttrs (args ? mainProgram) { inherit mainProgram; }; 1066 1067 } 1068 // optionalAttrs (args ? sourceRoot) { inherit sourceRoot; } 1069 // optionalAttrs (args ? setSourceRoot) { inherit setSourceRoot; } 1070 // optionalAttrs (args ? preCompileBuildDriver) { inherit preCompileBuildDriver; } 1071 // optionalAttrs (args ? postCompileBuildDriver) { inherit postCompileBuildDriver; } 1072 // optionalAttrs (args ? preUnpack) { inherit preUnpack; } 1073 // optionalAttrs (args ? postUnpack) { inherit postUnpack; } 1074 // optionalAttrs (args ? patches) { inherit patches; } 1075 // optionalAttrs (args ? patchPhase) { inherit patchPhase; } 1076 // optionalAttrs (args ? preConfigure) { inherit preConfigure; } 1077 // optionalAttrs (args ? postConfigure) { inherit postConfigure; } 1078 // optionalAttrs (args ? preBuild) { inherit preBuild; } 1079 // optionalAttrs (args ? postBuild) { inherit postBuild; } 1080 // optionalAttrs (args ? doBenchmark) { inherit doBenchmark; } 1081 // optionalAttrs (args ? checkPhase) { inherit checkPhase; } 1082 // optionalAttrs (args ? preCheck) { inherit preCheck; } 1083 // optionalAttrs (args ? postCheck) { inherit postCheck; } 1084 // optionalAttrs (args ? preHaddock) { inherit preHaddock; } 1085 // optionalAttrs (args ? postHaddock) { inherit postHaddock; } 1086 // optionalAttrs (args ? preInstall) { inherit preInstall; } 1087 // optionalAttrs (args ? installPhase) { inherit installPhase; } 1088 // optionalAttrs (args ? postInstall) { inherit postInstall; } 1089 // optionalAttrs (args ? preFixup) { inherit preFixup; } 1090 // optionalAttrs (args ? postFixup) { inherit postFixup; } 1091 // optionalAttrs (args ? dontStrip) { inherit dontStrip; } 1092 // optionalAttrs (postPhases != [ ]) { inherit postPhases; } 1093 // optionalAttrs (disallowedRequisites != [ ] || disallowGhcReference) { 1094 disallowedRequisites = disallowedRequisites ++ (if disallowGhcReference then [ ghc ] else [ ]); 1095 } 1096 ) 1097)