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.
This commit is contained in:
Judah Jacobson 2017-05-03 13:13:05 -07:00
parent 4ff4f6e038
commit 7131e06214
2 changed files with 42 additions and 0 deletions

View File

@ -228,6 +228,25 @@ stdenv.mkDerivation ({
configureFlags+=" --extra-lib-dirs=$p/lib"
fi
done
if "${if stdenv.isDarwin then "true" else "false"}"; then
# 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
fi
${ghcCommand}-pkg --${packageDbFlag}="$packageConfDir" recache
runHook postSetupCompilerEnvironment

View File

@ -97,6 +97,29 @@ symlinkJoin {
fi
done
# Work around a linker limit in Mac OS X Sierra (see generic-builder.nix):
if "${if stdenv.isDarwin then "true" else "false"}"; then
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
fi
${lib.optionalString hasLibraries "$out/bin/${ghcCommand}-pkg recache"}
${# ghcjs will read the ghc_libdir file when resolving plugins.
lib.optionalString (isGhcjs && ghcLibdir != null) ''