Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1{ lib, stdenv, buildPackages, buildHaskellPackages, ghc 2, jailbreak-cabal, hscolour, cpphs, nodejs 3, ghcWithHoogle, ghcWithPackages 4}: 5 6let 7 isCross = stdenv.buildPlatform != stdenv.hostPlatform; 8 inherit (buildPackages) 9 fetchurl removeReferencesTo 10 pkg-config coreutils gnugrep gnused glibcLocales; 11in 12 13{ pname 14# Note that ghc.isGhcjs != stdenv.hostPlatform.isGhcjs. 15# ghc.isGhcjs implies that we are using ghcjs, a project separate from GHC. 16# (mere) stdenv.hostPlatform.isGhcjs means that we are using GHC's JavaScript 17# backend. The latter is a normal cross compilation backend and needs little 18# special accommodation. 19, dontStrip ? (ghc.isGhcjs or false || stdenv.hostPlatform.isGhcjs) 20, version, revision ? null 21, sha256 ? null 22, src ? fetchurl { url = "mirror://hackage/${pname}-${version}.tar.gz"; inherit sha256; } 23, buildDepends ? [], setupHaskellDepends ? [], libraryHaskellDepends ? [], executableHaskellDepends ? [] 24, buildTarget ? "" 25, buildTools ? [], libraryToolDepends ? [], executableToolDepends ? [], testToolDepends ? [], benchmarkToolDepends ? [] 26, configureFlags ? [] 27, buildFlags ? [] 28, haddockFlags ? [] 29, description ? null 30, doCheck ? !isCross && lib.versionOlder "7.4" ghc.version 31, doBenchmark ? false 32, doHoogle ? true 33, doHaddockQuickjump ? doHoogle && lib.versionAtLeast ghc.version "8.6" 34, doInstallIntermediates ? false 35, editedCabalFile ? null 36# aarch64 outputs otherwise exceed 2GB limit 37, enableLibraryProfiling ? !(ghc.isGhcjs or stdenv.targetPlatform.isAarch64 or false) 38, enableExecutableProfiling ? false 39, profilingDetail ? "exported-functions" 40# TODO enable shared libs for cross-compiling 41, enableSharedExecutables ? false 42, enableSharedLibraries ? !stdenv.hostPlatform.isStatic && (ghc.enableShared or false) 43, enableDeadCodeElimination ? (!stdenv.isDarwin) # TODO: use -dead_strip for darwin 44, enableStaticLibraries ? !(stdenv.hostPlatform.isWindows or stdenv.hostPlatform.isWasm) 45, enableHsc2hsViaAsm ? stdenv.hostPlatform.isWindows && lib.versionAtLeast ghc.version "8.4" 46, extraLibraries ? [], librarySystemDepends ? [], executableSystemDepends ? [] 47# On macOS, statically linking against system frameworks is not supported; 48# see https://developer.apple.com/library/content/qa/qa1118/_index.html 49# They must be propagated to the environment of any executable linking with the library 50, libraryFrameworkDepends ? [], executableFrameworkDepends ? [] 51, homepage ? "https://hackage.haskell.org/package/${pname}" 52, platforms ? with lib.platforms; all # GHC can cross-compile 53, badPlatforms ? lib.platforms.none 54, hydraPlatforms ? null 55, hyperlinkSource ? true 56, isExecutable ? false, isLibrary ? !isExecutable 57, jailbreak ? false 58, license 59, enableParallelBuilding ? true 60, maintainers ? null 61, changelog ? null 62, mainProgram ? null 63, doCoverage ? false 64, doHaddock ? !(ghc.isHaLVM or false) && (ghc.hasHaddock or true) 65, doHaddockInterfaces ? doHaddock && lib.versionAtLeast ghc.version "9.0.1" 66, passthru ? {} 67, pkg-configDepends ? [], libraryPkgconfigDepends ? [], executablePkgconfigDepends ? [], testPkgconfigDepends ? [], benchmarkPkgconfigDepends ? [] 68, testDepends ? [], testHaskellDepends ? [], testSystemDepends ? [], testFrameworkDepends ? [] 69, benchmarkDepends ? [], benchmarkHaskellDepends ? [], benchmarkSystemDepends ? [], benchmarkFrameworkDepends ? [] 70, testTarget ? "", testFlags ? [] 71, broken ? false 72, preCompileBuildDriver ? null, postCompileBuildDriver ? null 73, preUnpack ? null, postUnpack ? null 74, patches ? null, patchPhase ? null, prePatch ? "", postPatch ? "" 75, preConfigure ? null, postConfigure ? null 76, preBuild ? null, postBuild ? null 77, preHaddock ? null, postHaddock ? null 78, installPhase ? null, preInstall ? null, postInstall ? null 79, checkPhase ? null, preCheck ? null, postCheck ? null 80, preFixup ? null, postFixup ? null 81, shellHook ? "" 82, coreSetup ? false # Use only core packages to build Setup.hs. 83, useCpphs ? false 84, hardeningDisable ? null 85, enableSeparateBinOutput ? false 86, enableSeparateDataOutput ? false 87, enableSeparateDocOutput ? doHaddock 88, enableSeparateIntermediatesOutput ? false 89, # Don't fail at configure time if there are multiple versions of the 90 # same package in the (recursive) dependencies of the package being 91 # built. Will delay failures, if any, to compile time. 92 allowInconsistentDependencies ? false 93, maxBuildCores ? 16 # more cores usually don't improve performance: https://ghc.haskell.org/trac/ghc/ticket/9221 94, # If set to true, this builds a pre-linked .o file for this Haskell library. 95 # This can make it slightly faster to load this library into GHCi, but takes 96 # extra disk space and compile time. 97 enableLibraryForGhci ? false 98 # Set this to a previous build of this same package to reuse the intermediate 99 # build products from that prior build as a starting point for accelerating 100 # this build 101, previousIntermediates ? null 102} @ args: 103 104assert editedCabalFile != null -> revision != null; 105 106# --enable-static does not work on windows. This is a bug in GHC. 107# --enable-static will pass -staticlib to ghc, which only works for mach-o and elf. 108assert stdenv.hostPlatform.isWindows -> enableStaticLibraries == false; 109assert stdenv.hostPlatform.isWasm -> enableStaticLibraries == false; 110 111let 112 113 inherit (lib) optional optionals optionalString versionOlder versionAtLeast 114 concatStringsSep enableFeature optionalAttrs; 115 116 isGhcjs = ghc.isGhcjs or false; 117 isHaLVM = ghc.isHaLVM or false; 118 packageDbFlag = if isGhcjs || isHaLVM || versionOlder "7.6" ghc.version 119 then "package-db" 120 else "package-conf"; 121 122 # GHC used for building Setup.hs 123 # 124 # Same as our GHC, unless we're cross, in which case it is native GHC with the 125 # same version, or ghcjs, in which case its the ghc used to build ghcjs. 126 nativeGhc = buildHaskellPackages.ghc; 127 nativePackageDbFlag = if versionOlder "7.6" nativeGhc.version 128 then "package-db" 129 else "package-conf"; 130 131 # the target dir for haddock documentation 132 docdir = docoutput: docoutput + "/share/doc/" + pname + "-" + version; 133 134 binDir = if enableSeparateBinOutput then "$bin/bin" else "$out/bin"; 135 136 newCabalFileUrl = "mirror://hackage/${pname}-${version}/revision/${revision}.cabal"; 137 newCabalFile = fetchurl { 138 url = newCabalFileUrl; 139 sha256 = editedCabalFile; 140 name = "${pname}-${version}-r${revision}.cabal"; 141 }; 142 143 defaultSetupHs = builtins.toFile "Setup.hs" '' 144 import Distribution.Simple 145 main = defaultMain 146 ''; 147 148 # This awk expression transforms a package conf file like 149 # 150 # author: John Doe <john-doe@example.com> 151 # description: 152 # The purpose of this library is to do 153 # foo and bar among other things 154 # 155 # into a more easily processeable form: 156 # 157 # author: John Doe <john-doe@example.com> 158 # description: The purpose of this library is to do foo and bar among other things 159 unprettyConf = builtins.toFile "unpretty-cabal-conf.awk" '' 160 /^[^ ]+:/ { 161 # When the line starts with a new field, terminate the previous one with a newline 162 if (started == 1) print "" 163 # to strip leading spaces 164 $1=$1 165 printf "%s", $0 166 started=1 167 } 168 169 /^ +/ { 170 # to strip leading spaces 171 $1=$1 172 printf " %s", $0 173 } 174 175 # Terminate the final field with a newline 176 END { print "" } 177 ''; 178 179 crossCabalFlags = [ 180 "--with-ghc=${ghcCommand}" 181 "--with-ghc-pkg=${ghc.targetPrefix}ghc-pkg" 182 # Pass the "wrong" C compiler rather than none at all so packages that just 183 # use the C preproccessor still work, see 184 # https://github.com/haskell/cabal/issues/6466 for details. 185 "--with-gcc=${if stdenv.hasCC then "$CC" else "$CC_FOR_BUILD"}" 186 ] ++ optionals stdenv.hasCC [ 187 "--with-ld=${stdenv.cc.bintools.targetPrefix}ld" 188 "--with-ar=${stdenv.cc.bintools.targetPrefix}ar" 189 # use the one that comes with the cross compiler. 190 "--with-hsc2hs=${ghc.targetPrefix}hsc2hs" 191 "--with-strip=${stdenv.cc.bintools.targetPrefix}strip" 192 ] ++ optionals (!isHaLVM) [ 193 "--hsc2hs-option=--cross-compile" 194 (optionalString enableHsc2hsViaAsm "--hsc2hs-option=--via-asm") 195 ] ++ optional (allPkgconfigDepends != []) 196 "--with-pkg-config=${pkg-config.targetPrefix}pkg-config"; 197 198 parallelBuildingFlags = "-j$NIX_BUILD_CORES" + optionalString stdenv.isLinux " +RTS -A64M -RTS"; 199 200 crossCabalFlagsString = 201 lib.optionalString isCross (" " + lib.concatStringsSep " " crossCabalFlags); 202 203 buildFlagsString = optionalString (buildFlags != []) (" " + concatStringsSep " " buildFlags); 204 205 defaultConfigureFlags = [ 206 "--verbose" 207 "--prefix=$out" 208 # Note: This must be kept in sync manually with mkGhcLibdir 209 ("--libdir=\\$prefix/lib/\\$compiler" + lib.optionalString (ghc ? hadrian) "/lib") 210 "--libsubdir=\\$abi/\\$libname" 211 (optionalString enableSeparateDataOutput "--datadir=$data/share/${ghcNameWithPrefix}") 212 (optionalString enableSeparateDocOutput "--docdir=${docdir "$doc"}") 213 ] ++ optionals stdenv.hasCC [ 214 "--with-gcc=$CC" # Clang won't work without that extra information. 215 ] ++ [ 216 "--package-db=$packageConfDir" 217 (optionalString (enableSharedExecutables && stdenv.isLinux) "--ghc-option=-optl=-Wl,-rpath=$out/${ghcLibdir}/${pname}-${version}") 218 (optionalString (enableSharedExecutables && stdenv.isDarwin) "--ghc-option=-optl=-Wl,-headerpad_max_install_names") 219 (optionalString enableParallelBuilding "--ghc-options=${parallelBuildingFlags}") 220 (optionalString useCpphs "--with-cpphs=${cpphs}/bin/cpphs --ghc-options=-cpp --ghc-options=-pgmP${cpphs}/bin/cpphs --ghc-options=-optP--cpp") 221 (enableFeature (enableDeadCodeElimination && !stdenv.hostPlatform.isAarch32 && !stdenv.hostPlatform.isAarch64 && (versionAtLeast "8.0.1" ghc.version)) "split-objs") 222 (enableFeature enableLibraryProfiling "library-profiling") 223 (optionalString ((enableExecutableProfiling || enableLibraryProfiling) && versionOlder "8" ghc.version) "--profiling-detail=${profilingDetail}") 224 (enableFeature enableExecutableProfiling (if versionOlder ghc.version "8" then "executable-profiling" else "profiling")) 225 (enableFeature enableSharedLibraries "shared") 226 (optionalString (versionAtLeast ghc.version "7.10") (enableFeature doCoverage "coverage")) 227 (optionalString (versionOlder "8.4" ghc.version) (enableFeature enableStaticLibraries "static")) 228 (optionalString (isGhcjs || versionOlder "7.4" ghc.version) (enableFeature enableSharedExecutables "executable-dynamic")) 229 (optionalString (isGhcjs || versionOlder "7" ghc.version) (enableFeature doCheck "tests")) 230 (enableFeature doBenchmark "benchmarks") 231 "--enable-library-vanilla" # TODO: Should this be configurable? 232 (enableFeature enableLibraryForGhci "library-for-ghci") 233 ] ++ optionals (enableDeadCodeElimination && (lib.versionOlder "8.0.1" ghc.version)) [ 234 "--ghc-option=-split-sections" 235 ] ++ optionals dontStrip [ 236 "--disable-library-stripping" 237 "--disable-executable-stripping" 238 ] ++ optionals isGhcjs [ 239 "--ghcjs" 240 ] ++ optionals isCross ([ 241 "--configure-option=--host=${stdenv.hostPlatform.config}" 242 ] ++ crossCabalFlags 243 ) ++ optionals enableSeparateBinOutput [ 244 "--bindir=${binDir}" 245 ] ++ optionals (doHaddockInterfaces && isLibrary) [ 246 "--ghc-options=-haddock" 247 ]; 248 249 postPhases = optional doInstallIntermediates [ "installIntermediatesPhase" ]; 250 251 setupCompileFlags = [ 252 (optionalString (!coreSetup) "-${nativePackageDbFlag}=$setupPackageConfDir") 253 (optionalString enableParallelBuilding (parallelBuildingFlags)) 254 "-threaded" # https://github.com/haskell/cabal/issues/2398 255 "-rtsopts" # allow us to pass RTS flags to the generated Setup executable 256 ]; 257 258 isHaskellPkg = x: x ? isHaskellLibrary; 259 260 allPkgconfigDepends = pkg-configDepends ++ libraryPkgconfigDepends ++ executablePkgconfigDepends ++ 261 optionals doCheck testPkgconfigDepends ++ optionals doBenchmark benchmarkPkgconfigDepends; 262 263 depsBuildBuild = [ nativeGhc ] 264 # CC_FOR_BUILD may be necessary if we have no C preprocessor for the host 265 # platform. See crossCabalFlags above for more details. 266 ++ lib.optionals (!stdenv.hasCC) [ buildPackages.stdenv.cc ]; 267 collectedToolDepends = 268 buildTools ++ libraryToolDepends ++ executableToolDepends ++ 269 optionals doCheck testToolDepends ++ 270 optionals doBenchmark benchmarkToolDepends; 271 nativeBuildInputs = 272 [ ghc removeReferencesTo ] ++ optional (allPkgconfigDepends != []) pkg-config ++ 273 setupHaskellDepends ++ collectedToolDepends; 274 propagatedBuildInputs = buildDepends ++ libraryHaskellDepends ++ executableHaskellDepends ++ libraryFrameworkDepends; 275 otherBuildInputsHaskell = 276 optionals doCheck (testDepends ++ testHaskellDepends) ++ 277 optionals doBenchmark (benchmarkDepends ++ benchmarkHaskellDepends); 278 otherBuildInputsSystem = 279 extraLibraries ++ librarySystemDepends ++ executableSystemDepends ++ executableFrameworkDepends ++ 280 allPkgconfigDepends ++ 281 optionals doCheck (testSystemDepends ++ testFrameworkDepends) ++ 282 optionals doBenchmark (benchmarkSystemDepends ++ benchmarkFrameworkDepends); 283 # TODO next rebuild just define as `otherBuildInputsHaskell ++ otherBuildInputsSystem` 284 otherBuildInputs = 285 extraLibraries ++ librarySystemDepends ++ executableSystemDepends ++ executableFrameworkDepends ++ 286 allPkgconfigDepends ++ 287 optionals doCheck (testDepends ++ testHaskellDepends ++ testSystemDepends ++ testFrameworkDepends) ++ 288 optionals doBenchmark (benchmarkDepends ++ benchmarkHaskellDepends ++ benchmarkSystemDepends ++ benchmarkFrameworkDepends); 289 290 setupCommand = "./Setup"; 291 292 ghcCommand' = if isGhcjs then "ghcjs" else "ghc"; 293 ghcCommand = "${ghc.targetPrefix}${ghcCommand'}"; 294 295 ghcNameWithPrefix = "${ghc.targetPrefix}${ghc.haskellCompilerName}"; 296 mkGhcLibdir = ghc: "lib/${ghc.targetPrefix}${ghc.haskellCompilerName}" 297 + lib.optionalString (ghc ? hadrian) "/lib"; 298 ghcLibdir = mkGhcLibdir ghc; 299 300 nativeGhcCommand = "${nativeGhc.targetPrefix}ghc"; 301 302 buildPkgDb = thisGhc: packageConfDir: '' 303 # If this dependency has a package database, then copy the contents of it, 304 # unless it is one of our GHCs. These can appear in our dependencies when 305 # we are doing native builds, and they have package databases in them, but 306 # we do not want to copy them over. 307 # 308 # We don't need to, since those packages will be provided by the GHC when 309 # we compile with it, and doing so can result in having multiple copies of 310 # e.g. Cabal in the database with the same name and version, which is 311 # ambiguous. 312 if [ -d "$p/${mkGhcLibdir thisGhc}/package.conf.d" ] && [ "$p" != "${ghc}" ] && [ "$p" != "${nativeGhc}" ]; then 313 cp -f "$p/${mkGhcLibdir thisGhc}/package.conf.d/"*.conf ${packageConfDir}/ 314 continue 315 fi 316 ''; 317 318 intermediatesDir = "share/haskell/${ghc.version}/${pname}-${version}/dist"; 319in lib.fix (drv: 320 321assert allPkgconfigDepends != [] -> pkg-config != null; 322 323stdenv.mkDerivation ({ 324 inherit pname version; 325 326 outputs = [ "out" ] 327 ++ (optional enableSeparateDataOutput "data") 328 ++ (optional enableSeparateDocOutput "doc") 329 ++ (optional enableSeparateBinOutput "bin") 330 ++ (optional enableSeparateIntermediatesOutput "intermediates"); 331 332 setOutputFlags = false; 333 334 pos = builtins.unsafeGetAttrPos "pname" args; 335 336 prePhases = ["setupCompilerEnvironmentPhase"]; 337 preConfigurePhases = ["compileBuildDriverPhase"]; 338 preInstallPhases = ["haddockPhase"]; 339 340 inherit src; 341 342 inherit depsBuildBuild nativeBuildInputs; 343 buildInputs = otherBuildInputs ++ optionals (!isLibrary) propagatedBuildInputs 344 # For patchShebangsAuto in fixupPhase 345 ++ optionals stdenv.hostPlatform.isGhcjs [ nodejs ]; 346 propagatedBuildInputs = optionals isLibrary propagatedBuildInputs; 347 348 LANG = "en_US.UTF-8"; # GHC needs the locale configured during the Haddock phase. 349 350 prePatch = optionalString (editedCabalFile != null) '' 351 echo "Replace Cabal file with edited version from ${newCabalFileUrl}." 352 cp ${newCabalFile} ${pname}.cabal 353 '' + prePatch; 354 355 postPatch = optionalString jailbreak '' 356 echo "Run jailbreak-cabal to lift version restrictions on build inputs." 357 ${jailbreak-cabal}/bin/jailbreak-cabal ${pname}.cabal 358 '' + postPatch; 359 360 setupCompilerEnvironmentPhase = '' 361 NIX_BUILD_CORES=$(( NIX_BUILD_CORES < ${toString maxBuildCores} ? NIX_BUILD_CORES : ${toString maxBuildCores} )) 362 runHook preSetupCompilerEnvironment 363 364 echo "Build with ${ghc}." 365 ${optionalString (isLibrary && hyperlinkSource) "export PATH=${hscolour}/bin:$PATH"} 366 367 builddir="$(mktemp -d)" 368 setupPackageConfDir="$builddir/setup-package.conf.d" 369 mkdir -p $setupPackageConfDir 370 packageConfDir="$builddir/package.conf.d" 371 mkdir -p $packageConfDir 372 373 setupCompileFlags="${concatStringsSep " " setupCompileFlags}" 374 configureFlags="${concatStringsSep " " defaultConfigureFlags} $configureFlags" 375 '' 376 # We build the Setup.hs on the *build* machine, and as such should only add 377 # dependencies for the build machine. 378 # 379 # pkgs* arrays defined in stdenv/setup.hs 380 + '' 381 for p in "''${pkgsBuildBuild[@]}" "''${pkgsBuildHost[@]}" "''${pkgsBuildTarget[@]}"; do 382 ${buildPkgDb nativeGhc "$setupPackageConfDir"} 383 done 384 ${nativeGhcCommand}-pkg --${nativePackageDbFlag}="$setupPackageConfDir" recache 385 '' 386 # For normal components 387 + '' 388 for p in "''${pkgsHostHost[@]}" "''${pkgsHostTarget[@]}"; do 389 ${buildPkgDb ghc "$packageConfDir"} 390 if [ -d "$p/include" ]; then 391 configureFlags+=" --extra-include-dirs=$p/include" 392 fi 393 if [ -d "$p/lib" ]; then 394 configureFlags+=" --extra-lib-dirs=$p/lib" 395 fi 396 '' 397 # It is not clear why --extra-framework-dirs does work fine on Linux 398 + optionalString (!stdenv.buildPlatform.isDarwin || versionAtLeast nativeGhc.version "8.0") '' 399 if [[ -d "$p/Library/Frameworks" ]]; then 400 configureFlags+=" --extra-framework-dirs=$p/Library/Frameworks" 401 fi 402 '' + '' 403 done 404 '' 405 # only use the links hack if we're actually building dylibs. otherwise, the 406 # "dynamic-library-dirs" point to nonexistent paths, and the ln command becomes 407 # "ln -s $out/lib/links", which tries to recreate the links dir and fails 408 # 409 # Note: We need to disable this work-around when using intermediate build 410 # products from a prior build because otherwise Nix will change permissions on 411 # the `$out/lib/links` directory to read-only when the build is done after the 412 # dist directory has already been exported, which triggers an unnecessary 413 # rebuild of modules included in the exported dist directory. 414 + (optionalString (stdenv.isDarwin && (enableSharedLibraries || enableSharedExecutables) && !enableSeparateIntermediatesOutput) '' 415 # Work around a limit in the macOS Sierra linker on the number of paths 416 # referenced by any one dynamic library: 417 # 418 # Create a local directory with symlinks of the *.dylib (macOS shared 419 # libraries) from all the dependencies. 420 local dynamicLinksDir="$out/lib/links" 421 mkdir -p $dynamicLinksDir 422 423 # Unprettify all package conf files before reading/writing them 424 for d in "$packageConfDir/"*; do 425 # gawk -i inplace seems to strip the last newline 426 gawk -f ${unprettyConf} "$d" > tmp 427 mv tmp "$d" 428 done 429 430 for d in $(grep '^dynamic-library-dirs:' "$packageConfDir"/* | cut -d' ' -f2- | tr ' ' '\n' | sort -u); do 431 for lib in "$d/"*.{dylib,so}; do 432 # Allow overwriting because C libs can be pulled in multiple times. 433 ln -sf "$lib" "$dynamicLinksDir" 434 done 435 done 436 # Edit the local package DB to reference the links directory. 437 for f in "$packageConfDir/"*.conf; do 438 sed -i "s,dynamic-library-dirs: .*,dynamic-library-dirs: $dynamicLinksDir," "$f" 439 done 440 '') + '' 441 ${ghcCommand}-pkg --${packageDbFlag}="$packageConfDir" recache 442 443 runHook postSetupCompilerEnvironment 444 ''; 445 446 compileBuildDriverPhase = '' 447 runHook preCompileBuildDriver 448 449 for i in Setup.hs Setup.lhs ${defaultSetupHs}; do 450 test -f $i && break 451 done 452 453 echo setupCompileFlags: $setupCompileFlags 454 ${nativeGhcCommand} $setupCompileFlags --make -o Setup -odir $builddir -hidir $builddir $i 455 456 runHook postCompileBuildDriver 457 ''; 458 459 # Cabal takes flags like `--configure-option=--host=...` instead 460 configurePlatforms = []; 461 inherit configureFlags; 462 463 # Note: the options here must be always added, regardless of whether the 464 # package specifies `hardeningDisable`. 465 hardeningDisable = lib.optionals (args ? hardeningDisable) hardeningDisable 466 ++ lib.optional (ghc.isHaLVM or false) "all" 467 # Static libraries (ie. all of pkgsStatic.haskellPackages) fail to build 468 # because by default Nix adds `-pie` to the linker flags: this 469 # conflicts with the `-r` and `-no-pie` flags added by GHC (see 470 # https://gitlab.haskell.org/ghc/ghc/-/issues/19580). hardeningDisable 471 # changes the default Nix behavior regarding adding "hardening" flags. 472 ++ lib.optional enableStaticLibraries "pie"; 473 474 configurePhase = '' 475 runHook preConfigure 476 477 unset GHC_PACKAGE_PATH # Cabal complains if this variable is set during configure. 478 479 echo configureFlags: $configureFlags 480 ${setupCommand} configure $configureFlags 2>&1 | ${coreutils}/bin/tee "$NIX_BUILD_TOP/cabal-configure.log" 481 ${lib.optionalString (!allowInconsistentDependencies) '' 482 if ${gnugrep}/bin/egrep -q -z 'Warning:.*depends on multiple versions' "$NIX_BUILD_TOP/cabal-configure.log"; then 483 echo >&2 "*** abort because of serious configure-time warning from Cabal" 484 exit 1 485 fi 486 ''} 487 export GHC_PACKAGE_PATH="$packageConfDir:" 488 489 runHook postConfigure 490 ''; 491 492 buildPhase = 493 '' 494 runHook preBuild 495 '' 496 + lib.optionalString (previousIntermediates != null) 497 '' 498 mkdir -p dist; 499 rm -r dist/build 500 cp -r ${previousIntermediates}/${intermediatesDir}/build dist/build 501 find dist/build -exec chmod u+w {} + 502 find dist/build -exec touch -d '1970-01-01T00:00:00Z' {} + 503 '' 504 + '' 505 ${setupCommand} build ${buildTarget}${crossCabalFlagsString}${buildFlagsString} 506 runHook postBuild 507 ''; 508 509 inherit doCheck; 510 511 # Run test suite(s) and pass `checkFlags` as well as `checkFlagsArray`. 512 # `testFlags` are added to `checkFlagsArray` each prefixed with 513 # `--test-option`, so Cabal passes it to the underlying test suite binary. 514 checkPhase = '' 515 runHook preCheck 516 checkFlagsArray+=( 517 "--show-details=streaming" 518 ${lib.escapeShellArgs (builtins.map (opt: "--test-option=${opt}") testFlags)} 519 ) 520 ${setupCommand} test ${testTarget} $checkFlags ''${checkFlagsArray:+"''${checkFlagsArray[@]}"} 521 runHook postCheck 522 ''; 523 524 haddockPhase = '' 525 runHook preHaddock 526 ${optionalString (doHaddock && isLibrary) '' 527 ${setupCommand} haddock --html \ 528 ${optionalString doHoogle "--hoogle"} \ 529 ${optionalString doHaddockQuickjump "--quickjump"} \ 530 ${optionalString (isLibrary && hyperlinkSource) "--hyperlink-source"} \ 531 ${lib.concatStringsSep " " haddockFlags} 532 ''} 533 runHook postHaddock 534 ''; 535 536 installPhase = '' 537 runHook preInstall 538 539 ${if !isLibrary && buildTarget == "" then "${setupCommand} install" 540 # ^^ if the project is not a library, and no build target is specified, we can just use "install". 541 else if !isLibrary then "${setupCommand} copy ${buildTarget}" 542 # ^^ if the project is not a library, and we have a build target, then use "copy" to install 543 # just the target specified; "install" will error here, since not all targets have been built. 544 else '' 545 ${setupCommand} copy ${buildTarget} 546 local packageConfDir="$out/${ghcLibdir}/package.conf.d" 547 local packageConfFile="$packageConfDir/${pname}-${version}.conf" 548 mkdir -p "$packageConfDir" 549 ${setupCommand} register --gen-pkg-config=$packageConfFile 550 if [ -d "$packageConfFile" ]; then 551 mv "$packageConfFile/"* "$packageConfDir" 552 rmdir "$packageConfFile" 553 fi 554 for packageConfFile in "$packageConfDir/"*; do 555 local pkgId=$(gawk -f ${unprettyConf} "$packageConfFile" \ 556 | grep '^id:' | cut -d' ' -f2) 557 mv "$packageConfFile" "$packageConfDir/$pkgId.conf" 558 done 559 560 # delete confdir if there are no libraries 561 find $packageConfDir -maxdepth 0 -empty -delete; 562 ''} 563 ${optionalString isGhcjs '' 564 for exeDir in "${binDir}/"*.jsexe; do 565 exe="''${exeDir%.jsexe}" 566 printWords '#!${nodejs}/bin/node' > "$exe" 567 echo >> "$exe" 568 cat "$exeDir/all.js" >> "$exe" 569 chmod +x "$exe" 570 done 571 ''} 572 ${optionalString doCoverage "mkdir -p $out/share && cp -r dist/hpc $out/share"} 573 ${optionalString (enableSharedExecutables && isExecutable && !isGhcjs && stdenv.isDarwin && lib.versionOlder ghc.version "7.10") '' 574 for exe in "${binDir}/"* ; do 575 install_name_tool -add_rpath "$out/${ghcLibdir}/${pname}-${version}" "$exe" 576 done 577 ''} 578 579 ${optionalString enableSeparateDocOutput '' 580 for x in ${docdir "$doc"}"/html/src/"*.html; do 581 remove-references-to -t $out $x 582 done 583 mkdir -p $doc 584 ''} 585 ${optionalString enableSeparateDataOutput "mkdir -p $data"} 586 587 runHook postInstall 588 ''; 589 590 ${if doInstallIntermediates then "installIntermediatesPhase" else null} = '' 591 runHook preInstallIntermediates 592 intermediatesOutput=${if enableSeparateIntermediatesOutput then "$intermediates" else "$out"} 593 installIntermediatesDir="$intermediatesOutput/${intermediatesDir}" 594 mkdir -p "$installIntermediatesDir" 595 cp -r dist/build "$installIntermediatesDir" 596 runHook postInstallIntermediates 597 ''; 598 599 passthru = passthru // rec { 600 601 inherit pname version; 602 603 compiler = ghc; 604 605 # All this information is intended just for `shellFor`. It should be 606 # considered unstable and indeed we knew how to keep it private we would. 607 getCabalDeps = { 608 inherit 609 buildDepends 610 buildTools 611 executableFrameworkDepends 612 executableHaskellDepends 613 executablePkgconfigDepends 614 executableSystemDepends 615 executableToolDepends 616 extraLibraries 617 libraryFrameworkDepends 618 libraryHaskellDepends 619 libraryPkgconfigDepends 620 librarySystemDepends 621 libraryToolDepends 622 pkg-configDepends 623 setupHaskellDepends 624 ; 625 } // lib.optionalAttrs doCheck { 626 inherit 627 testDepends 628 testFrameworkDepends 629 testHaskellDepends 630 testPkgconfigDepends 631 testSystemDepends 632 testToolDepends 633 ; 634 } // lib.optionalAttrs doBenchmark { 635 inherit 636 benchmarkDepends 637 benchmarkFrameworkDepends 638 benchmarkHaskellDepends 639 benchmarkPkgconfigDepends 640 benchmarkSystemDepends 641 benchmarkToolDepends 642 ; 643 }; 644 645 # Attributes for the old definition of `shellFor`. Should be removed but 646 # this predates the warning at the top of `getCabalDeps`. 647 getBuildInputs = rec { 648 inherit propagatedBuildInputs otherBuildInputs allPkgconfigDepends; 649 haskellBuildInputs = isHaskellPartition.right; 650 systemBuildInputs = isHaskellPartition.wrong; 651 isHaskellPartition = lib.partition 652 isHaskellPkg 653 (propagatedBuildInputs ++ otherBuildInputs ++ depsBuildBuild ++ nativeBuildInputs); 654 }; 655 656 isHaskellLibrary = isLibrary; 657 658 # TODO: ask why the split outputs are configurable at all? 659 # TODO: include tests for split if possible 660 # Given the haskell package, returns 661 # the directory containing the haddock documentation. 662 # `null' if no haddock documentation was built. 663 # TODO: fetch the self from the fixpoint instead 664 haddockDir = self: if doHaddock then "${docdir self.doc}/html" else null; 665 666 # Creates a derivation containing all of the necessary dependencies for building the 667 # parent derivation. The attribute set that it takes as input can be viewed as: 668 # 669 # { withHoogle } 670 # 671 # The derivation that it builds contains no outpaths because it is meant for use 672 # as an environment 673 # 674 # # Example use 675 # # Creates a shell with all of the dependencies required to build the "hello" package, 676 # # and with python: 677 # 678 # > nix-shell -E 'with (import <nixpkgs> {}); \ 679 # > haskell.packages.ghc865.hello.envFunc { buildInputs = [ python ]; }' 680 envFunc = { withHoogle ? false }: 681 let 682 name = "ghc-shell-for-${drv.name}"; 683 684 withPackages = if withHoogle then ghcWithHoogle else ghcWithPackages; 685 686 # We use the `ghcWithPackages` function from `buildHaskellPackages` if we 687 # want a shell for the sake of cross compiling a package. In the native case 688 # we don't use this at all, and instead put the setupDepends in the main 689 # `ghcWithPackages`. This way we don't have two wrapper scripts called `ghc` 690 # shadowing each other on the PATH. 691 ghcEnvForBuild = 692 assert isCross; 693 buildHaskellPackages.ghcWithPackages (_: setupHaskellDepends); 694 695 ghcEnv = withPackages (_: 696 otherBuildInputsHaskell ++ 697 propagatedBuildInputs ++ 698 lib.optionals (!isCross) setupHaskellDepends); 699 700 ghcCommandCaps = lib.toUpper ghcCommand'; 701 in stdenv.mkDerivation ({ 702 inherit name shellHook; 703 704 depsBuildBuild = lib.optional isCross ghcEnvForBuild; 705 nativeBuildInputs = 706 [ ghcEnv ] ++ optional (allPkgconfigDepends != []) pkg-config ++ 707 collectedToolDepends; 708 buildInputs = 709 otherBuildInputsSystem; 710 phases = ["installPhase"]; 711 installPhase = "echo $nativeBuildInputs $buildInputs > $out"; 712 LANG = "en_US.UTF-8"; 713 LOCALE_ARCHIVE = lib.optionalString (stdenv.hostPlatform.libc == "glibc") "${buildPackages.glibcLocales}/lib/locale/locale-archive"; 714 "NIX_${ghcCommandCaps}" = "${ghcEnv}/bin/${ghcCommand}"; 715 "NIX_${ghcCommandCaps}PKG" = "${ghcEnv}/bin/${ghcCommand}-pkg"; 716 # TODO: is this still valid? 717 "NIX_${ghcCommandCaps}_DOCDIR" = "${ghcEnv}/share/doc/ghc/html"; 718 "NIX_${ghcCommandCaps}_LIBDIR" = if ghc.isHaLVM or false 719 then "${ghcEnv}/lib/HaLVM-${ghc.version}" 720 else "${ghcEnv}/${ghcLibdir}"; 721 }); 722 723 env = envFunc { }; 724 725 }; 726 727 meta = { inherit homepage license platforms; } 728 // optionalAttrs (args ? broken) { inherit broken; } 729 // optionalAttrs (args ? description) { inherit description; } 730 // optionalAttrs (args ? maintainers) { inherit maintainers; } 731 // optionalAttrs (args ? hydraPlatforms) { inherit hydraPlatforms; } 732 // optionalAttrs (args ? badPlatforms) { inherit badPlatforms; } 733 // optionalAttrs (args ? changelog) { inherit changelog; } 734 // optionalAttrs (args ? mainProgram) { inherit mainProgram; } 735 ; 736 737} 738// optionalAttrs (args ? preCompileBuildDriver) { inherit preCompileBuildDriver; } 739// optionalAttrs (args ? postCompileBuildDriver) { inherit postCompileBuildDriver; } 740// optionalAttrs (args ? preUnpack) { inherit preUnpack; } 741// optionalAttrs (args ? postUnpack) { inherit postUnpack; } 742// optionalAttrs (args ? patches) { inherit patches; } 743// optionalAttrs (args ? patchPhase) { inherit patchPhase; } 744// optionalAttrs (args ? preConfigure) { inherit preConfigure; } 745// optionalAttrs (args ? postConfigure) { inherit postConfigure; } 746// optionalAttrs (args ? preBuild) { inherit preBuild; } 747// optionalAttrs (args ? postBuild) { inherit postBuild; } 748// optionalAttrs (args ? doBenchmark) { inherit doBenchmark; } 749// optionalAttrs (args ? checkPhase) { inherit checkPhase; } 750// optionalAttrs (args ? preCheck) { inherit preCheck; } 751// optionalAttrs (args ? postCheck) { inherit postCheck; } 752// optionalAttrs (args ? preHaddock) { inherit preHaddock; } 753// optionalAttrs (args ? postHaddock) { inherit postHaddock; } 754// optionalAttrs (args ? preInstall) { inherit preInstall; } 755// optionalAttrs (args ? installPhase) { inherit installPhase; } 756// optionalAttrs (args ? postInstall) { inherit postInstall; } 757// optionalAttrs (args ? preFixup) { inherit preFixup; } 758// optionalAttrs (args ? postFixup) { inherit postFixup; } 759// optionalAttrs (args ? dontStrip) { inherit dontStrip; } 760// optionalAttrs (postPhases != []) { inherit postPhases; } 761// optionalAttrs (stdenv.buildPlatform.libc == "glibc"){ LOCALE_ARCHIVE = "${glibcLocales}/lib/locale/locale-archive"; } 762) 763)