summary refs log tree commit diff
path: root/pkgs/development/compilers/ghc/common-hadrian.nix
diff options
context:
space:
mode:
authorsternenseemann <sternenseemann@systemli.org>2023-01-03 23:38:37 +0100
committersternenseemann <sternenseemann@systemli.org>2023-01-04 00:02:29 +0100
commit6392c21c1fefd50d9dda8bec70bcbbf01622f769 (patch)
tree8f074b3105ce356cb34dcdb313ef1e80d6fb2cbd /pkgs/development/compilers/ghc/common-hadrian.nix
parentb711b52d159d9c18e0cc3a839f21a1061ddc5b3e (diff)
downloadnixpkgs-6392c21c1fefd50d9dda8bec70bcbbf01622f769.tar
nixpkgs-6392c21c1fefd50d9dda8bec70bcbbf01622f769.tar.gz
nixpkgs-6392c21c1fefd50d9dda8bec70bcbbf01622f769.tar.bz2
nixpkgs-6392c21c1fefd50d9dda8bec70bcbbf01622f769.tar.lz
nixpkgs-6392c21c1fefd50d9dda8bec70bcbbf01622f769.tar.xz
nixpkgs-6392c21c1fefd50d9dda8bec70bcbbf01622f769.tar.zst
nixpkgs-6392c21c1fefd50d9dda8bec70bcbbf01622f769.zip
haskell.compiler.ghcHEAD: allow building the JavaScript backend
This is now possible by building a cross compiler for js-unknown-ghjs
using `pkgsCross.ghcjs.buildPackages.haskell.compiler.ghcHEAD`.

To allow this, the following things needed to be done:

* Disable dependencies that wouldn't work:

  - Don't pull in ncurses for terminfo
  - Don't pull in libffi
  - Don't pull in libiconv
  - Don't enable the LLVM backend
  - Enable gmp-less native-bignum backend

* Use emscripten instead of a C compiler. The way this works is inspired
  by emscriptenPackages, but avoids the following flaws:

  - Instead of using a custom configurePhase, just set
    `configureScript = "emconfigure ./configure";` which is much simpler.

  - Create writable EM_CACHE before configuring, as configure scripts
    want to compile test programs.

  Additionally, we need to disable the targetCC check, as it is not
  applicable with emscripten which never appears as part of stdenv.

* Use generic $configureScript in installPhase to be able to work with
  our emconfigure trick.

Note that the corresponding Haskell package set does not work yet. Cabal
doesn't seem to like GHC 9.7 yet and the generic-builder is clueless
about the JS backend.
Diffstat (limited to 'pkgs/development/compilers/ghc/common-hadrian.nix')
-rw-r--r--pkgs/development/compilers/ghc/common-hadrian.nix33
1 files changed, 25 insertions, 8 deletions
diff --git a/pkgs/development/compilers/ghc/common-hadrian.nix b/pkgs/development/compilers/ghc/common-hadrian.nix
index 00f08c9a802..15073bfec10 100644
--- a/pkgs/development/compilers/ghc/common-hadrian.nix
+++ b/pkgs/development/compilers/ghc/common-hadrian.nix
@@ -39,7 +39,8 @@
 , useLLVM ? !(stdenv.targetPlatform.isx86
               || stdenv.targetPlatform.isPower
               || stdenv.targetPlatform.isSparc
-              || (stdenv.targetPlatform.isAarch64 && stdenv.targetPlatform.isDarwin))
+              || (stdenv.targetPlatform.isAarch64 && stdenv.targetPlatform.isDarwin)
+              || stdenv.targetPlatform.isGhcjs)
 , # LLVM is conceptually a run-time-only depedendency, but for
   # non-x86, we need LLVM to bootstrap later stages, so it becomes a
   # build-time dependency too.
@@ -50,6 +51,7 @@
   # bignum backend instead of the faster but GPLed gmp backend.
   enableNativeBignum ? !(lib.meta.availableOn stdenv.hostPlatform gmp
                          && lib.meta.availableOn stdenv.targetPlatform gmp)
+                       || stdenv.targetPlatform.isGhcjs
 , gmp
 
 , # If enabled, use -fPIC when compiling static libs.
@@ -63,7 +65,8 @@
   enableShared ? with stdenv.targetPlatform; !isWindows && !useiOSPrebuilt && !isStatic
 
 , # Whether to build terminfo.
-  enableTerminfo ? !stdenv.targetPlatform.isWindows
+  enableTerminfo ? !(stdenv.targetPlatform.isWindows
+                     || stdenv.targetPlatform.isGhcjs)
 
 , # Libdw.c only supports x86_64, i686 and s390x as of 2022-08-04
   enableDwarf ? (stdenv.targetPlatform.isx86 ||
@@ -196,17 +199,19 @@ let
 
   # Splicer will pull out correct variations
   libDeps = platform: lib.optional enableTerminfo ncurses
-    ++ [libffi]
+    ++ lib.optionals (!targetPlatform.isGhcjs) [libffi]
     # Bindist configure script fails w/o elfutils in linker search path
     # https://gitlab.haskell.org/ghc/ghc/-/issues/22081
     ++ lib.optional enableDwarf elfutils
     ++ lib.optional (!enableNativeBignum) gmp
-    ++ lib.optional (platform.libc != "glibc" && !targetPlatform.isWindows) libiconv;
+    ++ lib.optional (platform.libc != "glibc" && !targetPlatform.isWindows && !targetPlatform.isGhcjs) libiconv;
 
   # TODO(@sternenseemann): is buildTarget LLVM unnecessary?
   # GHC doesn't seem to have {LLC,OPT}_HOST
   toolsForTarget = [
-    pkgsBuildTarget.targetPackages.stdenv.cc
+    (if targetPlatform.isGhcjs
+     then pkgsBuildTarget.emscripten
+     else pkgsBuildTarget.targetPackages.stdenv.cc)
   ] ++ lib.optional useLLVM buildTargetLlvmPackages.llvm;
 
   targetCC = builtins.head toolsForTarget;
@@ -246,7 +251,7 @@ in
 # C compiler, bintools and LLVM are used at build time, but will also leak into
 # the resulting GHC's settings file and used at runtime. This means that we are
 # currently only able to build GHC if hostPlatform == buildPlatform.
-assert targetCC == pkgsHostTarget.targetPackages.stdenv.cc;
+assert !targetPlatform.isGhcjs -> targetCC == pkgsHostTarget.targetPackages.stdenv.cc;
 assert buildTargetLlvmPackages.llvm == llvmPackages.llvm;
 assert stdenv.targetPlatform.isDarwin -> buildTargetLlvmPackages.clang == llvmPackages.clang;
 
@@ -329,6 +334,13 @@ stdenv.mkDerivation ({
                     '*-android*|*-gnueabi*|*-musleabi*)'
       done
   ''
+  # Need to make writable EM_CACHE for emscripten
+  # https://gitlab.haskell.org/ghc/ghc/-/wikis/javascript-backend#configure-fails-with-sub-word-sized-atomic-operations-not-available
+  + lib.optionalString targetPlatform.isGhcjs ''
+    export EM_CACHE="$(mktemp -d emcache.XXXXXXXXXX)"
+    cp -Lr ${targetCC /* == emscripten */}/share/emscripten/cache/* "$EM_CACHE/"
+    chmod u+rwX -R "$EM_CACHE"
+  ''
   # Create bash array hadrianFlagsArray for use in buildPhase. Do it in
   # preConfigure, so overrideAttrs can be used to modify it effectively.
   # hadrianSettings are passed via the command line so they are more visible
@@ -340,6 +352,8 @@ stdenv.mkDerivation ({
     )
   '';
 
+  ${if targetPlatform.isGhcjs then "configureScript" else null} = "emconfigure ./configure";
+
   # TODO(@Ericson2314): Always pass "--target" and always prefix.
   configurePlatforms = [ "build" "host" ]
     ++ lib.optional (targetPlatform != hostPlatform) "target";
@@ -348,7 +362,7 @@ stdenv.mkDerivation ({
   configureFlags = [
     "--datadir=$doc/share/doc/ghc"
     "--with-curses-includes=${ncurses.dev}/include" "--with-curses-libraries=${ncurses.out}/lib"
-  ] ++ lib.optionals (libffi != null) [
+  ] ++ lib.optionals (libffi != null && !targetPlatform.isGhcjs) [
     "--with-system-libffi"
     "--with-ffi-includes=${targetPackages.libffi.dev}/include"
     "--with-ffi-libraries=${targetPackages.libffi.out}/lib"
@@ -387,6 +401,9 @@ stdenv.mkDerivation ({
     autoSignDarwinBinariesHook
   ] ++ lib.optionals enableDocs [
     sphinx
+  ] ++ lib.optionals targetPlatform.isGhcjs [
+    # emscripten itself is added via depBuildTarget / targetCC
+    python3
   ];
 
   # For building runtime libs
@@ -445,7 +462,7 @@ stdenv.mkDerivation ({
   preInstall = ''
     pushd _build/bindist/*
 
-    ./configure $configureFlags "''${configureFlagsArray[@]}"
+    $configureScript $configureFlags "''${configureFlagsArray[@]}"
   '';
 
   postInstall = ''