diff --git a/builder/comp-builder.nix b/builder/comp-builder.nix index d9c479ac2e..4f6eabcbf7 100644 --- a/builder/comp-builder.nix +++ b/builder/comp-builder.nix @@ -1,13 +1,6 @@ { stdenv, buildPackages, ghc, lib, gobject-introspection ? null, haskellLib, makeConfigFiles, ghcForComponent, hsPkgs, runCommand, libffi, gmp, zlib, ncurses, numactl, nodejs }: -let - # These are here to avoid multiple calls to override - gmpStatic = gmp.override { withStatic = true; }; - zlibStatic = zlib.static; - ncursesStatic = ncurses.override { enableStatic = true; }; - numactlStatic = numactl.overrideAttrs (_: { configureFlags = "--enable-static"; }); -in lib.makeOverridable ( -let self = +let self = { componentId , component , package @@ -40,7 +33,10 @@ let self = , dontStrip ? component.dontStrip , enableStatic ? component.enableStatic -, enableShared ? component.enableShared && !haskellLib.isCrossHost +, enableShared ? ghc.enableShared && component.enableShared && !haskellLib.isCrossHost + # on x86 we'll use shared libraries, even with musl m( + # ghc's internal linker seems to be broken on x86. + && !(stdenv.hostPlatform.isMusl && !stdenv.hostPlatform.isx86) , enableDeadCodeElimination ? component.enableDeadCodeElimination # Options for Haddock generation @@ -126,10 +122,6 @@ let "--disable-executable-dynamic" "--ghc-option=-optl=-pthread" "--ghc-option=-optl=-static" - "--ghc-option=-optl=-L${gmpStatic}/lib" - "--ghc-option=-optl=-L${zlibStatic}/lib" - "--ghc-option=-optl=-L${ncursesStatic}/lib" - "--ghc-option=-optl=-L${numactlStatic}/lib" ] ++ lib.optional enableSeparateDataOutput "--datadir=$data/share/${ghc.name}" ++ lib.optional doHaddock' "--docdir=${docdir "$doc"}" ++ lib.optional (enableLibraryProfiling || enableExecutableProfiling) "--profiling-detail=${profilingDetail}" diff --git a/compiler/ghc/default.nix b/compiler/ghc/default.nix index 0ad5171759..5f5f1e1e56 100644 --- a/compiler/ghc/default.nix +++ b/compiler/ghc/default.nix @@ -107,6 +107,11 @@ let '' + stdenv.lib.optionalString (!enableTerminfo) '' WITH_TERMINFO=NO '' + # musl doesn't have a system-linker. Only on x86, and on x86 we need it, as + # our elf linker for x86_64 is broken. + + stdenv.lib.optionalString (targetPlatform.isMusl && !targetPlatform.isx86) '' + compiler_CONFIGURE_OPTS += --flags=-dynamic-system-linker + '' # While split sections are now enabled by default in ghc 8.8 for windows, # the seem to lead to `too many sections` errors when building base for # profiling. @@ -284,15 +289,15 @@ stdenv.mkDerivation (rec { if [[ ! -f "$out/bin/${targetPrefix}ghc-pkg" ]]; then echo "ERROR: Missing file $out/bin/${targetPrefix}ghc-pkg" exit 0 - fi + fi if [[ ! -d "$out/lib/${targetPrefix}ghc-${version}" ]]; then echo "ERROR: Missing directory $out/lib/${targetPrefix}ghc-${version}" exit 0 - fi + fi if (( $(ls -1 "$out/lib/${targetPrefix}ghc-${version}" | wc -l) < 30 )); then echo "ERROR: Expected more files in $out/lib/${targetPrefix}ghc-${version}" exit 0 - fi + fi ''; passthru = { diff --git a/overlays/bootstrap.nix b/overlays/bootstrap.nix index a86707cde4..27debf4b30 100644 --- a/overlays/bootstrap.nix +++ b/overlays/bootstrap.nix @@ -141,6 +141,7 @@ in { # hadrian one. ++ fromUntil "8.8" "8.12" ./patches/ghc/bec76733b818b0489ffea0834ab6b1560207577c.patch ++ fromUntil "8.8" "8.12" ./patches/ghc/67738db10010fd28a8e997b5c8f83ea591b88a0e.patch + ++ final.lib.optional (versionAtLeast "8.6.4" && versionLessThan "8.8") ./patches/ghc/ghc-no-system-linker.patch ; in ({ ghc844 = final.callPackage ../compiler/ghc { diff --git a/overlays/hackage-quirks.nix b/overlays/hackage-quirks.nix index af54d5380b..257e0b2b1d 100644 --- a/overlays/hackage-quirks.nix +++ b/overlays/hackage-quirks.nix @@ -44,12 +44,6 @@ in { haskell-nix = prev.haskell-nix // { sha256 = "0jcpja4s4cylmg9rddyakb1p1fb4l41ffwmy0njpb1dxc5z3v618"; }; }) - # Musl needs static zlib - (lib.optionalAttrs final.stdenv.hostPlatform.isMusl { - packages.pandoc.components.exes.pandoc.configureFlags = [ - "--ghc-option=-optl=-L${final.zlib.static}/lib" - ]; - }) ]; }; diff --git a/overlays/musl.nix b/overlays/musl.nix index d1d6608083..bcb3d9032f 100644 --- a/overlays/musl.nix +++ b/overlays/musl.nix @@ -11,6 +11,19 @@ final: prev: prev.lib.optionalAttrs prev.stdenv.hostPlatform.isMusl ({ # Prevent pkgsMusl.pkgsStatic chain busybox-sandbox-shell = prev.busybox-sandbox-shell.override { inherit (final) busybox; }; + # we don't want the static output to be split. That just + # messes with the z -> libz mapping. We can't have a conditonal + # z -> libz / z -> libz.static mapping without threading the + # package configuration in. That seems a bit overkill. + zlib = prev.zlib.override { splitStaticOutput = false; }; + + # and a few more packages that need their static libs explicitly enabled + gmp = prev.gmp.override { withStatic = true; }; + ncurses = prev.ncurses.override { enableStatic = true; }; + libsodium = prev.libsodium.overrideAttrs (_: { dontDisableStatic = true; }); + + numactl = prev.numactl.overrideAttrs (_: { configureFlags = "--enable-static"; }); + # Fails on cross compile nix = prev.nix.overrideAttrs (_: { doInstallCheck = false; }); } // prev.lib.optionalAttrs (prev.lib.versionAtLeast prev.lib.trivial.release "20.03") { diff --git a/overlays/patches/ghc/ghc-no-system-linker.patch b/overlays/patches/ghc/ghc-no-system-linker.patch new file mode 100644 index 0000000000..ed82cd531a --- /dev/null +++ b/overlays/patches/ghc/ghc-no-system-linker.patch @@ -0,0 +1,78 @@ +diff --git a/compiler/ghc.cabal.in b/compiler/ghc.cabal.in +index 01628dcad1..209704d034 100644 +--- a/compiler/ghc.cabal.in ++++ b/compiler/ghc.cabal.in +@@ -45,6 +45,11 @@ Flag terminfo + Default: True + Manual: True + ++Flag dynamic-system-linker ++ Description: The system can load dynamic code. This is not the case for musl. ++ Default: True ++ Manual: False ++ + Library + Default-Language: Haskell2010 + Exposed: False +@@ -84,6 +89,9 @@ Library + CPP-Options: -DGHCI + Include-Dirs: ../rts/dist/build @FFIIncludeDir@ + ++ if flag(dynamic-system-linker) ++ CPP-Options: -DCAN_LOAD_DLL ++ + Other-Extensions: + BangPatterns + CPP +diff --git a/compiler/ghci/Linker.hs b/compiler/ghci/Linker.hs +index 3b030be2d3..879c5c19ee 100644 +--- a/compiler/ghci/Linker.hs ++++ b/compiler/ghci/Linker.hs +@@ -1295,13 +1295,13 @@ linkPackage hsc_env pkg + + maybePutStr dflags + ("Loading package " ++ sourcePackageIdString pkg ++ " ... ") +- + -- See comments with partOfGHCi ++#if defined(CAN_LOAD_DLL) + when (packageName pkg `notElem` partOfGHCi) $ do + loadFrameworks hsc_env platform pkg + mapM_ (load_dyn hsc_env) + (known_dlls ++ map (mkSOName platform) dlls) +- ++#endif + -- After loading all the DLLs, we can load the static objects. + -- Ordering isn't important here, because we do one final link + -- step to resolve everything. +@@ -1382,10 +1382,15 @@ locateLib hsc_env is_hs lib_dirs gcc_dirs lib + -- O(n). Loading an import library is also O(n) so in general we prefer + -- shared libraries because they are simpler and faster. + -- +- = findDll user `orElse` ++ = ++#if defined(CAN_LOAD_DLL) ++ findDll user `orElse` ++#endif + tryImpLib user `orElse` ++#if defined(CAN_LOAD_DLL) + findDll gcc `orElse` + findSysDll `orElse` ++#endif + tryImpLib gcc `orElse` + findArchive `orElse` + tryGcc `orElse` +@@ -1452,7 +1457,13 @@ locateLib hsc_env is_hs lib_dirs gcc_dirs lib + full = dllpath $ search lib_so_name lib_dirs + gcc name = liftM (fmap Archive) $ search name lib_dirs + files = import_libs ++ arch_files +- in apply $ short : full : map gcc files ++ dlls = [short, full] ++ archives = map gcc files ++ in apply $ ++#if defined(CAN_LOAD_DLL) ++ dlls ++ ++#endif ++ archives + tryImpLib re = case os of + OSMinGW32 -> + let dirs' = if re == user then lib_dirs else gcc_dirs diff --git a/test/fully-static/default.nix b/test/fully-static/default.nix index b2d12d37e6..35f78096a9 100644 --- a/test/fully-static/default.nix +++ b/test/fully-static/default.nix @@ -17,32 +17,11 @@ let src = testSrc "fully-static"; pkg-def-extras = []; modules = [ - # Musl libc fully static build - (let - staticLibs = [ - zlib.static - (openssl.override { static = true; }).out - (libffi.overrideAttrs (oldAttrs: { - dontDisableStatic = true; - configureFlags = (oldAttrs.configureFlags or []) ++ [ - "--enable-static" - "--disable-shared" - ]; - })) - ] ++ optional gpl (gmp6.override { withStatic = true; }); - - withFullyStatic = { - configureFlags = - optionals stdenv.hostPlatform.isMusl (map (drv: "--ghc-option=-optl=-L${drv}/lib") staticLibs); - }; - in { + { # Select a non-GMP compiler, usually for software licensing reasons. ghc.package = mkIf (stdenv.hostPlatform.isMusl && !gpl) buildPackages.haskell-nix.compiler.integer-simple.${compiler}; - - # Add GHC flags and libraries for fully static build - packages.pandoc.components.exes.pandoc = withFullyStatic; - }) + } ]; }; packagesGmp = (project { gpl = true; }).hsPkgs;