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