RISC-V/GHC: Difference between revisions

From NixOS Wiki
0x4A6F (talk | contribs)
Created page with "{{RISC-V/breadcrumb}} <span id="ghc"></span> === GHC === <code>cannot bootstrap GHC on this platform ('riscv64-linux' with libc 'defaultLibc')</code> see: * https://gitlab.haskell.org/ghc/ghc/-/issues/23179 * https://gitlab.haskell.org/ghc/ghc/-/issues/16783 * https://gitlab.haskell.org/ghc/ghc/-/issues/14903 * https://gitlab.haskell.org/ghc/ghc/-/commit/31e265c1df948d1bcc82d08affe995fd1d1c1438 * '''https://gitlab.haskell.org/ghc/ghc/-/issues/23519''' ← we need this..."
 
Add link to sterni's GHC cross PR
 
(3 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{RISC-V/breadcrumb}}
{{RISC-V/breadcrumb}}
<span id="ghc"></span>
=== GHC ===


<code>cannot bootstrap GHC on this platform ('riscv64-linux' with libc 'defaultLibc')</code> see:
== Current status ==
* https://gitlab.haskell.org/ghc/ghc/-/issues/23179
* https://gitlab.haskell.org/ghc/ghc/-/issues/16783
* https://gitlab.haskell.org/ghc/ghc/-/issues/14903
* https://gitlab.haskell.org/ghc/ghc/-/commit/31e265c1df948d1bcc82d08affe995fd1d1c1438
* '''https://gitlab.haskell.org/ghc/ghc/-/issues/23519''' ← we need this one - https://gitlab.haskell.org/ghc/ghc/-/issues/23957


* ☐ nix-tree
<code>cannot bootstrap GHC on this platform ('riscv64-linux' with libc 'defaultLibc')</code>
* ☐ nixfmt
* ☐ hledger
* ☐ hledger-ui
* ☐ hledger-web
* ☐ exa
* ☐ pandoc
* does cross-compile though when building unregisterised


<span id="booting-ghc-via-cross-compilation"></span>
* [https://gitlab.haskell.org/ghc/ghc/-/issues/16783 Main issue]
==== Booting GHC via cross-compilation ====
* [https://gitlab.haskell.org/ghc/ghc/-/issues/23179 NCG]
* [https://gitlab.haskell.org/ghc/ghc/-/commit/31e265c1df948d1bcc82d08affe995fd1d1c1438 LLVM backend]
* '''[https://gitlab.haskell.org/ghc/ghc/-/issues/23519 Binary tarballs] (needed for bootstrap)'''
* [https://gitlab.haskell.org/ghc/ghc/-/issues/?label_name%5B%5D=RISC-V RISC-V Label]
 
Some popular affected packages are:
 
* nix-tree
* nixfmt
* hledger
* hledger-ui
* hledger-web
* exa
* pandoc
* nix-output-monitor
* xmonad
 
== Booting GHC via cross-compilation ==


On a platform where Nixpkgs supports compiling GHC (e.g. <code>x86_64-linux</code>):
On a platform where Nixpkgs supports compiling GHC (e.g. <code>x86_64-linux</code>):
Line 152: Line 155:
For newer GHCs, refer to the GHC documentation or the Nixpkgs source to find which version of GHC and LLVM is needed for compilation.
For newer GHCs, refer to the GHC documentation or the Nixpkgs source to find which version of GHC and LLVM is needed for compilation.


GHC &gt;=9.2 is unable to boot any version of GHC when cross-compiled. GHC &gt;=9.6 cannot be cross-compiled at all due to issues with Hadrian. Newer GHCs can be booted using natively compiled versions of GHC instead.
GHC &gt;=9.2 is unable to boot 9.2 and 9.4. GHC &gt;=9.6 cannot be cross-compiled at all due to issues with Hadrian. Newer GHCs can be booted using natively compiled versions of GHC instead.


See https://github.com/AlexandreTunstall/nixos-riscv for an example of a pure flake that uses this trick to compile Haskell programs for RISC-V.
See https://github.com/AlexandreTunstall/nixos-riscv for an example of a pure flake that uses this trick to compile Haskell programs for RISC-V.
== See also ==
* [https://github.com/NixOS/nixpkgs/pull/243619 Nixpkgs PR 243619 (fix cross-built native GHC)]
* [https://github.com/NixOS/nixpkgs/pull/305392 Nixpkgs PR 305392 (fix cross-built native GHC, version 2)]

Latest revision as of 12:59, 24 April 2024

Current status

cannot bootstrap GHC on this platform ('riscv64-linux' with libc 'defaultLibc')

Some popular affected packages are:

  • nix-tree
  • nixfmt
  • hledger
  • hledger-ui
  • hledger-web
  • exa
  • pandoc
  • nix-output-monitor
  • xmonad

Booting GHC via cross-compilation

On a platform where Nixpkgs supports compiling GHC (e.g. x86_64-linux):

nix copy --to ssh://root@$riscv_host --no-check-sigs \
  'github:alexandretunstall/nixpkgs/ghc-cross-usable#pkgsCross.riscv64.haskell.compiler.integer-simple.ghc8107'

(You don’t need to SSH as root if you copy it via a trusted user.)

Then you’ll want to pin the copied path so that the GC never deletes it. On the RISC-V host:

nix-store --realise --indirect --add-root $root_path $cross_ghc_path

Finally, create the GHC configuration on the RISC-V host so that native builds use the cross-compiled GHC.

The configuration below assumes that there is a symbolic link to the previously built GHC at ../boot/ghc-8.10.7.

The configuration should work with any modern version of Nixpkgs.

{ config, lib, pkgs, ... }:

let
  mkBootCompiler = { version, outPath, llvmPackages }: let
    passthru = {
      targetPrefix = "";
      enableShared = false;
      hasHaddock = false;
      hasThreadedRuntime = false;

      inherit llvmPackages;

      haskellCompilerName = "ghc-${version}";
    };
  in passthru // {
    inherit version outPath passthru;

    meta = {
      license = lib.licenses.bsd3;
      platforms = [ "riscv64-linux" ];
    };
  };

  mkBootPackages = { base, ghc }: let
    buildHaskellPackages = base.override (old: {
      inherit buildHaskellPackages ghc;

      overrides = bootOverrides;
    });
  in buildHaskellPackages;

  hsLib = pkgs.haskell.lib.compose;

  # Overrides that are needed to boot a native GHC
  bootOverrides = self: super: {
    mkDerivation = args: super.mkDerivation ({
      enableLibraryProfiling = false;
    } // args);

    alex = hsLib.dontCheck super.alex;
    data-array-byte = hsLib.dontCheck super.data-array-byte;
    doctest = hsLib.dontCheck super.doctest;
    hashable = hsLib.dontCheck super.hashable;
    optparse-applicative = hsLib.dontCheck super.optparse-applicative;
    QuickCheck = hsLib.dontCheck super.QuickCheck;
    temporary = hsLib.dontCheck super.temporary;
    vector = hsLib.dontCheck super.vector;
  };

  # If a package fails to build, try disabling checks here.
  # Since RISC-V has to use an unregisterised GHC, many test suites fail.
  unregOverrides = self: super: {
    # Example: lens fails without this override
    lens = hsLib.dontCheck super.lens;
  };

in {
  nixpkgs.overlays = [
    (self: super: {
      # If you need to change the default GHC, uncomment these lines.
      # Using the Nixpkgs default is better as it can build more packages than
      # other versions of GHC.
      #ghc = self.haskell.compiler.ghc94;
      #haskellPackages = self.haskell.packages.ghc94;

      haskell = super.haskell // {
        compiler = {
          ghc8107Boot = mkBootCompiler {
            version = "8.10.7";
            outPath = builtins.storePath ../boot/ghc-8.10.7;
            llvmPackages = pkgs.llvmPackages_12;
          };

          ghc928 = (super.haskell.compiler.ghc928.override (old: {
            bootPkgs = self.pkgsBuildBuild.haskell.packages.ghc8107Boot;
          })).overrideAttrs ({ configureFlags ? [], ... }: {
            # Registerised RV64 produces programs that segfault
            configureFlags = configureFlags ++ [ "--enable-unregisterised" ];
          });
          
          ghc92 = self.haskell.compiler.ghc928;
          
          ghc964 = (super.haskell.compiler.ghc964.override (old: {
            bootPkgs = self.pkgsBuildBuild.haskell.packages.ghc928;
          }).overrideAttrs ({ configureFlags ? [], ... }: {
            configureFlags = configureFlags ++ [ "--enable-unregisterised" ];
          });
          
          ghc96 = self.haskell.compiler.ghc964;
        };

        packages = {
          ghc928 = super.haskell.packages.ghc928.override (old: {
            overrides = unregOverrides;
          });
          
          ghc92 = self.haskell.packages.ghc928;
          
          ghc964 = super.haskell.packages.ghc964.override (old: {
            overrides = unregOverrides;
          });
          
          ghc96 = self.haskell.packages.ghc96;

          ghc8107Boot = mkBootPackages {
            base = super.haskell.packages.ghc8107;
            ghc = self.pkgsBuildHost.haskell.compiler.ghc8107Boot;
          };
        };
      };
    })
  ];
}

For newer GHCs, refer to the GHC documentation or the Nixpkgs source to find which version of GHC and LLVM is needed for compilation.

GHC >=9.2 is unable to boot 9.2 and 9.4. GHC >=9.6 cannot be cross-compiled at all due to issues with Hadrian. Newer GHCs can be booted using natively compiled versions of GHC instead.

See https://github.com/AlexandreTunstall/nixos-riscv for an example of a pure flake that uses this trick to compile Haskell programs for RISC-V.

See also