From 1ccfd295aa4b568d57f54dd04879514295b323e5 Mon Sep 17 00:00:00 2001 From: Hamish Mackenzie Date: Tue, 2 Aug 2022 17:42:17 +1200 Subject: [PATCH] Support native bignum (including static builds) (#1569) Co-authored-by: Mikaela Allan Co-authored-by: Travis Whitaker --- compiler/ghc/default.nix | 26 ++++++++++++++++++++++++-- overlays/ghc.nix | 20 ++++++++++++-------- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/compiler/ghc/default.nix b/compiler/ghc/default.nix index 63cd40b6..a4ec35a2 100644 --- a/compiler/ghc/default.nix +++ b/compiler/ghc/default.nix @@ -31,6 +31,9 @@ let self = , # If enabled, GHC will be built with the GPL-free but slower integer-simple # library instead of the faster but GPLed integer-gmp library. enableIntegerSimple ? !(lib.any (lib.meta.platformMatch stdenv.hostPlatform) gmp.meta.platforms), gmp +, # If enabled, GHC will be built with the GPL-free native backend of the + # bignum library that is nearly as fast as GMP + enableNativeBignum ? !((lib.any (lib.meta.platformMatch stdenv.hostPlatform) gmp.meta.platforms) || enableIntegerSimple) , # If enabled, use -fPIC when compiling static libs. enableRelocatedStaticLibs ? stdenv.targetPlatform != stdenv.hostPlatform && !stdenv.targetPlatform.isAarch32 @@ -71,7 +74,11 @@ let self = , extra-passthru ? {} }@args: -assert !enableIntegerSimple -> gmp != null; +assert !(enableIntegerSimple || enableNativeBignum) -> gmp != null; + +# Early check to make sure only one of these is enabled +assert enableNativeBignum -> !enableIntegerSimple; +assert enableIntegerSimple -> !enableNativeBignum; let inherit (stdenv) buildPlatform hostPlatform targetPlatform; @@ -79,6 +86,17 @@ let inherit (bootPkgs) ghc; + ghcHasNativeBignum = builtins.compareVersions ghc-version "9.0" >= 0; + + bignumSpec = + assert ghcHasNativeBignum -> !enableIntegerSimple; + assert !ghcHasNativeBignum -> !enableNativeBignum; + if ghcHasNativeBignum then '' + BIGNUM_BACKEND = ${if enableNativeBignum then "native" else "gmp"} + '' else '' + INTEGER_LIBRARY = ${if enableIntegerSimple then "integer-simple" else "integer-gmp"} + ''; + # TODO check if this possible fix for segfaults works or not. targetLibffi = # on native platforms targetPlatform.{libffi, gmp} do not exist; thus fall back @@ -106,7 +124,7 @@ let include mk/flavours/\$(BuildFlavour).mk endif DYNAMIC_GHC_PROGRAMS = ${if enableShared then "YES" else "NO"} - INTEGER_LIBRARY = ${if enableIntegerSimple then "integer-simple" else "integer-gmp"} + '' + bignumSpec + '' EXTRA_HADDOCK_OPTS += --quickjump --hyperlinked-source '' + lib.optionalString (targetPlatform != hostPlatform) '' CrossCompilePrefix = ${targetPrefix} @@ -121,6 +139,10 @@ let '' + lib.optionalString enableRelocatedStaticLibs '' GhcLibHcOpts += -fPIC GhcRtsHcOpts += -fPIC + GhcRtsCcOpts += -fPIC + '' + lib.optionalString (enableRelocatedStaticLibs && targetPlatform.isx86_64 && !targetPlatform.isWindows) '' + GhcLibHcOpts += -fexternal-dynamic-refs + GhcRtsHcOpts += -fexternal-dynamic-refs '' + lib.optionalString enableDWARF '' GhcLibHcOpts += -g3 GhcRtsHcOpts += -g3 diff --git a/overlays/ghc.nix b/overlays/ghc.nix index 84656030..2ab335ba 100644 --- a/overlays/ghc.nix +++ b/overlays/ghc.nix @@ -1,9 +1,13 @@ final: prev: with prev; # sadly we need to patch GHC a bit. - let - ghcPkgOverrides = { - enableIntegerSimple = false; - }; + let + # The new implementation appeared in GHC 9.0 + hasNativeBignum = name: !lib.hasPrefix "ghc8" name; + + ghcPkgOverrides = name: { enableIntegerSimple = false; } // lib.optionalAttrs (hasNativeBignum name) { + enableNativeBignum = false; + }; + ghcDrvOverrides = drv: { hardeningDisable = (drv.hardeningDisable or []) ++ [ "stackprotector" "format" ] ++ lib.optionals prev.stdenv.hostPlatform.isAarch32 [ "pic" "pie" ]; }; @@ -20,13 +24,13 @@ final: prev: with prev; && !lib.hasPrefix "ghc82" name && !lib.hasPrefix "ghcjs" name && !lib.hasSuffix "Binary" name; - overrideCompiler = compiler: - ((compiler.override ghcPkgOverrides).overrideAttrs ghcDrvOverrides) // { - dwarf = overrideCompiler compiler.dwarf; + overrideCompiler = name: compiler: + ((compiler.override (ghcPkgOverrides name)).overrideAttrs ghcDrvOverrides) // { + dwarf = overrideCompiler name compiler.dwarf; }; in lib.recursiveUpdate prev.haskell-nix { - compiler = lib.mapAttrs (_name: overrideCompiler) + compiler = lib.mapAttrs overrideCompiler (lib.filterAttrs (name: _value: needsPatches name) prev.haskell-nix.compiler); }; }