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