Open aherrmann opened 4 years ago
Unfortunately hie-bios
recently removed bazel support.
We internally have some patches to make hie-bios
and ghcide
work in our build environment (a bazel variant). We're not ready yet to publish them but I can give a high-level description.
hie-bios
hie.yaml
files so that ghcide
can work out of the boxghcide
-package
or -package-id
GHC flags)Hopefully this helps. Please feel free to ask if you have questions.
@jinwoo Thanks for the detailed response and sorry for the late reply.
Unfortunately
hie-bios
recently removed bazel support.
I'm aware, though the possibility to add it back is explicitly spelled out in the corresponding comment.
We internally have some patches to make
hie-bios
andghcide
work in our build environment (a bazel variant). We're not ready yet to publish them but I can give a high-level description.
Thanks for sharing those insights.
hie-bios
- We create "implicit" cradles rather than depending on
hie.yaml
files so thatghcide
can work out of the box- Each bazel build target becomes an implicit cradle with its own GHC flags and source files
- Given a Haskell source file, it finds the corresponding bazel target and creates a cradle for it
I'd be curious to learn more about how this works in practice. Let's consider a concrete example to ease the discussion.
haskell_toolchain_library(name = "base")
haskell_library(
name = "lib",
srcs = ["Lib.hs"],
deps = [":base"],
)
haskell_binary(
name = "bin",
srcs = ["Main.hs"],
deps = [":base", ":lib"],
)
If I understand you correctly, then :bin
will be loaded into a separate cradle than :lib
. This would mean that :lib
needs to be compiled and will be loaded as a prebuilt package into the GHC session for :bin
, correct? This, in turn, would mean that source changes to :lib
are not automatically picked up by the session for :bin
. So, the user would have to reload the IDE to make those visible. How do you address this issue in your internal forks?
ghcide
- There are quite a few patches here but the most important patch was to NOT locate imported files from random locations in the file system. Because bazel is hermetic and all the dependencies are explicitly specified in the build targets, when a module imports another module, it should be located only from those specified dependencies
Does this require ghcide
to talk to Bazel directly, or were you able to implement this maintaining the hie-bios
abstraction?
As for this feature request, I think it would still be a useful addition. We've just added a similar feature to rules_haskell
which allows pointing ghcide
at a haskell_repl
target. The same should be possible with hrepl
.
haskell_toolchain_library(name = "base") haskell_library( name = "lib", srcs = ["Lib.hs"], deps = [":base"], ) haskell_binary( name = "bin", srcs = ["Main.hs"], deps = [":base", ":lib"], )
If I understand you correctly, then
:bin
will be loaded into a separate cradle than:lib
. This would mean that:lib
needs to be compiled and will be loaded as a prebuilt package into the GHC session for:bin
, correct?
Correct.
This, in turn, would mean that source changes to
:lib
are not automatically picked up by the session for:bin
. So, the user would have to reload the IDE to make those visible. How do you address this issue in your internal forks?
Unfortunately we don't have a good solution yet. Some editor plugins support LSP server restart and it helps a bit, but yeah it is annoying. Our hope is that once ghcide supports .hie
well, it could improve this but we're not sure.
Another problem is "Go to definition" doesn't work across multiple build targets due to the same reason.
ghcide
- There are quite a few patches here but the most important patch was to NOT locate imported files from random locations in the file system. Because bazel is hermetic and all the dependencies are explicitly specified in the build targets, when a module imports another module, it should be located only from those specified dependencies
Does this require
ghcide
to talk to Bazel directly, or were you able to implement this maintaining thehie-bios
abstraction?
In order to find the imported module only from the source files specified in the build target, we set the "targets" of the current GHC session to those files. I have a (rejected) upstream PR: https://github.com/digital-asset/ghcide/pull/394. And we patched the locateModuleFile
function so that it locates the file only from the current "targets", rather than from any files in the file system.
For other things, we also have patches for hie-bios
, where we use bazel query
to get various information. For example, given a source file, to find the corresponding build target. They are done by the hie-bios
layer, so ghcide
doesn't directly talk to bazel. It only knows about the (bazel) cradle.
Feature
Add an option for
hrepl
to only print the relevant flags to GHCi for loading the specified range of targets. This should probably exclude flags that are only required forhrepl
specifics, e.g. for the ghci script thathrepl
defines.Use-case
The use-case I have in mind is to use
hrepl
in ahie-bios
cradle to enableghcide
to load rules_haskell projects.hie-bios
has abios
cradle that takes a program that will write all required GHC flags to a file specified by the$HIE_BIOS_OUTPUT
environment variable.hrepl
could be used as that program. Furthermore,hie-bios
could be extended with a dedicated Bazel cradle (reviving the currently disabled one).An example use-case could look like this:
Assuming wild-card support in
hrepl
(or thebazel
cradle) and multi-cradle support inghcide
.