-
Notifications
You must be signed in to change notification settings - Fork 849
Improve stack support for HLS #6154
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@mpilgrem if possible, I would like to know what you think :) |
@fendor, I support the objective. Stack has a command In terms of helping with the implementation of the idea, I am conscious of my own limitations but I would do what I can to help. To help me understand what is required from Stack, it would help to make the abstract more concrete, with a simple example. For example, if you had a plain vanilla In this context, what is meant by 'all the exact compilation options'? If you command
and the
You may already know this, but Stack uses the version of Cabal (the library) that ships with the version of GHC in question, which may limit the availability to Stack of information provided by Cabal's |
I'm somewhat familiar with stack codebase and don't mind contributing in this effort. |
Thinking out loud:
|
Thank you for your extensive comments! Let me add some clarifications:
Yes, that is exactly correct. When talking about filepaths, I mean haskell source files that are part of a stack project.
Yes, what you correctly inferred. The problem, for example, with
That is true, but let's not delay improvements just because some people cannot benefit from it immediately. I think |
@fendor, does the following assist? As noted above, recent versions of Cabal (the library) offer the
configure-options:
$targets:
- --enable-build-info After a For example, with a 'plain vanilla' {
"cabal-lib-version": "3.8.1.0",
"compiler": {
"flavour": "ghc",
"compiler-id": "ghc-9.4.6",
"path": "C:\\Users\\mikep\\AppData\\Local\\Programs\\stack\\x86_64-windows\\ghc-9.4.6\\bin\\ghc-9.4.6.exe"
},
"components": [
{
"type": "lib",
"name": "lib",
"unit-id": "foo-0.1.0.0-RDnI1UeKkS9SDv3Gmnx7A",
"compiler-args": [
"-fbuilding-cabal-package",
"-O",
"-outputdir",
".stack-work\\dist\\51f21a8f\\build",
"-odir",
".stack-work\\dist\\51f21a8f\\build",
"-hidir",
".stack-work\\dist\\51f21a8f\\build",
"-stubdir",
".stack-work\\dist\\51f21a8f\\build",
"-i",
"-i.stack-work\\dist\\51f21a8f\\build",
"-isrc",
"-i.stack-work\\dist\\51f21a8f\\build\\autogen",
"-i.stack-work\\dist\\51f21a8f\\build\\global-autogen",
"-I.stack-work\\dist\\51f21a8f\\build\\autogen",
"-I.stack-work\\dist\\51f21a8f\\build\\global-autogen",
"-I.stack-work\\dist\\51f21a8f\\build",
"-IC:\\Users\\mikep\\AppData\\Local\\Programs\\stack\\x86_64-windows\\msys2-20230526\\mingw64\\include",
"-optP-include",
"-optP.stack-work\\dist\\51f21a8f\\build\\autogen\\cabal_macros.h",
"-this-unit-id",
"foo-0.1.0.0-RDnI1UeKkS9SDv3Gmnx7A",
"-hide-all-packages",
"-Wmissing-home-modules",
"-no-user-package-db",
"-package-db",
"C:\\sr\\snapshots\\3fe291b3\\pkgdb",
"-package-db",
"C:\\Users\\mikep\\Documents\\Code\\Haskell\\foo\\.stack-work\\install\\9bf47987\\pkgdb",
"-package-id",
"base-4.17.2.0",
"-XHaskell2010",
"-Wall",
"-Wcompat",
"-Widentities",
"-Wincomplete-record-updates",
"-Wincomplete-uni-patterns",
"-Wmissing-export-lists",
"-Wmissing-home-modules",
"-Wpartial-fields",
"-Wredundant-constraints"
],
"modules": [
"Lib",
"Paths_foo"
],
"src-files": [],
"hs-src-dirs": [
"src"
],
"src-dir": "C:\\Users\\mikep\\Documents\\Code\\Haskell\\foo\\",
"cabal-file": ".\\foo.cabal"
},
{
"type": "exe",
"name": "exe:foo-exe",
"unit-id": "foo-0.1.0.0-8kxBowjWnorJiiEogpBLXn-foo-exe",
"compiler-args": [
"-fbuilding-cabal-package",
"-O",
"-outputdir",
".stack-work\\dist\\51f21a8f\\build",
"-odir",
".stack-work\\dist\\51f21a8f\\build",
"-hidir",
".stack-work\\dist\\51f21a8f\\build",
"-stubdir",
".stack-work\\dist\\51f21a8f\\build",
"-i",
"-i.stack-work\\dist\\51f21a8f\\build",
"-iapp",
"-i.stack-work\\dist\\51f21a8f\\build\\foo-exe\\autogen",
"-i.stack-work\\dist\\51f21a8f\\build\\global-autogen",
"-I.stack-work\\dist\\51f21a8f\\build\\foo-exe\\autogen",
"-I.stack-work\\dist\\51f21a8f\\build\\global-autogen",
"-I.stack-work\\dist\\51f21a8f\\build",
"-IC:\\Users\\mikep\\AppData\\Local\\Programs\\stack\\x86_64-windows\\msys2-20230526\\mingw64\\include",
"-optP-include",
"-optP.stack-work\\dist\\51f21a8f\\build\\foo-exe\\autogen\\cabal_macros.h",
"-hide-all-packages",
"-Wmissing-home-modules",
"-no-user-package-db",
"-package-db",
"C:\\sr\\snapshots\\3fe291b3\\pkgdb",
"-package-db",
"C:\\Users\\mikep\\Documents\\Code\\Haskell\\foo\\.stack-work\\install\\9bf47987\\pkgdb",
"-package-id",
"base-4.17.2.0",
"-package-id",
"foo-0.1.0.0-RDnI1UeKkS9SDv3Gmnx7A",
"-XHaskell2010",
"-Wall",
"-Wcompat",
"-Widentities",
"-Wincomplete-record-updates",
"-Wincomplete-uni-patterns",
"-Wmissing-export-lists",
"-Wmissing-home-modules",
"-Wpartial-fields",
"-Wredundant-constraints",
"-threaded",
"-rtsopts",
"-with-rtsopts=-N"
],
"modules": [
"Paths_foo"
],
"src-files": [
"Main.hs"
],
"hs-src-dirs": [
"app"
],
"src-dir": "C:\\Users\\mikep\\Documents\\Code\\Haskell\\foo\\",
"cabal-file": ".\\foo.cabal"
}
]
} There is, currently, no Stack command-line equivalent of the configuration option above. However, it would be (I think) trivial to add a |
I think that works in general... The only disadvantage is that we can't load a component if one of its dependencies doesn't build due to type errors, I believe. It would be much nicer, if we had something like haskell/cabal#8726 in stack as well. However, I will play around with it, time to polish https://github.com/fendor/cabal-build-info/ |
@fendor, I did not follow what was the relevant part of haskell/cabal#8726. The initial post refers to a goal of starting GHCi with more than one package loaded. |
In the process of that PR, the author implemented the concept of a The |
@fendor, thanks. Adding here a link to the blog post on that topic: https://well-typed.com/blog/2023/03/cabal-multi-unit/. |
@fendor, I am returning to this issue. However, I realise that I am still not clear on what HLS needs from Stack. For example, if HLS currently (assuming nothing has moved on since July 2023) just harvests GHC options (using a shim) from |
Yes, exactly, that would work for us! |
@fendor, I have a draft and in the No doubt it will need to be further refined, including as I understand better what HLS needs/wants. Implementing it raised the following questions:
The output of my draft
I implemented Some other 'logging'-type information is still output to the standard error channel. |
So, for example:
generates, to standard error:
and, then, to standard output:
(In the Stack environment, There is no After a
|
Similarly, if a dependency is added to
and after building (when
|
Ok, so, working through this: (1)
We do override these options, so we are not interested, but I think there is still value to keep them in the output. (2) Yeah, HLS is definitely interested in the contents of this file. However, I am not quite sure if I understand the rest of the question correctly, HLS is, at the moment, not generating this CPP macros based on the package database, or anything like that. (3) We want to mirror Since Another thing we need is a list of modules that can be compiled with these flags. Even if The ghc-options for library also should have a One more thing, in multiple home unit sessions, we need to uphold the closure property. Since stack supports internal libraries, this is a thing we need to consider as well. |
Hi!
Setting the stage, Haskell Language Server's support for stack projects is currently lacking.
There are many reasons why using HLS with stack is a subpar experience.
I am trying to list the most important issues here, in the hope of better collaboration, so we can improve the developer experience with both HLS and stack.
Finding the compilation options of a filepath
Essentially, HLS is a compiler. As the compiler, it needs to know how to compile a component / file. Stack knows how to compile a file part of a stack project, and we want to extract that information.
The status quo is that we call a variation of
stack repl
with a special GHC shim that intercepts the ghc options whenstack repl
tries to invokeghc --interactive
. Then we use these options to compile the project ourselves.This works reasonably well, but has some shortcomings. Most notably, the issues:
Some of these are full-blown blockers and stack users have suffered in the past.
You can work around this using implicit-hie, which is its own can of worms, and not a proper solution for the needs of HLS.
What does HLS need
It is not a requirement for us to keep using this ugly hack of
stack repl
.What we fundamentally need is this:
Given a filepath, we need to be able to find the exact compilation options for it (preferably for the whole component it belongs to) in the quickest way possible, with as little work as possible. Additionally, the compilation options must be enough to actually compile the file. Potential configure hooks must have been run before HLS tries to compile the file.
In the light of multiple home units coming to cabal and ghc, we would like even a bit more, but I can't specify right now what exactly.
Going forward
To get this stuff sorted out, there are multiple ways. In Cabal, we've added a couple of months/years ago the
--enable-build-info
flag with writes outbuild-info.json
files containing the build information required to compile a component.If someone wants to collaborate on this, I'd be happy to give more information, maybe even in a sync call.
The text was updated successfully, but these errors were encountered: