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