|
| 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. |
0 commit comments