Skip to content
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

haskell/generic-builder.nix: Fix C lib multiple inclusions #87881

Merged

Conversation

roberth
Copy link
Member

@roberth roberth commented May 15, 2020

Motivation for this change

Fixes #87880

Allow the darwin links code to overwrite libs that were already copied, because C dependencies can occur multiple times.

Solves errors like

ln: failed to create symbolic link '/nix/store/higpc9xavwcjjzdipz7m9ly03bh7iy2z-hercules-ci-agent-source-0.7.0/lib/links/libboost_context.dylib': File exists
Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS linux)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Determined the impact on package closure size (by running nix path-info -S before and after)
  • Ensured that relevant documentation is up to date
  • Fits CONTRIBUTING.md.

Allow the darwin links code to overwrite libs that were already
copied, because C dependencies can occur multiple times.

Solves errors like

    ln: failed to create symbolic link '/nix/store/higpc9xavwcjjzdipz7m9ly03bh7iy2z-hercules-ci-agent-source-0.7.0/lib/links/libboost_context.dylib': File exists
@cdepillabout
Copy link
Member

cdepillabout commented May 15, 2020

I think there is also a fix for this in #84985?

However, I don't understand the following things, which is part of the reason why this hasn't been fixed yet:

  • What exactly is the problem here? (I get the direct problem, using ln -s instead of ln -sf, but what is this chunk of code doing in the first place? I can't seem to make heads or tails of the comments on this chunk of code.)
  • Why does this only happen on OSX?
  • How can I reproduce this locally?
  • Why do we need to unprettify all package conf files?
  • Why do we need to use this $out/lib/links directory?
  • Why is Fix the error of making symlink in setupCompilerEnvironmentPhase. #84985 so much more complicated than this PR?

@roberth
Copy link
Member Author

roberth commented May 15, 2020

Thanks @cdepillabout ! I didn't find that PR for some reason. It seems like at some point it solved the problem but it's back to creating a more informative error message instead.

What exactly is the problem here?

Multiple packages may write links for the same C lib with the same name, causing the issue. I don't think this is a bug. If for example cachix adds libnixstore.dylib and hercules-ci-agent depends on cachix but also libnixstore.dylib, it will try to write a link that already exists.

Why does this only happen on OSX?
Why do we need to use this $out/lib/links directory?

The darwin linker puts a limit on the total size of the section that references dynamic libraries (correct my wording if needed). Putting them in the links directory means we can reference them with short names via rpath. This has been painstakingly iterated on by haskellPackages contributors.

Why do we need to unprettify all package conf files?

I've seen a commit by infinisil in the git blame earlier talking about the reasons why. Basically we it's the best we have.

Why is #84985 so much more complicated than this PR?

That PR also updates the package set, bumps ghcHEAD and has a lot of code to print a more useful error message. It doesn't actually solve #87880. It only provides a more detailed error message.

How can I reproduce this locally?

This is detailed in #87880. To summarize, build this gist on macOS.

@peti
Copy link
Member

peti commented May 15, 2020

  • Why does this only happen on OSX?

The code in question is not executed on any other platform! This is a hack to work around a length limitation of LD_LIBRARY_PATH on Darwin (or, well, it's DYNLIBPATH or whatever, but you know what I mean). Now I remember ... we introduced that hack when MacOS Sierra came out.

  • Why do we need to unprettify all package conf files?

I seem to recall that older versions of GHC could not parse the pretty-printed config files properly under certain circumstances, so all the newlines and indentation were removed to work around that issue. It's possible that current versions of GHC don't have that problem any more and that we can remove the un-pretty'fying stage.

Copy link
Member

@peti peti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@peti peti merged this pull request into NixOS:haskell-updates May 15, 2020
@cdepillabout
Copy link
Member

@roberth @peti Thanks for these detailed explanations!

There is one other question I had from #84985 (that also applies here): What would happen if a Haskell library depended on two different C libraries that happened to have the same name?

For instance, what if my Haskell library mmmonad depended on the following two packages:

  • the Haskell package ffffunctor, which uses a C library called libfoobar.dylib
  • the Haskell package aaaaplicative, which uses a different C library that also happens to be called libfoobar.dylib

Reading the code in this PR, it appears that the first libfoobar.dylib would be overwritten by the second libfoobar.dylib? In this case, maybe mmmonad wouldn't be able to correctly link to ffffunctor's libfoobar.dylib (since it has been overwritten).

I was thinking this would be a problem, but maybe I'm interpreting the code incorrectly?

In either case, I imagine it is pretty unlikely we run into this error, since different C libraries will probably (hopefully?) have different names.

@infinisil
Copy link
Member

Yeah the libraries would override each other, which is why in #84985 (review) I mentioned how it should be properly fixable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants