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