Skip to content

Commit 69977b3

Browse files
committed
Add docs on Stack and VS Code
The use of the 'Haskell' extension for Visual Studio Code (VS Code), the extent of its current integration with Stack, and the possible implications of that for Stack's position relative to other build tools for Haskell (namely, Cabal (the tool)) have been the subject of some extensive discusion recently on the [Haskell Community](https://discourse.haskell.org/), under a number of Topics. This proposed pull request seeks to add documentation on Stack and VS Code and the current position. Its objective is to capture that there are current viable workarounds to the limitations and that future developments may see the extension able to work well with Stack.
1 parent 62ecfc9 commit 69977b3

File tree

2 files changed

+129
-0
lines changed

2 files changed

+129
-0
lines changed

doc/Stack_and_VS_Code.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<div class="hidden-warning"><a href="https://docs.haskellstack.org/"><img src="https://cdn.jsdelivr.net/gh/commercialhaskell/stack/doc/img/hidden-warning.svg"></a></div>
2+
3+
# Stack and Visual Studio Code
4+
5+
[Visual Studio Code](https://code.visualstudio.com/) (VS Code) is a popular
6+
source code editor, and
7+
['Haskell'](https://marketplace.visualstudio.com/items?itemName=haskell.haskell)
8+
is an extension for VS Code that is popular with Haskell coders.
9+
10+
The 'Haskell' extension can be used with Stack but there are some things to be
11+
aware of, set out below.
12+
13+
## Haskell Language Server
14+
15+
The VS Code extension makes use of the Haskell Language Server (HLS). To work,
16+
HLS has to be built with the same version of GHC that it will support. That is,
17+
a version of HLS is required for each version of GHC in use. It is possible that
18+
the most recent versions of GHC are not supported by HLS.
19+
20+
By default, the VS Code extension uses tools that are in the PATH. However, the
21+
extension's settings (under 'Haskell: Manage HLS') allow a user to specify
22+
that the extension should use a separate application,
23+
[GHCup](https://www.haskell.org/ghcup/), to download and install the versions of
24+
HLS that it needs. GHCup can download and install things other than HLS,
25+
including GHC, MSYS2 (on Windows), Cabal (a build tool), and Stack itself. GHCup
26+
can also update itself. On Windows, GHCup has the capability of using the
27+
Stack-supplied MSYS2 rather than installing a duplicate copy. Cabal (the build
28+
tool), like Stack, depends on the Cabal (the library). Cabal (the tool), unlike
29+
Stack, does not have the capability to automatically install necessary versions
30+
of GHC, and (as well as supporting the extension) GHCup fills a important gap
31+
for users of the Cabal tool.
32+
33+
If the VS Code extension is set not to use GHCup, its user needs to ensure that
34+
each version of HLS that the extension needs is on the PATH.
35+
36+
For the most part, the versions of HLS provided by GHCup are built with the same
37+
versions of GHC that Stack downloads from its default `setup-info` dictionary
38+
(see [YAML configuration: setup-info](yaml_configuration.md)). Stack's default
39+
is to mirror the 'official' binary distributions published by GHC. However, in
40+
some cases, it is possible that a GHCup-supplied and GHCup-selected HLS has been
41+
built with a different binary distribution of GHC than the one which Stack has
42+
installed.
43+
44+
One example of that occurred with the release of GHC 9.0.2. For some Linux users
45+
(Debian 9 and Fedora 27), the version of GHC 9.0.2 linked on GHC’s download
46+
[web page](https://www.haskell.org/ghc/download_ghc_9_0_2.html) was broken. The
47+
GHC developers made alternative ‘9.0.2a’ versions available. For a while, Stack
48+
referred to the versions published by GHC on its download web page while the
49+
GHCup-supplied versions of HLS were built using alternative versions. This
50+
incompatibility led to problems. It was resolved by Stack's default also being
51+
changed to refer to the '9.0.2a' versions. (Where Stack has already installed
52+
GHC 9.0.2, it is necessary to delete GHC 9.0.2 from the `stack path --programs`
53+
directory. This will cause Stack to reinstall the alternative version, when it
54+
first needs GHC 9.0.2. Stack should distinguish what it builds with the
55+
alternative from what it has built, and cached, with the original GHC 9.0.2.)
56+
57+
### Workaround #1
58+
59+
One workaround is to allow GHCup to install versions of GHC on the PATH and to
60+
cause Stack to use those versions of GHC, by making use of Stack's `install-ghc`
61+
option (which needs to be disabled) and Stack's `system-ghc` option (which needs
62+
to be enabled) (see [YAML configuration](yaml_configuration.md)).
63+
64+
For this workaround to work, each time that a resolver is used that references a
65+
different version of GHC, then GHCup must be used to install it (if GHCup has
66+
not already installed that version). For example, to use `resolver: lts-19.16`
67+
(GHC 9.0.2), the command `ghcup install ghc 9.0.2` must have been used to
68+
install GHC 9.0.2. That may be a minor inconvenience for some people, as one the
69+
primary benefits of Stack over other Haskell build tools has been that Stack
70+
automatically ensures that the necessary version of GHC is available.
71+
72+
It is hoped that the next release of Stack will include a new feature that will
73+
allow the VS Code extension/GHCup to customise Stack, so that Stack can
74+
automatically obtain versions of GHC using GHCup and switch between GHC versions
75+
that GHCup has obtained. It is hoped a future release of the extension/GHCup
76+
will take advantage of that new feature. See
77+
[Stack #5585](https://github.com/commercialhaskell/stack/pull/5585) and
78+
[GHCup #392](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/392).
79+
80+
### Workaround #2
81+
82+
Another partial workaround is to install GHCup so that it is 'empty' except for
83+
the current version of HLS, allow the VS Code extension to use GHCup to manage
84+
HLS requirements only, and to ignore any messages (if any) from the extension on
85+
start-up that installation of GHC, Cabal (the tool) and/or Stack are also
86+
necessary (they are not, if only Stack is being used).
87+
88+
For this workaround to work, however, there can be no differences between the
89+
version of GHC that the GHCup-supplied HLS was built with and the version that
90+
Stack has installed. A slight inconvenience here is also the posibility of false
91+
messages from the start-up that need to be ignored. In principle, those messages
92+
can be disabled by
93+
[setting the following](https://github.com/haskell/vscode-haskell#setting-a-specific-toolchain)
94+
for the VS Code extension:
95+
96+
~~~yaml
97+
"haskell.toolchain": {
98+
"ghc": null,
99+
"cabal": null,
100+
"stack": null
101+
}
102+
~~~
103+
104+
To install a version of GHCup that is 'empty' is a little more complicated than
105+
a default installation of GHCup.
106+
107+
On Unix-like operating systems, the following environment variable must be set
108+
before GHCup's installation `sh` script is run: `BOOTSTRAP_HASKELL_MINIMAL`.
109+
110+
On Windows, the second argument to the PowerShell script must be set to
111+
`$false`, namely:
112+
113+
Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;Invoke-Command -ScriptBlock ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -ArgumentList $true,$false
114+
115+
### Cradle
116+
117+
HLS may need a 'cradle' - an
118+
[`hie.yaml` file](https://hackage.haskell.org/package/hie-bios#stack) - in the
119+
project's root directory in order to work well.
120+
121+
The [`gen-hie` tool](https://hackage.haskell.org/package/implicit-hie) can help
122+
generate such a cradle.
123+
124+
### Tips
125+
126+
It has been suggested that a project must have been successfully built before
127+
the VS code extension (and HLS) is first activated on the project, for HLS to
128+
work reliably.

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pages:
2222
- Configuration (project and global): yaml_configuration.md
2323
- stack.yaml vs cabal package files: stack_yaml_vs_cabal_package_file.md
2424
- Build command: build_command.md
25+
- Stack and Visual Studio Code: Stack_and_VS_Code.md
2526
- Developing on Windows: developing_on_windows.md
2627
- Dependency visualization: dependency_visualization.md
2728
- Docker integration: docker_integration.md

0 commit comments

Comments
 (0)