Open Profpatsch opened 3 years ago
If you install hls the expected way, via downloading the executables using ghcup, you actually end up with a set of binaries, one per GHC version, and one called haskell-language-server-wrapper
.
The wrapper exe works out which GHC version is used for the file/project being opened, and then execs the appropriate GHC-specific haskell-language-server version.
Indeed.
In other words. wrapper
in HLS does what is needed to abstract the environment complexities from the server HLS implementation.
For example, a while ago I wanted to add Nix environment support to the wrapper, but was rebuffed. And maybe rightfully so. Maybe Nix needs indeed be outside for the HLS, or be a Cradle implementation. Nix community itself can not standardize the approach and even an entry point, it is custom who-likes-what implementations all the way. But that is another topic.
wrapper
is there to abstract env that particular project developer uses. Wrapper reads Cradle information, differentiates between Cabal & Stack project setups and package resolution, and resolves the GHC version - all that resolves to what developer has chosen to use currently in the project, which allows to load the according fully compatible (hopefully) with that env HLS - that uses the same resolving process (Cabal, Hackage, Stack, Stackage, (Nix, Nixpkgs if run inside Nix env)) and loads the HLS that compiled in and supports the same version of the GHC that project is developed in.
Without the wrapper
we would ask Alan and others HLS devs to "just support" binaries of HLS compiled to arbitrary GHC be ready for and support internalls of other arbitrary GHCs all at once. The wrapper allows them to abstract from project environments and dependencies resolution and concentrates on supporting recent GHC branches, and ship single HLS-API-GHC pairings:
Oversimplification:
wrapper :: GhcVer -> IO Hls
wrapper ghcVer = (\v -> interfaceWith v $ runFor v $ compileTo v $ implementHlsFor v) ghcVer
If you want - they essentially recreate the static environment for themself (as Nix project envs do), and consistent single entry point for us.
The downside - is that we need to load and store several HLS backends, just like in Nix downside.:
haskell-language-server-wrapper -> haskell-language-server-wrapper-0.8.0
haskell-language-server-wrapper-0.8.0
haskell-language-server-8.6.4 -> haskell-language-server-8.6.4~0.8.0
haskell-language-server-8.6.4~0.8.0
haskell-language-server-8.6.5 -> haskell-language-server-8.6.5~0.8.0
haskell-language-server-8.6.5~0.8.0
haskell-language-server-8.8.2 -> haskell-language-server-8.8.2~0.8.0
haskell-language-server-8.8.2~0.8.0
haskell-language-server-8.8.3 -> haskell-language-server-8.8.3~0.8.0
haskell-language-server-8.8.3~0.8.0
haskell-language-server-8.8.4 -> haskell-language-server-8.8.4~0.8.0
haskell-language-server-8.8.4~0.8.0
haskell-language-server-8.10.1 -> haskell-language-server-8.10.1~0.8.0
haskell-language-server-8.10.1~0.8.0
haskell-language-server-8.10.2 -> haskell-language-server-8.10.2~0.8.0
haskell-language-server-8.10.2~0.8.0
haskell-language-server-8.10.3 -> haskell-language-server-8.10.3~0.8.0
haskell-language-server-8.10.3~0.8.0
haskell-language-server-wrapper-0.9.0
haskell-language-server-8.6.4~0.9.0
haskell-language-server-8.6.5~0.9.0
haskell-language-server-8.8.2~0.9.0
haskell-language-server-8.8.3~0.9.0
haskell-language-server-8.8.4~0.9.0
haskell-language-server-8.10.1~0.9.0
haskell-language-server-8.10.2~0.9.0
haskell-language-server-8.10.3~0.9.0
If haskell-language-server-wrapper
looks like executable in Nix user profile env entry, and the chain looks like closure resolution for compiled binaries - because it is, it does the same thing for the particular purpose of shipping HLS portable for "all" Haskell ecosystems.
The upside - they have the same frontend executable entry point and the perfect HLS-for-GHC pairings so HLS works for everybody. And they have lightweight wrapper that supports everybody, without the need for anyone to force into learn/maintain Nix, have coupling/maintenance of revs and coupling on Nixpkgs version resolutions and so on. Their simple solution so far works for everybody.
Otherwise, they would've needed support the Cartesian product of Haskell envs possible.
And with the Haskell env ecosystem fragmentation and nuances... they need a wrapper simplification to abstract from it.
The existence and reliance on the wrapping of HLS is a Haskell env ecosystem fragmentation question and HLS upstream implementation simplification, it is not Emacs lsp-haskell
package question in any shape or form. And I am happy that it works nicely for HLS devs and for Haskell devs.
I've proposed something in https://github.com/emacs-lsp/lsp-haskell/issues/169 following @michaelpj proposal
https://github.com/emacs-lsp/lsp-haskell/blob/5d3f4814f6ac44547a62551472cc76fbaebcccf7/lsp-haskell.el#L162-L166
I am trying to set up the
haskell-language-server
, and I’m wondering why the default executable name in this module is calledhaskell-language-server-wrapper
instead of justhaskell-language-server
. As far as I can see the latter is how hls expects users to call the binary.