-
-
Notifications
You must be signed in to change notification settings - Fork 15.5k
haskell: work around linker limits on Mac OS X Sierra. #25537
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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 (NixOS#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 NixOS#22810.
cc @shlevy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder about the strange way the Darwin-specific code in integrated.
@@ -228,6 +228,25 @@ stdenv.mkDerivation ({ | |||
configureFlags+=" --extra-lib-dirs=$p/lib" | |||
fi | |||
done | |||
if "${if stdenv.isDarwin then "true" else "false"}"; then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Considering the fact you have conditionals in the Nix language, why is that feature used here to create input for yet another level of conditional that's evaluated by the shell? This looks awkward. Is there a deeper reason for this implementation choice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was mostly due to my lack of familiarity with Nix. I've switched to @shlevy 's suggestion.
@@ -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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dito
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Untested, but overall looks great! Can you just change the stylistic nit (in both files)?
@@ -228,6 +228,25 @@ stdenv.mkDerivation ({ | |||
configureFlags+=" --extra-lib-dirs=$p/lib" | |||
fi | |||
done | |||
if "${if stdenv.isDarwin then "true" else "false"}"; then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: prefer
'' + (stdenv.lib.optionalString stdenv.isDarwin ''
darwin-only-command
'') + ''
the-rest
''
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, thanks for the suggestion.
@judah You've tested the latest? |
Running the test again now. It will probably take a couple hours since it needs to re-bootstrap GHC. I'll ping back on this thread once I've seen the test pass. |
@@ -228,6 +228,23 @@ stdenv.mkDerivation ({ | |||
configureFlags+=" --extra-lib-dirs=$p/lib" | |||
fi | |||
done | |||
'' + (optionalString stdenv.isDarwin '' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we also want to skip this when building a static library/executable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a no-op in that case since static libraries have the different extension *.a
and aren't affected by the dynamic-library-dirs
field.
Confirmed that the build still passed after the fix. |
LGTM 👍 |
# libraries) from all the dependencies. | ||
local dynamicLinksDir="$out/lib/links" | ||
mkdir -p $dynamicLinksDir | ||
local foundDylib=false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see where foundDylib
is used. Perhaps you wanted to set foundDylib
to "true"
in the for
loop below, and then if no dylib is found, delete the (empty) $out/lib/links
dir?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry about that; sent out #25602 to remove the line.
Originally I was going to add more complicated logic to handle the different Linux/Mac cases (since the former uses a different extension for shared libraries). But the call to stdenv.isDarwin
has an equivalent effect.
@judah, can you please address @cstrahan's comments from #25537 (review)? |
Previously the package conf files were handled without paying attention to the fact that it's pretty-printed output. One problem was discovered with GHC 8.8.1 on Darwin, where the dynamic-library-dirs first field seems to have increased in length, meaning while before it was dynamic-library-dirs: some-small-directory-name some-more-directories Now it is dynamic-library-dirs: some-larger-directory-name some-more-directories Which breaks the code installed for NixOS#25537, because that assumed the former format, resulting in the reoccurence of the bug in NixOS#22810, see infinisil/all-hies#43 This commit fixes this by "unprettyfying" the package conf files before processing them.
Previously the package conf files were handled without paying attention to the fact that it's pretty-printed output. One problem was discovered with GHC 8.8.1 on Darwin, where the dynamic-library-dirs first field seems to have increased in length, meaning while before it was dynamic-library-dirs: some-small-directory-name some-more-directories Now it is dynamic-library-dirs: some-larger-directory-name some-more-directories Which breaks the code installed for #25537, because that assumed the former format, resulting in the reoccurence of the bug in #22810, see infinisil/all-hies#43 This commit fixes this by "unprettyfying" the package conf files before processing them. Closes #78738.
Previously the package conf files were handled without paying attention to the fact that it's pretty-printed output. One problem was discovered with GHC 8.8.1 on Darwin, where the dynamic-library-dirs first field seems to have increased in length, meaning while before it was dynamic-library-dirs: some-small-directory-name some-more-directories Now it is dynamic-library-dirs: some-larger-directory-name some-more-directories Which breaks the code installed for #25537, because that assumed the former format, resulting in the reoccurence of the bug in #22810, see infinisil/all-hies#43 This commit fixes this by "unprettyfying" the package conf files before processing them. Closes #78738.
Previously the package conf files were handled without paying attention to the fact that it's pretty-printed output. One problem was discovered with GHC 8.8.1 on Darwin, where the dynamic-library-dirs first field seems to have increased in length, meaning while before it was dynamic-library-dirs: some-small-directory-name some-more-directories Now it is dynamic-library-dirs: some-larger-directory-name some-more-directories Which breaks the code installed for NixOS#25537, because that assumed the former format, resulting in the reoccurence of the bug in NixOS#22810, see infinisil/all-hies#43 This commit fixes this by "unprettyfying" the package conf files before processing them. Closes NixOS#78738.
Previously the package conf files were handled without paying attention to the fact that it's pretty-printed output. One problem was discovered with GHC 8.8.1 on Darwin, where the dynamic-library-dirs first field seems to have increased in length, meaning while before it was dynamic-library-dirs: some-small-directory-name some-more-directories Now it is dynamic-library-dirs: some-larger-directory-name some-more-directories Which breaks the code installed for NixOS#25537, because that assumed the former format, resulting in the reoccurence of the bug in NixOS#22810, see infinisil/all-hies#43 This commit fixes this by "unprettyfying" the package conf files before processing them. Closes NixOS#78738.
The workaround that this change deletes was initially contributed in NixOS#25537 to mitigate NixOS#22810 until a more permanent solution could be devised. That more permanent solution was eventually contributed in NixOS#27536, which now obviates the initial workaround, so this change removes it.
The Sierra linker added a limit on the number of paths that any one
dynamic library (
*.dylib
) can reference. This causes problems whena 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 bygeneric-builder.nix
.Tested by building the
stack
binary as described in #22810.