Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1{ 2 version, 3 rev ? null, 4 sha256, 5 url ? 6 if rev != null then 7 "https://gitlab.haskell.org/ghc/ghc.git" 8 else 9 "https://downloads.haskell.org/ghc/${version}/ghc-${version}-src.tar.xz", 10 postFetch ? null, 11}: 12 13{ 14 lib, 15 stdenv, 16 stdenvNoCC, 17 pkgsBuildTarget, 18 pkgsHostTarget, 19 buildPackages, 20 targetPackages, 21 fetchpatch, 22 23 # build-tools 24 bootPkgs, 25 autoreconfHook, 26 coreutils, 27 fetchurl, 28 fetchgit, 29 perl, 30 python3, 31 sphinx, 32 xattr, 33 autoSignDarwinBinariesHook, 34 bash, 35 srcOnly, 36 37 libiconv ? null, 38 ncurses, 39 glibcLocales ? null, 40 41 # GHC can be built with system libffi or a bundled one. 42 libffi ? null, 43 44 useLLVM ? !(import ./common-have-ncg.nix { inherit lib stdenv version; }), 45 # LLVM is conceptually a run-time-only dependency, but for 46 # non-x86, we need LLVM to bootstrap later stages, so it becomes a 47 # build-time dependency too. 48 buildTargetLlvmPackages, 49 llvmPackages, 50 51 # If enabled, GHC will be built with the GPL-free but slightly slower native 52 # bignum backend instead of the faster but GPLed gmp backend. 53 enableNativeBignum ? 54 !(lib.meta.availableOn stdenv.hostPlatform gmp && lib.meta.availableOn stdenv.targetPlatform gmp) 55 || stdenv.targetPlatform.isGhcjs, 56 gmp, 57 58 # If enabled, use -fPIC when compiling static libs. 59 enableRelocatedStaticLibs ? stdenv.targetPlatform != stdenv.hostPlatform, 60 61 # Exceeds Hydra output limit (at the time of writing ~3GB) when cross compiled to riscv64. 62 # A riscv64 cross-compiler fits into the limit comfortably. 63 enableProfiledLibs ? !stdenv.hostPlatform.isRiscV64, 64 65 # Whether to build dynamic libs for the standard library (on the target 66 # platform). Static libs are always built. 67 enableShared ? with stdenv.targetPlatform; !isWindows && !useiOSPrebuilt && !isStatic && !isGhcjs, 68 69 # Whether to build terminfo. 70 # FIXME(@sternenseemann): This actually doesn't influence what hadrian does, 71 # just what buildInputs etc. looks like. It would be best if we could actually 72 # tell it what to do like it was possible with make. 73 enableTerminfo ? 74 !( 75 stdenv.targetPlatform.isWindows 76 || stdenv.targetPlatform.isGhcjs 77 # terminfo can't be built for cross 78 || (stdenv.buildPlatform != stdenv.hostPlatform) 79 || (stdenv.hostPlatform != stdenv.targetPlatform) 80 ), 81 82 # Libdw.c only supports x86_64, i686 and s390x as of 2022-08-04 83 enableDwarf ? 84 (stdenv.targetPlatform.isx86 || (stdenv.targetPlatform.isS390 && stdenv.targetPlatform.is64bit)) 85 && lib.meta.availableOn stdenv.hostPlatform elfutils 86 && lib.meta.availableOn stdenv.targetPlatform elfutils 87 && 88 # HACK: elfutils is marked as broken on static platforms 89 # which availableOn can't tell. 90 !stdenv.targetPlatform.isStatic 91 && !stdenv.hostPlatform.isStatic, 92 elfutils, 93 94 # What flavour to build. Flavour string may contain a flavour and flavour 95 # transformers as accepted by hadrian. 96 ghcFlavour ? 97 let 98 # TODO(@sternenseemann): does using the static flavour make sense? 99 baseFlavour = "release"; 100 # Note: in case hadrian's flavour transformers cease being expressive 101 # enough for us, we'll need to resort to defining a "nixpkgs" flavour 102 # in hadrianUserSettings and using that instead. 103 transformers = 104 lib.optionals useLLVM [ "llvm" ] 105 ++ lib.optionals (!enableShared) [ 106 "no_dynamic_libs" 107 "no_dynamic_ghc" 108 ] 109 ++ lib.optionals (!enableProfiledLibs) [ "no_profiled_libs" ] 110 # While split sections are now enabled by default in ghc 8.8 for windows, 111 # they seem to lead to `too many sections` errors when building base for 112 # profiling. 113 ++ lib.optionals (!stdenv.targetPlatform.isWindows) [ "split_sections" ]; 114 in 115 baseFlavour + lib.concatMapStrings (t: "+${t}") transformers, 116 117 # Contents of the UserSettings.hs file to use when compiling hadrian. 118 hadrianUserSettings ? '' 119 module UserSettings ( 120 userFlavours, userPackages, userDefaultFlavour, 121 verboseCommand, buildProgressColour, successColour, finalStage 122 ) where 123 124 import Flavour.Type 125 import Expression 126 import {-# SOURCE #-} Settings.Default 127 128 -- no way to set this via the command line 129 finalStage :: Stage 130 finalStage = ${ 131 # Always build the stage 2 compiler if possible. 132 # TODO(@sternensemann): unify condition with make-built GHCs 133 if stdenv.hostPlatform.canExecute stdenv.targetPlatform then 134 "Stage2" # native compiler or “native” cross e.g. pkgsStatic 135 else 136 "Stage1" # cross compiler 137 } 138 139 userDefaultFlavour :: String 140 userDefaultFlavour = "release" 141 142 userFlavours :: [Flavour] 143 userFlavours = [] 144 145 -- Disable Colours 146 buildProgressColour :: BuildProgressColour 147 buildProgressColour = mkBuildProgressColour (Dull Reset) 148 successColour :: SuccessColour 149 successColour = mkSuccessColour (Dull Reset) 150 151 -- taken from src/UserSettings.hs unchanged, need to be there 152 userPackages :: [Package] 153 userPackages = [] 154 verboseCommand :: Predicate 155 verboseCommand = do 156 verbosity <- expr getVerbosity 157 return $ verbosity >= Verbose 158 '', 159 160 ghcSrc ? srcOnly { 161 name = "ghc-${version}"; # -source appended by srcOnly 162 src = (if rev != null then fetchgit else fetchurl) ( 163 { 164 inherit url sha256; 165 } 166 // lib.optionalAttrs (rev != null) { 167 inherit rev; 168 } 169 // lib.optionalAttrs (postFetch != null) { 170 inherit postFetch; 171 } 172 ); 173 174 patches = 175 let 176 enableHyperlinkedSource = 177 # Disable haddock generating pretty source listings to stay under 3GB on aarch64-linux 178 !(stdenv.hostPlatform.isAarch64 && stdenv.hostPlatform.isLinux) 179 # 9.8 and 9.10 don't run into this problem for some reason 180 || (lib.versionAtLeast version "9.8" && lib.versionOlder version "9.11"); 181 in 182 183 # Fix docs build with Sphinx >= 7 https://gitlab.haskell.org/ghc/ghc/-/issues/24129 184 lib.optionals (lib.versionOlder version "9.6.7") [ 185 ./docs-sphinx-7.patch 186 ] 187 ++ lib.optionals (lib.versionAtLeast version "9.6" && lib.versionOlder version "9.6.5") [ 188 # Fix aarch64-linux builds of 9.6.0 - 9.6.4. 189 # Fixes a pointer type mismatch in the RTS. 190 # https://gitlab.haskell.org/ghc/ghc/-/issues/24348 191 (fetchpatch { 192 name = "fix-incompatible-pointer-types.patch"; 193 url = "https://gitlab.haskell.org/ghc/ghc/-/commit/1e48c43483693398001bfb0ae644a3558bf6a9f3.diff"; 194 hash = "sha256-zUlzpX7J1n+MCEv9AWpj69FTy2uzJH8wrQDkTexGbgM="; 195 }) 196 ] 197 ++ 198 lib.optionals 199 ( 200 # 2025-01-16: unix >= 2.8.6.0 is unaffected which is shipped by GHC 9.12.1 and 9.8.4 201 lib.versionOlder version "9.11" 202 && !(lib.versionAtLeast version "9.6.7" && lib.versionOlder version "9.8") 203 && !(lib.versionAtLeast version "9.8.4" && lib.versionOlder version "9.9") 204 && !(lib.versionAtLeast version "9.10.2" && lib.versionOlder version "9.11") 205 ) 206 [ 207 # Determine size of time related types using hsc2hs instead of assuming CLong. 208 # Prevents failures when e.g. stat(2)ing on 32bit systems with 64bit time_t etc. 209 # https://github.com/haskell/ghcup-hs/issues/1107 210 # https://gitlab.haskell.org/ghc/ghc/-/issues/25095 211 # Note that in normal situations this shouldn't be the case since nixpkgs 212 # doesn't set -D_FILE_OFFSET_BITS=64 and friends (yet). 213 (fetchpatch { 214 name = "unix-fix-ctimeval-size-32-bit.patch"; 215 url = "https://github.com/haskell/unix/commit/8183e05b97ce870dd6582a3677cc82459ae566ec.patch"; 216 sha256 = "17q5yyigqr5kxlwwzb95sx567ysfxlw6bp3j4ji20lz0947aw6gv"; 217 stripLen = 1; 218 extraPrefix = "libraries/unix/"; 219 }) 220 ] 221 ++ lib.optionals (lib.versionAtLeast version "9.6" && lib.versionOlder version "9.6.6") [ 222 (fetchpatch { 223 name = "fix-fully_static.patch"; 224 url = "https://gitlab.haskell.org/ghc/ghc/-/commit/1bb24432ff77e11a0340a7d8586e151e15bba2a1.diff"; 225 hash = "sha256-MpvTmFFsNiPDoOp9BhZyWeapeibQ77zgEV+xzZ1UAXs="; 226 }) 227 ] 228 ++ lib.optionals (lib.versionAtLeast version "9.6" && lib.versionOlder version "9.8") [ 229 # Fix unlit being installed under a different name than is used in the 230 # settings file: https://gitlab.haskell.org/ghc/ghc/-/issues/23317 231 (fetchpatch { 232 name = "ghc-9.6-fix-unlit-path.patch"; 233 url = "https://gitlab.haskell.org/ghc/ghc/-/commit/8fde4ac84ec7b1ead238cb158bbef48555d12af9.patch"; 234 hash = "sha256-3+CyRBpebEZi8YpS22SsdGQHqi0drR7cCKPtKbR3zyE="; 235 }) 236 ] 237 ++ lib.optionals (stdenv.targetPlatform.isDarwin && stdenv.targetPlatform.isAarch64) [ 238 # Prevent the paths module from emitting symbols that we don't use 239 # when building with separate outputs. 240 # 241 # These cause problems as they're not eliminated by GHC's dead code 242 # elimination on aarch64-darwin. (see 243 # https://github.com/NixOS/nixpkgs/issues/140774 for details). 244 ( 245 if lib.versionOlder version "9.10" then 246 ./Cabal-at-least-3.6-paths-fix-cycle-aarch64-darwin.patch 247 else 248 ./Cabal-3.12-paths-fix-cycle-aarch64-darwin.patch 249 ) 250 ] 251 # Prevents passing --hyperlinked-source to haddock. Note that this can 252 # be configured via a user defined flavour now. Unfortunately, it is 253 # impossible to import an existing flavour in UserSettings, so patching 254 # the defaults is actually simpler and less maintenance intensive 255 # compared to keeping an entire flavour definition in sync with upstream 256 # manually. See also https://gitlab.haskell.org/ghc/ghc/-/issues/23625 257 ++ lib.optionals (!enableHyperlinkedSource) [ 258 ( 259 if lib.versionOlder version "9.8" then 260 ../../tools/haskell/hadrian/disable-hyperlinked-source-pre-9.8.patch 261 else 262 ../../tools/haskell/hadrian/disable-hyperlinked-source-extra-args.patch 263 ) 264 ] 265 # Incorrect bounds on Cabal in hadrian 266 # https://gitlab.haskell.org/ghc/ghc/-/issues/24100 267 ++ 268 lib.optionals 269 (lib.elem version [ 270 "9.8.1" 271 "9.8.2" 272 ]) 273 [ 274 ../../tools/haskell/hadrian/hadrian-9.8.1-allow-Cabal-3.10.patch 275 ] 276 ++ lib.optionals (lib.versionAtLeast version "9.8" && lib.versionOlder version "9.12") [ 277 (fetchpatch { 278 name = "enable-ignore-build-platform-mismatch.patch"; 279 url = "https://gitlab.haskell.org/ghc/ghc/-/commit/4ee094d46effd06093090fcba70f0a80d2a57e6c.patch"; 280 includes = [ "configure.ac" ]; 281 hash = "sha256-L3FQvcm9QB59BOiR2g5/HACAufIG08HiT53EIOjj64g="; 282 }) 283 ] 284 # Fixes stack overrun in rts which crashes an process whenever 285 # freeHaskellFunPtr is called with nixpkgs' hardening flags. 286 # https://gitlab.haskell.org/ghc/ghc/-/issues/25485 287 # https://gitlab.haskell.org/ghc/ghc/-/merge_requests/13599 288 ++ lib.optionals (lib.versionOlder version "9.13") [ 289 (fetchpatch { 290 name = "ghc-rts-adjustor-fix-i386-stack-overrun.patch"; 291 url = "https://gitlab.haskell.org/ghc/ghc/-/commit/39bb6e583d64738db51441a556d499aa93a4fc4a.patch"; 292 sha256 = "0w5fx413z924bi2irsy1l4xapxxhrq158b5gn6jzrbsmhvmpirs0"; 293 }) 294 ]; 295 296 stdenv = stdenvNoCC; 297 }, 298 299 # GHC's build system hadrian built from the GHC-to-build's source tree 300 # using our bootstrap GHC. 301 hadrian ? import ../../tools/haskell/hadrian/make-hadrian.nix { inherit bootPkgs lib; } { 302 inherit ghcSrc; 303 ghcVersion = version; 304 userSettings = hadrianUserSettings; 305 }, 306 307 # Whether to build sphinx documentation. 308 # TODO(@sternenseemann): Hadrian ignores the --docs flag if finalStage = Stage1 309 enableDocs ? ( 310 # Docs disabled if we are building on musl because it's a large task to keep 311 # all `sphinx` dependencies building in this environment. 312 !stdenv.buildPlatform.isMusl 313 ), 314 315 # Whether to disable the large address space allocator 316 # necessary fix for iOS: https://www.reddit.com/r/haskell/comments/4ttdz1/building_an_osxi386_to_iosarm64_cross_compiler/d5qvd67/ 317 disableLargeAddressSpace ? stdenv.targetPlatform.isiOS, 318 319 # Whether to build an unregisterised version of GHC. 320 # GHC will normally auto-detect whether it can do a registered build, but this 321 # option will force it to do an unregistered build when set to true. 322 # See https://gitlab.haskell.org/ghc/ghc/-/wikis/building/unregisterised 323 enableUnregisterised ? false, 324}: 325 326assert !enableNativeBignum -> gmp != null; 327 328# GHC does not support building when all 3 platforms are different. 329assert stdenv.buildPlatform == stdenv.hostPlatform || stdenv.hostPlatform == stdenv.targetPlatform; 330 331# It is currently impossible to cross-compile GHC with Hadrian. 332assert stdenv.buildPlatform == stdenv.hostPlatform; 333 334let 335 inherit (stdenv) buildPlatform hostPlatform targetPlatform; 336 337 # TODO(@Ericson2314) Make unconditional 338 targetPrefix = lib.optionalString (targetPlatform != hostPlatform) "${targetPlatform.config}-"; 339 340 hadrianSettings = 341 # -fexternal-dynamic-refs apparently (because it's not clear from the 342 # documentation) makes the GHC RTS able to load static libraries, which may 343 # be needed for TemplateHaskell. This solution was described in 344 # https://www.tweag.io/blog/2020-09-30-bazel-static-haskell 345 lib.optionals enableRelocatedStaticLibs [ 346 "*.*.ghc.*.opts += -fPIC -fexternal-dynamic-refs" 347 ] 348 ++ lib.optionals targetPlatform.useAndroidPrebuilt [ 349 "*.*.ghc.c.opts += -optc-std=gnu99" 350 ]; 351 352 # Splicer will pull out correct variations 353 libDeps = 354 platform: 355 lib.optional enableTerminfo ncurses 356 ++ lib.optionals (!targetPlatform.isGhcjs) [ libffi ] 357 # Bindist configure script fails w/o elfutils in linker search path 358 # https://gitlab.haskell.org/ghc/ghc/-/issues/22081 359 ++ lib.optional enableDwarf elfutils 360 ++ lib.optional (!enableNativeBignum) gmp 361 ++ lib.optional ( 362 platform.libc != "glibc" 363 && !targetPlatform.isWindows 364 && !targetPlatform.isGhcjs 365 && !targetPlatform.useAndroidPrebuilt 366 ) libiconv; 367 368 # TODO(@sternenseemann): is buildTarget LLVM unnecessary? 369 # GHC doesn't seem to have {LLC,OPT}_HOST 370 toolsForTarget = [ 371 ( 372 if targetPlatform.isGhcjs then 373 pkgsBuildTarget.emscripten 374 else 375 pkgsBuildTarget.targetPackages.stdenv.cc 376 ) 377 ] 378 ++ lib.optional useLLVM buildTargetLlvmPackages.llvm; 379 380 buildCC = buildPackages.stdenv.cc; 381 targetCC = builtins.head toolsForTarget; 382 installCC = 383 if targetPlatform.isGhcjs then 384 pkgsHostTarget.emscripten 385 else 386 pkgsHostTarget.targetPackages.stdenv.cc; 387 388 # toolPath calculates the absolute path to the name tool associated with a 389 # given `stdenv.cc` derivation, i.e. it picks the correct derivation to take 390 # the tool from (cc, cc.bintools, cc.bintools.bintools) and adds the correct 391 # subpath of the tool. 392 toolPath = 393 name: cc: 394 let 395 tools = 396 { 397 "cc" = cc; 398 "c++" = cc; 399 as = cc.bintools; 400 401 ar = cc.bintools; 402 ranlib = cc.bintools; 403 nm = cc.bintools; 404 readelf = cc.bintools; 405 objdump = cc.bintools; 406 407 ld = cc.bintools; 408 "ld.gold" = cc.bintools; 409 410 otool = cc.bintools.bintools; 411 412 # GHC needs install_name_tool on all darwin platforms. The same one can 413 # be used on both platforms. It is safe to use with linker-generated 414 # signatures because it will update the signatures automatically after 415 # modifying the target binary. 416 install_name_tool = cc.bintools.bintools; 417 418 # strip on darwin is wrapped to enable deterministic mode. 419 strip = 420 # TODO(@sternenseemann): also use wrapper if linker == "bfd" or "gold" 421 if stdenv.targetPlatform.isDarwin then cc.bintools else cc.bintools.bintools; 422 423 # clang is used as an assembler on darwin with the LLVM backend 424 clang = cc; 425 } 426 .${name}; 427 in 428 "${tools}/bin/${tools.targetPrefix}${name}"; 429 430 # Use gold either following the default, or to avoid the BFD linker due to some bugs / perf issues. 431 # But we cannot avoid BFD when using musl libc due to https://sourceware.org/bugzilla/show_bug.cgi?id=23856 432 # see #84670 and #49071 for more background. 433 useLdGold = 434 targetPlatform.linker == "gold" 435 || ( 436 targetPlatform.linker == "bfd" 437 && (targetCC.bintools.bintools.hasGold or false) 438 && !targetPlatform.isMusl 439 ); 440 441 # Makes debugging easier to see which variant is at play in `nix-store -q --tree`. 442 variantSuffix = lib.concatStrings [ 443 (lib.optionalString stdenv.hostPlatform.isMusl "-musl") 444 (lib.optionalString enableNativeBignum "-native-bignum") 445 ]; 446 447 # These libraries are library dependencies of the standard libraries bundled 448 # by GHC (core libs) users will link their compiled artifacts again. Thus, 449 # they should be taken from targetPackages. 450 # 451 # We need to use pkgsHostTarget if we are cross compiling a native GHC compiler, 452 # though (when native compiling GHC, pkgsHostTarget == targetPackages): 453 # 454 # 1. targetPackages would be empty(-ish) in this situation since we can't 455 # execute cross compiled compilers in order to obtain the libraries 456 # that would be in targetPackages. 457 # 2. pkgsHostTarget is fine to use since hostPlatform == targetPlatform in this 458 # situation. 459 # 3. The core libs used by the final GHC (stage 2) for user artifacts are also 460 # used to build stage 2 GHC itself, i.e. the core libs are both host and 461 # target. 462 targetLibs = { 463 inherit (if hostPlatform != targetPlatform then targetPackages else pkgsHostTarget) 464 elfutils 465 gmp 466 libffi 467 ncurses 468 ; 469 }; 470 471 # Our Cabal compiler name 472 haskellCompilerName = "ghc-${version}"; 473 474in 475 476stdenv.mkDerivation ( 477 { 478 pname = "${targetPrefix}ghc${variantSuffix}"; 479 inherit version; 480 481 src = ghcSrc; 482 483 enableParallelBuilding = true; 484 485 postPatch = '' 486 patchShebangs --build . 487 ''; 488 489 # GHC needs the locale configured during the Haddock phase. 490 LANG = "en_US.UTF-8"; 491 492 # GHC is a bit confused on its cross terminology. 493 # TODO(@sternenseemann): investigate coreutils dependencies and pass absolute paths 494 preConfigure = '' 495 for env in $(env | grep '^TARGET_' | sed -E 's|\+?=.*||'); do 496 export "''${env#TARGET_}=''${!env}" 497 done 498 # No need for absolute paths since these tools only need to work during the build 499 export CC_STAGE0="$CC_FOR_BUILD" 500 export LD_STAGE0="$LD_FOR_BUILD" 501 export AR_STAGE0="$AR_FOR_BUILD" 502 503 # Stage0 (build->build) which builds stage 1 504 export GHC="${bootPkgs.ghc}/bin/ghc" 505 # GHC is a bit confused on its cross terminology, as these would normally be 506 # the *host* tools. 507 export CC="${toolPath "cc" targetCC}" 508 export CXX="${toolPath "c++" targetCC}" 509 # Use gold to work around https://sourceware.org/bugzilla/show_bug.cgi?id=16177 510 export LD="${toolPath "ld${lib.optionalString useLdGold ".gold"}" targetCC}" 511 export AS="${toolPath "as" targetCC}" 512 export AR="${toolPath "ar" targetCC}" 513 export NM="${toolPath "nm" targetCC}" 514 export RANLIB="${toolPath "ranlib" targetCC}" 515 export READELF="${toolPath "readelf" targetCC}" 516 export STRIP="${toolPath "strip" targetCC}" 517 export OBJDUMP="${toolPath "objdump" targetCC}" 518 '' 519 + lib.optionalString (stdenv.targetPlatform.linker == "cctools") '' 520 export OTOOL="${toolPath "otool" targetCC}" 521 export INSTALL_NAME_TOOL="${toolPath "install_name_tool" targetCC}" 522 '' 523 + lib.optionalString useLLVM '' 524 export LLC="${lib.getBin buildTargetLlvmPackages.llvm}/bin/llc" 525 export OPT="${lib.getBin buildTargetLlvmPackages.llvm}/bin/opt" 526 '' 527 + lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) '' 528 # LLVM backend on Darwin needs clang: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/codegens.html#llvm-code-generator-fllvm 529 # The executable we specify via $CLANG is used as an assembler (exclusively, it seems, but this isn't 530 # clarified in any user facing documentation). As such, it'll be called on assembly produced by $CC 531 # which usually comes from the darwin stdenv. To prevent a situation where $CLANG doesn't understand 532 # the assembly it is given, we need to make sure that it matches the LLVM version of $CC if possible. 533 # It is unclear (at the time of writing 2024-09-01) whether $CC should match the LLVM version we use 534 # for llc and opt which would require using a custom darwin stdenv for targetCC. 535 export CLANG="${ 536 if targetCC.isClang then 537 toolPath "clang" targetCC 538 else 539 "${buildTargetLlvmPackages.clang}/bin/${buildTargetLlvmPackages.clang.targetPrefix}clang" 540 }" 541 '' 542 + lib.optionalString (stdenv.hostPlatform.isLinux && hostPlatform.libc == "glibc") '' 543 export LOCALE_ARCHIVE="${glibcLocales}/lib/locale/locale-archive" 544 '' 545 + lib.optionalString (!stdenv.hostPlatform.isDarwin) '' 546 export NIX_LDFLAGS+=" -rpath $out/lib/ghc-${version}" 547 '' 548 + lib.optionalString stdenv.hostPlatform.isDarwin '' 549 export NIX_LDFLAGS+=" -no_dtrace_dof" 550 551 # GHC tries the host xattr /usr/bin/xattr by default which fails since it expects python to be 2.7 552 export XATTR=${lib.getBin xattr}/bin/xattr 553 '' 554 # If we are not using release tarballs, some files need to be generated using 555 # the boot script. 556 + lib.optionalString (rev != null) '' 557 echo ${version} > VERSION 558 echo ${rev} > GIT_COMMIT_ID 559 ./boot 560 '' 561 + lib.optionalString targetPlatform.useAndroidPrebuilt '' 562 sed -i -e '5i ,("armv7a-unknown-linux-androideabi", ("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", "cortex-a8", ""))' llvm-targets 563 '' 564 + lib.optionalString targetPlatform.isMusl '' 565 echo "patching llvm-targets for musl targets..." 566 echo "Cloning these existing '*-linux-gnu*' targets:" 567 grep linux-gnu llvm-targets | sed 's/^/ /' 568 echo "(go go gadget sed)" 569 sed -i 's,\(^.*linux-\)gnu\(.*\)$,\0\n\1musl\2,' llvm-targets 570 echo "llvm-targets now contains these '*-linux-musl*' targets:" 571 grep linux-musl llvm-targets | sed 's/^/ /' 572 573 echo "And now patching to preserve '-musleabi' as done with '-gnueabi'" 574 # (aclocal.m4 is actual source, but patch configure as well since we don't re-gen) 575 for x in configure aclocal.m4; do 576 substituteInPlace $x \ 577 --replace '*-android*|*-gnueabi*)' \ 578 '*-android*|*-gnueabi*|*-musleabi*)' 579 done 580 '' 581 # Need to make writable EM_CACHE for emscripten. The path in EM_CACHE must be absolute. 582 # https://gitlab.haskell.org/ghc/ghc/-/wikis/javascript-backend#configure-fails-with-sub-word-sized-atomic-operations-not-available 583 + lib.optionalString targetPlatform.isGhcjs '' 584 export EM_CACHE="$(realpath $(mktemp -d emcache.XXXXXXXXXX))" 585 cp -Lr ${ 586 targetCC # == emscripten 587 }/share/emscripten/cache/* "$EM_CACHE/" 588 chmod u+rwX -R "$EM_CACHE" 589 '' 590 # Create bash array hadrianFlagsArray for use in buildPhase. Do it in 591 # preConfigure, so overrideAttrs can be used to modify it effectively. 592 # hadrianSettings are passed via the command line so they are more visible 593 # in the build log. 594 + '' 595 hadrianFlagsArray=( 596 "-j$NIX_BUILD_CORES" 597 ${lib.escapeShellArgs hadrianSettings} 598 ) 599 ''; 600 601 ${if targetPlatform.isGhcjs then "configureScript" else null} = "emconfigure ./configure"; 602 # GHC currently ships an edited config.sub so ghcjs is accepted which we can not rollback 603 ${if targetPlatform.isGhcjs then "dontUpdateAutotoolsGnuConfigScripts" else null} = true; 604 605 # TODO(@Ericson2314): Always pass "--target" and always prefix. 606 configurePlatforms = [ 607 "build" 608 "host" 609 ] 610 ++ lib.optional (targetPlatform != hostPlatform) "target"; 611 612 # `--with` flags for libraries needed for RTS linker 613 configureFlags = [ 614 "--datadir=$doc/share/doc/ghc" 615 ] 616 ++ lib.optionals enableTerminfo [ 617 "--with-curses-includes=${lib.getDev targetLibs.ncurses}/include" 618 "--with-curses-libraries=${lib.getLib targetLibs.ncurses}/lib" 619 ] 620 ++ lib.optionals (libffi != null && !targetPlatform.isGhcjs) [ 621 "--with-system-libffi" 622 "--with-ffi-includes=${targetLibs.libffi.dev}/include" 623 "--with-ffi-libraries=${targetLibs.libffi.out}/lib" 624 ] 625 ++ lib.optionals (targetPlatform == hostPlatform && !enableNativeBignum) [ 626 "--with-gmp-includes=${targetLibs.gmp.dev}/include" 627 "--with-gmp-libraries=${targetLibs.gmp.out}/lib" 628 ] 629 ++ 630 lib.optionals 631 (targetPlatform == hostPlatform && hostPlatform.libc != "glibc" && !targetPlatform.isWindows) 632 [ 633 "--with-iconv-includes=${libiconv}/include" 634 "--with-iconv-libraries=${libiconv}/lib" 635 ] 636 ++ lib.optionals (targetPlatform != hostPlatform) [ 637 "--enable-bootstrap-with-devel-snapshot" 638 ] 639 ++ lib.optionals useLdGold [ 640 "CFLAGS=-fuse-ld=gold" 641 "CONF_GCC_LINKER_OPTS_STAGE1=-fuse-ld=gold" 642 "CONF_GCC_LINKER_OPTS_STAGE2=-fuse-ld=gold" 643 ] 644 ++ lib.optionals (disableLargeAddressSpace) [ 645 "--disable-large-address-space" 646 ] 647 ++ lib.optionals enableDwarf [ 648 "--enable-dwarf-unwind" 649 "--with-libdw-includes=${lib.getDev targetLibs.elfutils}/include" 650 "--with-libdw-libraries=${lib.getLib targetLibs.elfutils}/lib" 651 ] 652 ++ lib.optionals targetPlatform.isDarwin [ 653 # Darwin uses llvm-ar. GHC will try to use `-L` with `ar` when it is `llvm-ar` 654 # but it doesn’t currently work because Cabal never uses `-L` on Darwin. See: 655 # https://gitlab.haskell.org/ghc/ghc/-/issues/23188 656 # https://github.com/haskell/cabal/issues/8882 657 "fp_cv_prog_ar_supports_dash_l=no" 658 ] 659 ++ lib.optionals enableUnregisterised [ 660 "--enable-unregisterised" 661 ] 662 ++ 663 lib.optionals 664 (stdenv.buildPlatform.isAarch64 && stdenv.buildPlatform.isMusl && lib.versionOlder version "9.12") 665 [ 666 # The bootstrap binaries for aarch64 musl were built for the wrong triple. 667 # https://gitlab.haskell.org/ghc/ghc/-/merge_requests/13182 668 "--enable-ignore-build-platform-mismatch" 669 ]; 670 671 # Make sure we never relax`$PATH` and hooks support for compatibility. 672 strictDeps = true; 673 674 # Don’t add -liconv to LDFLAGS automatically so that GHC will add it itself. 675 dontAddExtraLibs = true; 676 677 nativeBuildInputs = [ 678 autoreconfHook 679 perl 680 hadrian 681 bootPkgs.alex 682 bootPkgs.happy 683 bootPkgs.hscolour 684 # Python is used in a few scripts invoked by hadrian to generate e.g. rts headers. 685 python3 686 # Tool used to update GHC's settings file in postInstall 687 bootPkgs.ghc-settings-edit 688 ] 689 ++ lib.optionals (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64) [ 690 autoSignDarwinBinariesHook 691 ] 692 ++ lib.optionals enableDocs [ 693 sphinx 694 ]; 695 696 # For building runtime libs 697 depsBuildTarget = toolsForTarget; 698 # Everything the stage0 compiler needs to build stage1: CC, bintools, extra libs. 699 # See also GHC, {CC,LD,AR}_STAGE0 in preConfigure. 700 depsBuildBuild = [ 701 # N.B. We do not declare bootPkgs.ghc in any of the stdenv.mkDerivation 702 # dependency lists to prevent the bintools setup hook from adding ghc's 703 # lib directory to the linker flags. Instead we tell configure about it 704 # via the GHC environment variable. 705 buildCC 706 # stage0 builds terminfo unconditionally, so we always need ncurses 707 ncurses 708 ]; 709 710 # Prevent stage0 ghc from leaking into the final result. This was an issue 711 # with GHC 9.6. 712 disallowedReferences = [ 713 bootPkgs.ghc 714 ]; 715 716 buildInputs = [ bash ] ++ (libDeps hostPlatform); 717 718 depsTargetTarget = map lib.getDev (libDeps targetPlatform); 719 depsTargetTargetPropagated = map (lib.getOutput "out") (libDeps targetPlatform); 720 721 hadrianFlags = [ 722 "--flavour=${ghcFlavour}" 723 "--bignum=${if enableNativeBignum then "native" else "gmp"}" 724 "--docs=${if enableDocs then "no-sphinx-pdfs" else "no-sphinx"}" 725 ] 726 ++ lib.optionals (lib.versionAtLeast version "9.8") [ 727 # In 9.14 this will be default with release flavour. 728 # See https://gitlab.haskell.org/ghc/ghc/-/merge_requests/13444 729 "--hash-unit-ids" 730 ]; 731 732 buildPhase = '' 733 runHook preBuild 734 735 # hadrianFlagsArray is created in preConfigure 736 echo "hadrianFlags: $hadrianFlags ''${hadrianFlagsArray[@]}" 737 738 # We need to go via the bindist for installing 739 hadrian $hadrianFlags "''${hadrianFlagsArray[@]}" binary-dist-dir 740 741 runHook postBuild 742 ''; 743 744 # required, because otherwise all symbols from HSffi.o are stripped, and 745 # that in turn causes GHCi to abort 746 stripDebugFlags = [ "-S" ] ++ lib.optional (!targetPlatform.isDarwin) "--keep-file-symbols"; 747 748 checkTarget = "test"; 749 750 # GHC cannot currently produce outputs that are ready for `-pie` linking. 751 # Thus, disable `pie` hardening, otherwise `recompile with -fPIE` errors appear. 752 # See: 753 # * https://github.com/NixOS/nixpkgs/issues/129247 754 # * https://gitlab.haskell.org/ghc/ghc/-/issues/19580 755 hardeningDisable = [ 756 "format" 757 "pie" 758 ]; 759 760 # big-parallel allows us to build with more than 2 cores on 761 # Hydra which already warrants a significant speedup 762 requiredSystemFeatures = [ "big-parallel" ]; 763 764 outputs = [ 765 "out" 766 "doc" 767 ]; 768 769 # We need to configure the bindist *again* before installing 770 # https://gitlab.haskell.org/ghc/ghc/-/issues/22058 771 # TODO(@sternenseemann): it would be nice if the bindist could be an intermediate 772 # derivation, but since it is > 2GB even on x86_64-linux, not a good idea? 773 preInstall = '' 774 pushd _build/bindist/* 775 776 '' 777 # the bindist configure script uses different env variables than the GHC configure script 778 # see https://github.com/NixOS/nixpkgs/issues/267250 and https://gitlab.haskell.org/ghc/ghc/-/issues/24211 779 + lib.optionalString (stdenv.targetPlatform.linker == "cctools") '' 780 export InstallNameToolCmd=$INSTALL_NAME_TOOL 781 export OtoolCmd=$OTOOL 782 '' 783 + '' 784 $configureScript $configureFlags "''${configureFlagsArray[@]}" 785 ''; 786 787 postInstall = '' 788 # leave bindist directory 789 popd 790 791 settingsFile="$out/lib/${targetPrefix}${haskellCompilerName}/lib/settings" 792 793 # Make the installed GHC use the host->target tools. 794 ghc-settings-edit "$settingsFile" \ 795 "C compiler command" "${toolPath "cc" installCC}" \ 796 "Haskell CPP command" "${toolPath "cc" installCC}" \ 797 "C++ compiler command" "${toolPath "c++" installCC}" \ 798 "ld command" "${toolPath "ld${lib.optionalString useLdGold ".gold"}" installCC}" \ 799 "Merge objects command" "${toolPath "ld${lib.optionalString useLdGold ".gold"}" installCC}" \ 800 "ar command" "${toolPath "ar" installCC}" \ 801 "ranlib command" "${toolPath "ranlib" installCC}" 802 '' 803 + lib.optionalString (stdenv.targetPlatform.linker == "cctools") '' 804 ghc-settings-edit "$settingsFile" \ 805 "otool command" "${toolPath "otool" installCC}" \ 806 "install_name_tool command" "${toolPath "install_name_tool" installCC}" 807 '' 808 + lib.optionalString useLLVM '' 809 ghc-settings-edit "$settingsFile" \ 810 "LLVM llc command" "${lib.getBin llvmPackages.llvm}/bin/llc" \ 811 "LLVM opt command" "${lib.getBin llvmPackages.llvm}/bin/opt" 812 '' 813 + lib.optionalString (useLLVM && stdenv.targetPlatform.isDarwin) '' 814 ghc-settings-edit "$settingsFile" \ 815 "LLVM clang command" "${ 816 # See comment for CLANG in preConfigure 817 if installCC.isClang then 818 toolPath "clang" installCC 819 else 820 "${llvmPackages.clang}/bin/${llvmPackages.clang.targetPrefix}clang" 821 }" 822 '' 823 + '' 824 825 # Install the bash completion file. 826 install -Dm 644 utils/completion/ghc.bash $out/share/bash-completion/completions/${targetPrefix}ghc 827 ''; 828 829 passthru = { 830 inherit bootPkgs targetPrefix haskellCompilerName; 831 832 inherit llvmPackages; 833 inherit enableShared; 834 835 # Expose hadrian used for bootstrapping, for debugging purposes 836 inherit hadrian; 837 838 # TODO(@sternenseemann): there's no stage0:exe:haddock target by default, 839 # so haddock isn't available for GHC cross-compilers. Can we fix that? 840 hasHaddock = stdenv.hostPlatform == stdenv.targetPlatform; 841 842 bootstrapAvailable = lib.meta.availableOn stdenv.buildPlatform bootPkgs.ghc; 843 }; 844 845 meta = { 846 homepage = "http://haskell.org/ghc"; 847 description = "Glasgow Haskell Compiler"; 848 maintainers = with lib.maintainers; [ 849 guibou 850 ]; 851 teams = [ lib.teams.haskell ]; 852 timeout = 24 * 3600; 853 platforms = lib.platforms.all; 854 inherit (bootPkgs.ghc.meta) license; 855 }; 856 857 dontStrip = targetPlatform.useAndroidPrebuilt || targetPlatform.isWasm; 858 } 859 // lib.optionalAttrs targetPlatform.useAndroidPrebuilt { 860 dontPatchELF = true; 861 noAuditTmpdir = true; 862 } 863)