Open Pitometsu opened 3 years ago
Would it be something lke:
(lambda (argv)
(let
((original-path (getenv-internal "PATH"))
(stack-env-path (shell-command-to-string "stack config env")) ;; TODO: handle case when stack is not present
(args ((mapconcat ’identity argv " "))))
(list (format "env PATH=%s:%s %s" ;; Should it handle empty environment variable case here?
original-path stack-env-path args))))
???
Result (in *Messages*):
LSP :: The following servers support current file but do not have automatic installation configuration: lsp-haskell
You may find the installation instructions at https://emacs-lsp.github.io/lsp-mode/page/languages.
(If you have already installed the server check *lsp-log*).
And no *lsp-log*
now. Looks like, lsp-haskell
is not able to determine presence of haskell-language-server
with that wrapper function anymore.
Also here possible lags with direnv-mode
and lorri
tools, and refreshing their caches (like M-x direnv-update-environment RET
and M-& lorri shell RET
M-x eshell-command RET lorri shell RET
.
Maybe the people have difficulty responding, because the case & semantics are not ordered. It is hard to parse the semantics, even weak interpretation does not infer into the concrete case.
It would be easier to understand if you would describe the environment of the project, what is used for what, and then nail the case.
Overall, from my experience, and from referring to the current official Stack docs, Stack just as 3 years ago, has very weak Nix integration: link.
Cabal has much better integration with Nix, running in Nix environment. Cabal would detect that it is running in Nix environment & would use Nix to load dependencies & work as Nix client, download the Haskell binary caches from Nixpkgs Hydra CI, and store the build artifacts in Nix.
Also, important to note that stack config env
& stack config --any-key
stack path
& stack path --any-key
are all effectful:
$ stack path --project-root
Preparing to install GHC (tinfo6) to an isolated location.
This will not interfere with any system-level installation.
ghc-tinfo6-8.10.4: 10.59 MiB / 207.59 MiB ( 5.10%) downloaded...^C
Tangent:
To tell a secret - using cabal
inside Nix is equivalent to stack
but with binary caches. As cabal
would infer the package dependency versions from Nixpkgs which in fact inherits Stackage provided package set every midnight (thou I do not remember Nightly or LTS), and so the Stackage package set is a core of Nixpkgs haskellPackages
, and all other Hackage set weekly gets handcrafted updates in Nixpkgs to be aligned to Stackage package versions. Thou there is a maintainer change there which probably would result in some infrastructure changes & also need to mention Cabal-Nix setup nevertheless comes with its own configuration & maintenance woes, but if there is strong reliance on Stackage versions - it should be a pretty stable calm experience.
Stack in Nix is also a legitimate combination, if the project uses a lot of FFI & so system package dependencies.
But, overall the solution may be (if I understand the question correctly) as simple as this: Of course, there is a directive to inherit something from host environment into a pure Nix environment:
🅸 ~/s/h/hnix:2021-05-27-refactors◦> echo "$IN_NIX_SHELL"
(nope)
🅸 ~/s/h/hnix:2021-05-27-refactors◦> bash
> export LALALA=TRALALA
> echo "$LALALA"
TRALALA
-- Entering Nix environment:
> nix-shell -p haskellPackages.stack --pure --keep LALALA
[user@host ~/path]$ echo "$IN_NIX_SHELL"
pure
[user@host ~/path]$ echo "$LALALA"
TRALALA
Note: https://github.com/NixOS/nix/issues/419#issuecomment-66932799
:arrow_up: It is true. It was true when it was written, & it is the same currently. Would spare the details, but can recommend not do shell work for Nix, or if do any - upfront be ready to throw the work out the window to not be disappointed. Nix taught me to not care to contribute when doing contribution, as caring does not depend on me but on one holding the "merge" button.
Also important to note that some "deep" Nix people - use all bashisms possible, which heavily hardcodes Nix to Bash. When operating with Nix in the code - the /usr/bin/env sh
(more portable) or /bin/sh
(a bit less portable), which preferably to be bash
or dash
, need to be run as a wrapper, for example, to make nix-shell -p .. --pure --keep PATH
inheritance work. The other shells do comply to the environment sharing standards - but Nix hardcode on bash
is so strong, fish
or zsh
or something a bit more exotic - Nix rigidness is not fully compatible with them. Nix promises portability & not follows POSIX or production-grade RFC standards (as Syslog RFC 3164).
I'd wanted to give less of a disclaimer, but the solution involves quirks that demand to be mentioned to implement proper solutions & save people's time upfront.
Sadly there is a lot of such open secret undocumented technical difficulties which when researched are frequently caused by social context reasons, seems like Nix details (at least in the past) borrowed heavilly from the Conway's law & Cognitive dimensions of notations.
Yuriy @Pitometsu, can the topic be closed?
Having somewhat extensive knowledge on the Haskell tooling & Nix situation both from prior work experience ("having skin in the game" with Stack & Nix situation in the past at work, where I built infrastructure pipeline) & my current experience with them and knowing new things on it.
The only thing I can tell - is that Stack and Nix combination completely disintegrates in the main agenda of them (the dependency/package management, Stack goes its own way, has own package inference, own system of building artifacts, while Nix infra demands 100% declarative descriptiveness & reproducibility & integration from Stack, which Stack does not provide for Nix, which produces a result that accumulates downsides of both - not reproducible builds that are not declarative, caching does not work, no deduplication, therefore the set size of the build artifacts during work is tremendous, builds always start anew, the number of custom hacks required is "the more hacks the better" which is a nice indication that path does not work, the maintenance cost of combination is unreasonable, it is undocumented, unsupported use, so no support from both upstreams...). So far Nix & Stack are not designed for each other. Use of Cabal(or HPack or DHall) with Nix is much more happy path & reasonable choice that should succeed.
I have errors like
when run
haskell-language-server
. I guess the reason is becausehspec-discover
inpackage.yaml:tests:build-tools:
, and so installed bystack
(not bynix-shell
as rest, not-build-specific, tools).But I have no such problems when run it like
env PATH=$PATH:`bash -c 'source <(stack config env); echo $PATH'` haskell-language-server
.I can't just run
stack exec haskell-language-server
to just simply have all thestack
's environments available, becausestack
usingnix --pure
for more robust and reproducible builds, and so that cause nix shells conflicts (not sure -- is it because of shells recursivity, orstack
can't decide, which nix shell is build one, according toSTACK_IN_NIX_SHELL
environment variable, I guess).So the question is: how construction like
env PATH=$PATH:`bash -c 'source <(stack config env); echo $PATH'` haskell-language-server
could be passed tolsp-haskell-server-wrapper-function
properly?Possible workaround would be: just add each tool from
stack
'spackage.yaml:tests:build-tools:
(likehspec-discover
here) into top-levelshell.nix
, but that would be fragile and require continuous project build tools consistency manual maintaining.