Skip to content

haskell-language-server: make linking configureable in wrapper#158669

Merged
maralorn merged 4 commits intoNixOS:haskell-updatesfrom
sternenseemann:hls-dynamic-wrapper
Feb 11, 2022
Merged

haskell-language-server: make linking configureable in wrapper#158669
maralorn merged 4 commits intoNixOS:haskell-updatesfrom
sternenseemann:hls-dynamic-wrapper

Conversation

@sternenseemann
Copy link
Member

haskell-language-server will now default to building a shared
executable, as upstream does, complete with a huge closure. By passing
{ dynamic = false; } via override, it is still possible to build a
"statically linked" variant of HLS, as it used to be.

Note: Before this change HLS would fail to compile on aarch64.

Motivation for this change
Things done
  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandbox = true set in nix.conf? (See Nix manual)
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 22.05 Release Notes (or backporting 21.11 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
    • (Release notes changes) Ran nixos/doc/manual/md-to-db.sh to update generated release notes
  • Fits CONTRIBUTING.md.

haskell-language-server will now default to building a shared
executable, as upstream does, complete with a huge closure. By passing
{ dynamic = false; } via override, it is still possible to build a
"statically linked" variant of HLS, as it used to be.

Note: Before this change HLS would fail to compile on aarch64.
@github-actions github-actions bot added the 6.topic: haskell General-purpose, statically typed, purely functional programming language label Feb 8, 2022
@sternenseemann
Copy link
Member Author

@ofborg build haskell-language-server

@ofborg ofborg bot added 10.rebuild-darwin: 1-10 This PR causes between 1 and 10 packages to rebuild on Darwin. 10.rebuild-darwin: 1 This PR causes 1 package to rebuild on Darwin. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. 10.rebuild-linux: 1 This PR causes 1 package to rebuild on Linux. labels Feb 8, 2022
@maralorn
Copy link
Member

maralorn commented Feb 8, 2022

@sternenseemann I am sorry I haven‘t followed the platform specific and the linking problems to closely. It was my impression that hls did (except for ghc 9.2) build on aarch64.

Are there upsides for the other platforms as well from dynamic linking? I hadn‘t noticed any issues, even with template haskell.

I am honestly not sure that this wrapper is even worth it or the recommended install method any more when it has a 5 GB closure. That’s a huge downside. (Seriously, that feels like something we loose Haskell adoption to … Some people are really scared of big closures.)

Maybe we need to consider to changing the default here? Alternatively are there any downsides to enable dynamic linking in haskellPackages?

@sternenseemann
Copy link
Member Author

This is not platform specific at all (there seems to be some platform specific component which hardly matters though). What happened is that starting with HLS 1.6.1.1 upstream will enable dynamic linking by default. I've so far just reflected the default in nixpkgs in order to keep builds working.

The closure size is a concern of course, and I agree that we should probably default to dynamic = false for the wrapper. Just didn't want to take action without consulting with you more or less.

@sternenseemann
Copy link
Member Author

Are there upsides for the other platforms as well from dynamic linking? I hadn‘t noticed any issues, even with template haskell.

I think this is relevant if you use e. g. TH and system libraries, as without dynamic linking the (partially buggy, especially on darwin) GHC internal linker is used instead of the system one.

This means we don't use the system linker by default, but decreases
closure size significantly, as we no longer reference every supported
version GHC.
@sternenseemann
Copy link
Member Author

Maybe we need to consider to changing the default here? Alternatively are there any downsides to enable dynamic linking in haskellPackages?

Also, this is already enable in haskellPackages, but the justStaticExecutables here was messing with it.

@maralorn
Copy link
Member

maralorn commented Feb 8, 2022

Maybe we need to consider to changing the default here? Alternatively are there any downsides to enable dynamic linking in haskellPackages?

Also, this is already enable in haskellPackages, but the justStaticExecutables here was messing with it.

Do I understand correctly that upstream changed the default in their cabal file and thus this changed automatically in haskellPackages?

Does this mean that the wrapper package is currently broken on master because it uses justStaticExecutables on a dynamically linked build?

@maralorn
Copy link
Member

maralorn commented Feb 8, 2022

I read a bit backlog in the hls channel. Apparently no one is really convinced that dynamic linking will solve an actual problem, but they do think so.

Sadly, I don’t believe that users will know, that they need to open an issue, against nixpkgs, when they encounter an issue like this.

My gut feeling is that the correct way forward would be to reduce the wrapper to the current default ghc, enable dynamic linking by default and document this accordingly.

To get better caching in that case: I wonder: Do we need the remove references part if the closure size is screwed anyways?

@sternenseemann
Copy link
Member Author

To get better caching in that case: I wonder: Do we need the remove references part if the closure size is screwed anyways?

Probably at least the ghc one should be removed as it would probably cause some level of incorrectness. Not sure about the data output ones (why are they even there?).

@maralorn
Copy link
Member

maralorn commented Feb 9, 2022

To get better caching in that case: I wonder: Do we need the remove references part if the closure size is screwed anyways?

Probably at least the ghc one should be removed as it would probably cause some level of incorrectness. Not sure about the data output ones (why are they even there?).

I just remember that those references happened in some kind of documentation and were therefore irrelevant for code correctness.

If we are linking dynamically, it's practically no use removing
references, as we depend on GHC either way via linking.

I've also elected to keep the references to the data outputs in all
cases — they are a bit arcane (there's no easy way to tell they
definitely are not necessary) and don't contribute too much to the
overall closure size.
@sternenseemann
Copy link
Member Author

See a386d54.

@maralorn
Copy link
Member

I‘d be delighted to hear, if anyone is experiencing any TH+hls+linking issues.

I am on the fence if we should enable dynamic linking by default.

Still this PR is strict improvement. Thank you ver much!

@maralorn maralorn merged commit 562ad4a into NixOS:haskell-updates Feb 11, 2022
@sternenseemann sternenseemann deleted the hls-dynamic-wrapper branch February 11, 2022 11:56
@sternenseemann
Copy link
Member Author

As it stands haskell.packages.ghc*.haskell-language-server will be dynamically linked, haskell-language-server statically linked (unless you override it). I'd keep all of this undocumented for a bit though, so we can change our minds still.

@gloaming
Copy link
Contributor

gloaming commented Jun 1, 2022

I‘d be delighted to hear, if anyone is experiencing any TH+hls+linking issues.

@maralorn I spent a while trying to figure out why TH wasn't working in VSCode, and ended up here after seeing TH mentioned in the HLS troubleshooting guide. Many thanks to @sternenseemann for the previous comment explaining how to install with dynamic linking, which seems to have fixed the problem. 🎉

@maralorn
Copy link
Member

maralorn commented Jun 2, 2022

@gloaming Thanks for the feedback. Then I guess we should enable this by default? But yeah, then we should restricted the wrapper to only the default version and document this accordingly.

@sternenseemann
Copy link
Member Author

I don't think it's feasible to have it on by default as it'll necessarily pull in 4 GHCs (RTS is linked dynamically).

@maralorn
Copy link
Member

maralorn commented Jun 2, 2022

Well then we should disable pulling in 4 GHCs by default?
I’d rather users notice, that they don‘t have the right hls and go to the docs and find out how to install the correct one, than having a weird cornercase failure.

@sternenseemann
Copy link
Member Author

HLS actually displays a message about it on startup, in theory we could patch that to link to instructions for NixOS or check if they link anywhere and try getting upstream to amend the instructions.

@maralorn
Copy link
Member

maralorn commented Jun 4, 2022

Hm, is that message intrusive enough? I am pretty sure I never saw it. But yeah, a documentation based fix would be nice, I guess.

@nixos-discourse
Copy link

@ParetoOptimalDev
Copy link

I‘d be delighted to hear, if anyone is experiencing any TH+hls+linking issues.

I am on the fence if we should enable dynamic linking by default.

Still this PR is strict improvement. Thank you ver much!

Just wanted to add why I think this was a good change.

I wasted many hours if not days because dynamic linking not being on messed up TH. It negatively affected my experiment/proposal to use Nix at work.

Plus I think "it works for common cases like TH" is more common than "I don't want a 5GB closure". Haskell users, especially Haskell on Nix users are used to using 100s of gigabytes of space for better or worse.

At least... I am given I have 20-40 direnv environments across various ghc versions, some also with different hls versions.

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

Labels

6.topic: haskell General-purpose, statically typed, purely functional programming language 10.rebuild-darwin: 1-10 This PR causes between 1 and 10 packages to rebuild on Darwin. 10.rebuild-darwin: 1 This PR causes 1 package to rebuild on Darwin. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. 10.rebuild-linux: 1 This PR causes 1 package to rebuild on Linux.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants