@@ -20,7 +20,8 @@ let self =
20
20
, # GHC can be built with system libffi or a bundled one.
21
21
libffi ? null
22
22
23
- , useLLVM ? ! stdenv . targetPlatform . isx86
23
+ , # we don't need LLVM for x86, aarch64, or ghcjs
24
+ useLLVM ? with stdenv . targetPlatform ; ! ( isx86 || isAarch64 || isGhcjs )
24
25
, # LLVM is conceptually a run-time-only dependency, but for
25
26
# non-x86, we need LLVM to bootstrap later stages, so it becomes a
26
27
# build-time dependency too.
121
122
122
123
# TODO(@Ericson2314) Make unconditional
123
124
targetPrefix = lib . optionalString
124
- ( targetPlatform != hostPlatform )
125
- "${ targetPlatform . config } -" ;
125
+ ( targetPlatform != hostPlatform ) (
126
+ if useHadrian && targetPlatform . isGhcjs
127
+ then "javascript-unknown-ghcjs-"
128
+ else "${ targetPlatform . config } -" ) ;
126
129
127
130
buildMK = ''
128
131
BuildFlavour = ${ ghcFlavour }
@@ -177,13 +180,13 @@ let
177
180
# `--with` flags for libraries needed for RTS linker
178
181
configureFlags = [
179
182
"--datadir=$doc/share/doc/ghc"
180
- "--with-curses-includes=${ targetPackages . ncurses . dev } /include" "--with-curses-libraries=${ targetPackages . ncurses . out } /lib"
181
- ] ++ lib . optionals ( targetLibffi != null ) [ "--with-system-libffi" "--with-ffi-includes=${ targetLibffi . dev } /include" "--with-ffi-libraries=${ targetLibffi . out } /lib"
182
- ] ++ lib . optionals ( ! enableIntegerSimple ) [
183
+ ] ++ lib . optionals ( ! targetPlatform . isGhcjs ) [ "--with-curses-includes=${ targetPackages . ncurses . dev } /include" "--with-curses-libraries=${ targetPackages . ncurses . out } /lib"
184
+ ] ++ lib . optionals ( targetLibffi != null && ! targetPlatform . isGhcjs ) [ "--with-system-libffi" "--with-ffi-includes=${ targetLibffi . dev } /include" "--with-ffi-libraries=${ targetLibffi . out } /lib"
185
+ ] ++ lib . optionals ( ! enableIntegerSimple && ! targetPlatform . isGhcjs ) [
183
186
"--with-gmp-includes=${ targetGmp . dev } /include" "--with-gmp-libraries=${ targetGmp . out } /lib"
184
187
] ++ lib . optionals ( targetPlatform == hostPlatform && hostPlatform . libc != "glibc" && ! targetPlatform . isWindows ) [
185
188
"--with-iconv-includes=${ libiconv } /include" "--with-iconv-libraries=${ libiconv } /lib"
186
- ] ++ lib . optionals ( targetPlatform != hostPlatform ) [
189
+ ] ++ lib . optionals ( targetPlatform != hostPlatform && ! targetPlatform . isGhcjs ) [
187
190
"--with-iconv-includes=${ targetIconv } /include" "--with-iconv-libraries=${ targetIconv } /lib"
188
191
] ++ lib . optionals ( targetPlatform != hostPlatform ) [
189
192
"--enable-bootstrap-with-devel-snapshot"
@@ -198,29 +201,35 @@ let
198
201
"--enable-dwarf-unwind"
199
202
"--with-libdw-includes=${ lib . getDev elfutils } /include"
200
203
"--with-libdw-libraries=${ lib . getLib elfutils } /lib"
201
- ] ;
204
+ ] ++ lib . optional ( targetPlatform . isGhcjs ) "--target=javascript-unknown-ghcjs" ; # TODO use configurePlatforms once tripple is updated in nixpkgs
202
205
203
206
# Splicer will pull out correct variations
204
- libDeps = platform : lib . optional enableTerminfo [ targetPackages . ncurses targetPackages . ncurses . dev ]
205
- ++ [ targetLibffi ]
206
- ++ lib . optional ( ! enableIntegerSimple ) gmp
207
+ libDeps = platform : lib . optional ( enableTerminfo && ! targetPlatform . isGhcjs ) [ targetPackages . ncurses targetPackages . ncurses . dev ]
208
+ ++ lib . optional ( ! targetPlatform . isGhcjs ) targetLibffi
209
+ ++ lib . optional ( ! enableIntegerSimple && ! targetPlatform . isGhcjs ) gmp
207
210
++ lib . optional ( platform . libc != "glibc" && ! targetPlatform . isWindows ) libiconv
208
211
++ lib . optional ( enableNUMA && platform . isLinux && ! platform . isAarch32 && ! platform . isAndroid ) numactl
209
212
# Even with terminfo disabled some older ghc cross arm and windows compilers do not build unless `ncurses` is found and they seem to want the buildPlatform version
210
213
++ lib . optional ( ! enableTerminfo && haskell-nix . haskellLib . isCrossTarget && ( stdenv . targetPlatform . isAarch64 || stdenv . targetPlatform . isWindows ) && builtins . compareVersions ghc-version "8.10" < 0 ) ncurses . dev
211
214
++ lib . optional enableDWARF ( lib . getLib elfutils ) ;
212
215
213
216
toolsForTarget =
214
- if hostPlatform == buildPlatform then
215
- [ targetPackages . stdenv . cc ] ++ lib . optional useLLVM llvmPackages . llvm
217
+ if targetPlatform . isGhcjs
218
+ then [ buildPackages . emscripten ]
219
+ else if hostPlatform == buildPlatform
220
+ then [ targetPackages . stdenv . cc ] ++ lib . optional useLLVM llvmPackages . llvm
216
221
else assert targetPlatform == hostPlatform ; # build != host == target
217
222
[ stdenv . cc ] ++ lib . optional useLLVM buildLlvmPackages . llvm ;
218
223
219
224
targetCC = builtins . head toolsForTarget ;
220
225
221
226
useHadrian = builtins . compareVersions ghc-version "9.4" >= 0 ;
222
227
# Indicates if we are installing by copying the hadrian stage1 output
223
- installStage1 = useHadrian && ( haskell-nix . haskellLib . isCrossTarget || targetPlatform . isMusl ) ;
228
+ # I think we want to _always_ just install stage1. For now let's do this
229
+ # for musl only; but I'd like to stay far away from the unnecessary
230
+ # bindist logic as we can. It's slow, and buggy, and doesn't provide any
231
+ # value for us.
232
+ installStage1 = useHadrian && ( haskell-nix . haskellLib . isCrossTarget || stdenv . targetPlatform . isMusl ) ;
224
233
225
234
inherit ( ( buildPackages . haskell-nix . cabalProject {
226
235
compiler-nix-name = "ghc8107" ;
248
257
# For build flavours and flavour transformers
249
258
# see https://gitlab.haskell.org/ghc/ghc/blob/master/hadrian/doc/flavours.md
250
259
hadrianArgs = "--flavour=${
251
- " default"
260
+ ( if targetPlatform . isGhcjs then "quick" else " default")
252
261
+ lib . optionalString ( ! enableShared ) "+no_dynamic_ghc"
253
262
+ lib . optionalString useLLVM "+llvm"
263
+ + lib . optionalString enableDWARF "+debug_info"
264
+ + lib . optionalString targetPlatform . isGhcjs "+native_bignum+no_profiled_libs"
254
265
} --docs=no-sphinx -j --verbose" ;
255
266
256
267
# When installation is done by copying the stage1 output the directory layout
@@ -310,10 +321,15 @@ stdenv.mkDerivation (rec {
310
321
for env in $(env | grep '^TARGET_' | sed -E 's|\+?=.*||'); do
311
322
export "'' ${env#TARGET_}='' ${!env}"
312
323
done
324
+ '' + lib . optionalString ( targetPlatform . isGhcjs ) ''
325
+ export CC="${ targetCC } /bin/emcc"
326
+ export CXX="${ targetCC } /bin/em++"
327
+ export LD="${ targetCC } /bin/emcc"
328
+ export EM_CACHE=$(mktemp -d)
313
329
''
314
330
# GHC is a bit confused on its cross terminology, as these would normally be
315
331
# the *host* tools.
316
- + ''
332
+ + lib . optionalString ( ! targetPlatform . isGhcjs ) ( ''
317
333
export CC="${ targetCC } /bin/${ targetCC . targetPrefix } cc"
318
334
export CXX="${ targetCC } /bin/${ targetCC . targetPrefix } c++"
319
335
''
@@ -329,7 +345,7 @@ stdenv.mkDerivation (rec {
329
345
'' + lib . optionalString ( stdenv . targetPlatform . linker == "cctools" ) ''
330
346
export OTOOL="${ targetCC . bintools . bintools } /bin/${ targetCC . bintools . targetPrefix } otool"
331
347
export INSTALL_NAME_TOOL="${ bintoolsFor . install_name_tool } /bin/${ bintoolsFor . install_name_tool . targetPrefix } install_name_tool"
332
- '' + lib . optionalString ( targetPlatform == hostPlatform && useLdGold )
348
+ '' ) + lib . optionalString ( targetPlatform == hostPlatform && useLdGold )
333
349
# set LD explicitly if we want gold even if we aren't cross compiling
334
350
''
335
351
export LD="${ targetCC . bintools } /bin/ld.gold"
@@ -376,7 +392,7 @@ stdenv.mkDerivation (rec {
376
392
./boot
377
393
'' ;
378
394
379
- configurePlatforms = [ "build" "host" "target" ] ;
395
+ configurePlatforms = [ "build" "host" ] ++ lib . optional ( ! targetPlatform . isGhcjs ) "target" ;
380
396
381
397
enableParallelBuilding = true ;
382
398
postPatch = "patchShebangs ." ;
@@ -399,8 +415,8 @@ stdenv.mkDerivation (rec {
399
415
400
416
buildInputs = [ perl bash ] ++ ( libDeps hostPlatform ) ;
401
417
402
- depsTargetTarget = map lib . getDev ( libDeps targetPlatform ) ;
403
- depsTargetTargetPropagated = map ( lib . getOutput "out" ) ( libDeps targetPlatform ) ;
418
+ depsTargetTarget = lib . optionals ( ! targetPlatform . isGhcjs ) ( map lib . getDev ( libDeps targetPlatform ) ) ;
419
+ depsTargetTargetPropagated = lib . optionals ( ! targetPlatform . isGhcjs ) ( map ( lib . getOutput "out" ) ( libDeps targetPlatform ) ) ;
404
420
405
421
# required, because otherwise all symbols from HSffi.o are stripped, and
406
422
# that in turn causes GHCi to abort
@@ -438,7 +454,7 @@ stdenv.mkDerivation (rec {
438
454
# The ghcprog fixup is for musl (where runhaskell script just needs to point to the correct
439
455
# ghc program to work).
440
456
sed -i \
441
- -e '2i export PATH="$PATH:${ lib . makeBinPath [ targetPackages . stdenv . cc . bintools coreutils ] } "' \
457
+ -e '2i export PATH="$PATH:${ lib . makeBinPath ( lib . optionals ( ! targetPlatform . isGhcjs ) [ targetPackages . stdenv . cc . bintools coreutils ] ) } "' \
442
458
-e 's/ghcprog="ghc-/ghcprog="${ targetPrefix } ghc-/' \
443
459
$i
444
460
done
@@ -586,6 +602,10 @@ stdenv.mkDerivation (rec {
586
602
--replace 'dynamic-library-dirs:' 'dynamic-library-dirs: ${ libcxx } /lib ${ libcxxabi } /lib'
587
603
find . -name 'system*.conf*'
588
604
cat mk/system-cxx-std-lib-1.0.conf
605
+ '' + lib . optionalString ( installStage1 && stdenv . targetPlatform . isMusl ) ''
606
+ substituteInPlace hadrian/cfg/system.config \
607
+ --replace 'cross-compiling = YES' \
608
+ 'cross-compiling = NO'
589
609
'' ;
590
610
} ) ;
591
611
@@ -651,13 +671,24 @@ stdenv.mkDerivation (rec {
651
671
--replace 'dynamic-library-dirs:' 'dynamic-library-dirs: ${ libcxx } /lib ${ libcxxabi } /lib'
652
672
find . -name 'system*.conf*'
653
673
cat mk/system-cxx-std-lib-1.0.conf
674
+ '' + lib . optionalString ( installStage1 && stdenv . targetPlatform . isMusl ) ''
675
+ substituteInPlace hadrian/cfg/system.config \
676
+ --replace 'cross-compiling = YES' \
677
+ 'cross-compiling = NO'
654
678
'' ;
655
679
buildPhase = ''
656
680
${ hadrian } /bin/hadrian ${ hadrianArgs }
657
- '' + lib . optionalString installStage1 ''
681
+ '' + lib . optionalString ( installStage1 && ! stdenv . targetPlatform . isGhcjs ) ''
658
682
${ hadrian } /bin/hadrian ${ hadrianArgs } stage1:lib:libiserv
659
683
'' + lib . optionalString targetPlatform . isMusl ''
660
684
${ hadrian } /bin/hadrian ${ hadrianArgs } stage1:lib:terminfo
685
+ '' + lib . optionalString ( installStage1 && ! haskell-nix . haskellLib . isCrossTarget ) ''
686
+ ${ hadrian } /bin/hadrian ${ hadrianArgs } stage2:exe:iserv
687
+ pushd _build/stage1/bin
688
+ for exe in *; do
689
+ mv $exe ${ targetPrefix } $exe
690
+ done
691
+ popd
661
692
'' ;
662
693
663
694
# Hadrian's installation only works for native compilers, and is broken for cross compilers.
0 commit comments