note how to fix the hls oopsie
This commit is contained in:
parent
7d9b77ab58
commit
9978909ced
1 changed files with 162 additions and 0 deletions
162
content/posts/nix-hls-for-deps.md
Normal file
162
content/posts/nix-hls-for-deps.md
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
+++
|
||||
date = "2022-07-21"
|
||||
draft = false
|
||||
path = "/blog/nix-hls-for-deps"
|
||||
tags = ["haskell", "nix"]
|
||||
title = "Setting up dev environments with Haskell Language Server and Nix"
|
||||
+++
|
||||
|
||||
A problem I sometimes have is dealing with a bunch of independently maintained
|
||||
but very interdependent libraries, for which I would like proper IDE
|
||||
functionality cross-project. Another problem I sometimes have is that I want to
|
||||
make a contribution to some library but setting up an IDE for it is a pain in
|
||||
the neck.
|
||||
|
||||
# YOLO method (putting it all in a workspace with your app and not telling Nix)
|
||||
|
||||
Often it is easiest to partially bypass Nix while doing development on
|
||||
dependencies. This means that Nix provides the compiler but the dependency
|
||||
you're working on *and everything below it* is then owned by Cabal.
|
||||
|
||||
This is achieved by adding the dependencies into `packages:` inside
|
||||
`cabal.project` or `cabal.project.local`. Then they are part of the workspace,
|
||||
and cabal can do partial recompilation on them as desired.
|
||||
|
||||
For instance, if your application depends on persistent and esqueleto and you
|
||||
want to hack on persistent, you would have to do the following:
|
||||
|
||||
* Clone persistent and esqueleto into subdirectories under the app (no need to
|
||||
make them submodules)
|
||||
* Put something like the following into `cabal.project` or
|
||||
`cabal.project.local`:
|
||||
|
||||
```cabalproject
|
||||
packages:
|
||||
esqueleto
|
||||
persistent/persistent
|
||||
persistent/persistent-*
|
||||
```
|
||||
|
||||
Sometimes, there will be an error that says that some files are missing. This
|
||||
is because Cabal decided to try to rebuild the Nix version of the package in
|
||||
question, and could not find source code. The solution to this is to clone the
|
||||
package with such an error and add it to `cabal.project` as before.
|
||||
|
||||
You can set up HLS by running `gen-hie` (from the `implicit-hie` package) and
|
||||
then put the results into `hie.yaml`.
|
||||
|
||||
Sometimes HLS won't have loaded up the dependency yet, for some reason and
|
||||
might have some weird import errors. This is solved by opening a file from that
|
||||
dependency.
|
||||
|
||||
This is kind of a hack, but this method works really really well for large
|
||||
codebases as it preserves the ability to do incremental builds on changes of
|
||||
dependencies, while also mostly using dependencies from Nix caches.
|
||||
|
||||
# Standalone workspace
|
||||
|
||||
It's possible to create a workspace to work on two or more libraries. This
|
||||
leverages Nix relatively nicely: pulls in dependencies as expected, and so on.
|
||||
|
||||
Let's do this to Persistent and Esqueleto, two database libraries. As I
|
||||
later learned, this was rather annoying due to having a large number of
|
||||
packages.
|
||||
|
||||
First, make a directory to do this in, and clone the dependencies into this
|
||||
directory. It's important this *not* be a git repo, because Nix gets confused
|
||||
with nested git repos, and it would be silly to have to set up submodules to do
|
||||
a little hacking ([apparently they don't work at all anyway][submodules-oops]).
|
||||
|
||||
[submodules-oops]: https://github.com/NixOS/nix/pull/5284
|
||||
|
||||
```sh
|
||||
$ mkdir deps && cd deps
|
||||
$ gh repo clone yesodweb/persistent
|
||||
$ gh repo clone bitemyapp/esqueleto
|
||||
```
|
||||
|
||||
Then initialize the flake with just a `flake.nix` with `nix flake init`, with a
|
||||
[flake template]:
|
||||
|
||||
```
|
||||
$ nix flake init -t github:lf-/flake-templates#haskell.flakeNix
|
||||
```
|
||||
|
||||
[flake template]: https://github.com/lf-/flake-templates/tree/main/haskell
|
||||
|
||||
Make a `cabal.project` so cabal considers it a multi package project properly:
|
||||
|
||||
```cabal
|
||||
packages:
|
||||
esqueleto
|
||||
persistent/persistent
|
||||
persistent/persistent-*
|
||||
```
|
||||
|
||||
Edit the `flake.nix` to add both of the packages in the workspace to the
|
||||
overlay and to the `packages` of the `devShell`:
|
||||
|
||||
```nix
|
||||
{
|
||||
# ...
|
||||
outputs = { self, nixpkgs, flake-utils }:
|
||||
let
|
||||
# ...
|
||||
out = system:
|
||||
let
|
||||
# ...
|
||||
in
|
||||
{
|
||||
# ...
|
||||
devShells.default =
|
||||
let
|
||||
haskellPackages = pkgs.haskell.packages.${ghcVer};
|
||||
in
|
||||
haskellPackages.shellFor {
|
||||
packages = p: with pkgs.haskell.packages.${ghcVer}; [
|
||||
persistent
|
||||
esqueleto
|
||||
persistent-qq
|
||||
persistent-template
|
||||
persistent-mysql
|
||||
persistent-test
|
||||
persistent-postgresql
|
||||
persistent-sqlite
|
||||
];
|
||||
withHoogle = true;
|
||||
buildInputs = with haskellPackages; [
|
||||
haskell-language-server
|
||||
fourmolu
|
||||
ghcid
|
||||
cabal-install
|
||||
];
|
||||
};
|
||||
};
|
||||
in
|
||||
flake-utils.lib.eachDefaultSystem out // {
|
||||
# this stuff is *not* per-system
|
||||
overlays = {
|
||||
default = makeHaskellOverlay (
|
||||
prev: hfinal: hprev:
|
||||
let
|
||||
hlib = prev.haskell.lib;
|
||||
# this uses overrideSrc because of funniness with the deps of
|
||||
# persistent-sqlite
|
||||
makeLocal = n: hlib.overrideSrc hprev.${n} { src = ./persistent + "/${n}"; };
|
||||
in
|
||||
{
|
||||
persistent = makeLocal "persistent";
|
||||
persistent-test = makeLocal "persistent-test";
|
||||
persistent-sqlite = makeLocal "persistent-sqlite";
|
||||
persistent-postgresql = makeLocal "persistent-postgresql";
|
||||
persistent-mysql = makeLocal "persistent-mysql";
|
||||
persistent-qq = makeLocal "persistent-qq";
|
||||
persistent-template = makeLocal "persistent-template";
|
||||
esqueleto = hprev.callCabal2nix "esqueleto" ./esqueleto/esqueleto.cabal {};
|
||||
}
|
||||
);
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue