From cb2b4ca700425a7270fa23039c77e888d74352fc Mon Sep 17 00:00:00 2001 From: Judah Jacobson Date: Wed, 3 May 2017 13:13:05 -0700 Subject: [PATCH] haskell: work around linker limits on Mac OS X Sierra. The Sierra linker added a limit on the number of paths that any one dynamic library (`*.dylib`) can reference. This causes problems when a Haskell library has many immediate dependencies (#22810). We follow a similar fix as GHC/Cabal/Stack: for each derivation, create a new directory with symlinks to all the dylibs of its immediate dependencies, and patch its package DB to reference that directory using the new `dynamic-library-dirs` field. Note that this change is a no-op for older versions of GHC, i.e., they will continue to fail on some packages as before. Also note that this change causes the bootstrapped versions of GHC to be recompiled, since they depend on `hscolour` which is built by `generic-builder.nix`. Tested by building the `stack` binary as described in #22810. --- .../haskell-modules/generic-builder.nix | 17 ++++++++++++++ .../haskell-modules/with-packages-wrapper.nix | 23 ++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/pkgs/development/haskell-modules/generic-builder.nix b/pkgs/development/haskell-modules/generic-builder.nix index f7d16a89df86f..5fcd76b51752e 100644 --- a/pkgs/development/haskell-modules/generic-builder.nix +++ b/pkgs/development/haskell-modules/generic-builder.nix @@ -227,6 +227,23 @@ stdenv.mkDerivation ({ configureFlags+=" --extra-lib-dirs=$p/lib" fi done + '' + (optionalString stdenv.isDarwin '' + # Work around a limit in the Mac OS X Sierra linker on the number of paths + # referenced by any one dynamic library: + # + # Create a local directory with symlinks of the *.dylib (Mac OS X shared + # libraries) from all the dependencies. + local dynamicLinksDir="$out/lib/links" + mkdir -p $dynamicLinksDir + local foundDylib=false + for d in $(grep dynamic-library-dirs $packageConfDir/*|awk '{print $2}'); do + ln -s $d/*.dylib $dynamicLinksDir + done + # Edit the local package DB to reference the links directory. + for f in $packageConfDir/*.conf; do + sed -i "s,dynamic-library-dirs: .*,dynamic-library-dirs: $dynamicLinksDir," $f + done + '') + '' ${ghcCommand}-pkg --${packageDbFlag}="$packageConfDir" recache runHook postSetupCompilerEnvironment diff --git a/pkgs/development/haskell-modules/with-packages-wrapper.nix b/pkgs/development/haskell-modules/with-packages-wrapper.nix index 15d66bbd6dc03..147a021ff5346 100644 --- a/pkgs/development/haskell-modules/with-packages-wrapper.nix +++ b/pkgs/development/haskell-modules/with-packages-wrapper.nix @@ -96,7 +96,28 @@ symlinkJoin { makeWrapper ${ghc}/bin/$prg $out/bin/$prg --add-flags "${packageDBFlag}=${packageCfgDir}" fi done - + '' + (lib.optionalString stdenv.isDarwin '' + # Work around a linker limit in Mac OS X Sierra (see generic-builder.nix): + local packageConfDir="$out/lib/${ghc.name}/package.conf.d"; + local dynamicLinksDir="$out/lib/links" + mkdir -p $dynamicLinksDir + # Clean up the old links that may have been (transitively) included by + # symlinkJoin: + rm -f $dynamicLinksDir/* + for d in $(grep dynamic-library-dirs $packageConfDir/*|awk '{print $2}'); do + ln -s $d/*.dylib $dynamicLinksDir + done + for f in $packageConfDir/*.conf; do + # Initially, $f is a symlink to a read-only file in one of the inputs + # (as a result of this symlinkJoin derivation). + # Replace it with a copy whose dynamic-library-dirs points to + # $dynamicLinksDir + cp $f $f-tmp + rm $f + sed "s,dynamic-library-dirs: .*,dynamic-library-dirs: $dynamicLinksDir," $f-tmp > $f + rm $f-tmp + done + '') + '' ${lib.optionalString hasLibraries "$out/bin/${ghcCommand}-pkg recache"} ${# ghcjs will read the ghc_libdir file when resolving plugins. lib.optionalString (isGhcjs && ghcLibdir != null) ''