ghc-mod
ghc-mod copied to clipboard
cabal new-build support
On a project which I built using the new-configure/new-build feature of cabal-install, ghc-mod fails to init the project because it runs cabal configure
instead of cabal new-configure
and then fails to find the package dependencies. The new-*
commands of cabal-install will eventually replace their current equivalents. But I honestly don't know when, I will let a Cabal core dev to comment. So perhaps this is going to be an ephemeral change, nonetheless useful.
I suspect for minimal support there may be more changes required than just the command names.
As I discussed with @DanielG at the recent hackathon, this is an opportunity to have better integration/communication between cabal and ghc-mod. We're awaiting a ticket with suggestions from @DanielG about what info ghc-mod would like, and an interaction pattern that'd work for ghc-mod.
See also #809
@dcoutts See https://github.com/haskell/cabal/pull/2771#issuecomment-131733124 which has at least some information about what we need but you'll also want to glance at the source code starting here: https://github.com/DanielG/cabal-helper/blob/master/CabalHelper/Main.hs#L185. Main.hs
is the only file that should be relevant to you though, everything else is just bindings to the command interface and runtime-recompilation stuff.
@dcoutts here you go haskell/cabal#3872, that should get the discussion going :)
Since this has been open for almost a year, is there any progress on supporting new-build in ghc-mod (or vice versa i guess)?
No unfortunately, any help is welcome though :)
I'd be glad to help in my spare time but I don't know where to start and I'm afraid helping me get up to speed with the codebase would take more effort than fixing the issue^^
As a user of cabal new-build
, I believe the introduction of GHC environment files removes most of the need for configuration logic in ghc-mod
itself. Essentially cabal-install
writes out a .ghc.environment
file containing the package configuration that it would use to compile the last-used component. This file then gets picked up by GHC. This means that the usual ghc
and ghci
commands work without further help from cabal
. It also has the happy consequence that tools like ghc-mod
work largely out of the box. In practice environment files have worked reasonably well for me.
@bgamari I saw that ghc envirnoment stuff but never really investigated what they really do. Can you maybe show an example of what such a thing looks like or link to some docs? I wonder if this could be extended to support spitting out info for multiple components, I'd rather not have to downgrade support for multiple components in ghc-mod to support this.
The GHC user guide provides a specification of the format. Unfortunately I don't think the cabal bits were ever properly documented. I'm also not sure what the story for multiple components looks like. @ezyang or @dcoutts may be able to fill in some details here.
@hvr was responsible for new-build environment file support, so he will best be able to say, but I believe the way it works is that when you run new-build, cabal generates an environment file, so that ghc (and anything using the ghc api) when run without -hide-all-packages
uses this environment.
As far as multiple components goes, I am not sure how ghc-mod's multiple components support works, so it is difficult to say.
Ah I see, the environment just contains info about packages and package-dbs not exact per-component GHC flags. Not sure how useful that is in more complex projects TBH.
As far as multi-component support in ghc-mod goes: we basically look at {exposed,other}-modules
and include paths (hs-src-dirs
and what have you) to figure out which files belong to which set of components and then just arbitrarily pick one of them to use as a source of GHC flags. We have to build a module graph to do that though because of cabal's leniency with other-modules
in exe components.
OK, but after picking one of the components, you use those flags to build the other components? I.e., if you have a test suite, surely it's going to have extra dependencies for tests? (Maybe you merge the deps together?)
No, we always check which component a file belongs to before doing anything and initialize a GHC session with the flags for the picked component. If you then switch to a different component we just re-initialize the session with the new flags.
The dependency merging is only a hack to not break the command API for the browse
command (i.e. completion) since that doesn't have a file/module argument for historical reasons.
Ah I see.
In that case, I think this can be made to work. In practice, the environment should eliminate the need to specify package flags: instead, the environment will have exactly the set of packages necessary to run the package (as if you had cabal install'ed each of the dependencies into a fresh user package database, and decided to use that.) (In theory, this is not quite good enough because you need to hide/show packages based on the set of build-depends for a particular component.)
@DanielG, does @ezyang's description sound plausible to you?
For what it's worth, I've been using ghc-mod
on some quite large projects using new-build
and environment files with no problems for quite some time now. In my experience it all seems to "just work".
The problem I see is that, for example, per component ghc-options
won't be passed to ghc-mod
with this approach which would be a regression in functionality. I still think going via plan.json+cabal-helper/show-build-info is the best long term solution.
Any hopes for supporting cabal new-build
anytime soon?
I am using ghc 8.2
@bgamari, do you have a write-up of your setup?