This is a more in-depth guide specific to GHCup.
ghcup --help is your friend.
For the simple interactive TUI (not available on windows), run:
For the full functionality via cli:
# list available ghc/cabal versions ghcup list # install the recommended GHC version ghcup install ghc # install a specific GHC version ghcup install ghc 8.2.2 # set the currently "active" GHC version ghcup set ghc 8.4.4 # install cabal-install ghcup install cabal # update ghcup itself ghcup upgrade
Tags and shortcuts
GHCup has a number of tags and version shortcuts, that can be used as arguments to install/set etc.
All of the following are valid arguments to
ghcup install ghc:
If the argument is omitted, the default is
For man pages to work you need man-db as your
man provider, then issue
man ghc. Manpages only work for the currently set ghc.
MANPATH may be required to be unset.
Shell completions are in scripts/shell-completions directory of this repository.
For bash: install
/etc/bash_completion.d/ghcup (depending on distro)
and make sure your bashrc sources the startup script
/usr/share/bash-completion/bash_completion on some distros).
ghcup is very portable. There are a few exceptions though:
ghcup tuiis only available on non-windows platforms
- legacy subcommands
ghcup install(without a tool identifier) and
ghcup install-cabalmay be removed in the future
A configuration file can be put in
~/.ghcup/config.yaml. The default config file
explaining all possible configurations can be found in this repo: config.yaml.
Partial configuration is fine. Command line options always override the config file settings.
This is the complete list of env variables that change GHCup behavior:
GHCUP_USE_XDG_DIRS: see XDG support above
GHCUP_INSTALL_BASE_PREFIX: the base of ghcup (default:
GHCUP_CURL_OPTS: additional options that can be passed to curl
GHCUP_WGET_OPTS: additional options that can be passed to wget
GHCUP_GPG_OPTS: additional options that can be passed to gpg
GHCUP_SKIP_UPDATE_CHECK: Skip the (possibly annoying) update check when you run a command
LDetc.: full environment is passed to the build system when compiling GHC via GHCup
To enable XDG style directories, set the environment variable
GHCUP_USE_XDG_DIRS to anything.
Then you can control the locations via XDG environment variables as such:
XDG_DATA_HOME: GHCs will be unpacked in
XDG_CACHE_HOME: logs and download files will be stored in
XDG_BIN_HOME: binaries end up here (default:
XDG_CONFIG_HOME: the config file is stored in
ghcup makes some assumptions about structure of files in
XDG_BIN_HOME. So if you have other tools
installing e.g. stack/cabal/ghc into it, this will likely clash. In that case consider disabling XDG support.
GHCup has a few caching mechanisms to avoid redownloads. All cached files end up in
~/.ghcup/cache by default.
Downloaded tarballs (such as GHC, cabal, etc.) are not cached by default unless you pass
ghcup --cache or set caching
in your config via
ghcup config set cache true.
The metadata files (also see github.com/haskell/ghcup-metadata)
have a 5 minutes cache per default depending on the last access time of the file. That means if you run
ghcup list 10 times in a row, only the first time will trigger a download attempt.
Clearing the cache
If you experience problems, consider clearing the cache via
ghcup gc --cache.
The metadata are the files that describe tool versions, where to download them etc. and can be viewed here: https://github.com/haskell/ghcup-metadata
GHCup allows to use custom mirrors/download-info hosted by yourself or 3rd parties.
To use a mirror, set the following option in
url-source: # Accepts file/http/https scheme OwnSource: "https://some-url/ghcup-0.0.6.yaml"
See config.yaml for more options.
Alternatively you can do it via a cli switch:
ghcup --url-source=https://some-url/ghcup-0.0.6.yaml list
A release channel is basically just a metadata file location. You can add additional release channels that complement the default one, such as the prerelease channel like so:
ghcup config add-release-channel https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.7.yaml
This will result in
~/.ghcup/config.yaml to contain this record:
url-source: AddSource: - Right: https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.7.yaml
You can add as many channels as you like. They are combined under Last, so versions from the prerelease channel here overwrite the default ones, if any.
To remove the channel, delete the entire
url-source section or set it back to the default:
url-source: GHCupURL: 
If you want to combine your release channel with a mirror, you'd do it like so:
url-source: OwnSource: # base metadata - "https://mirror.sjtu.edu.cn/ghcup/yaml/ghcup/data/ghcup-0.0.6.yaml" # prerelease channel - "https://raw.githubusercontent.com/haskell/ghcup-metadata/master/ghcup-prereleases-0.0.7.yaml"
More on installation
Installing custom bindists
There are a couple of good use cases to install custom bindists:
- manually built bindists (e.g. with patches)
ghcup install ghc -u 'file:///home/mearwald/tmp/ghc-eff-patches/ghc-8.10.2-x86_64-deb10-linux.tar.xz' 8.10.2-eff
- GHC head CI bindists
ghcup install ghc -u 'https://gitlab.haskell.org/api/v4/projects/1/jobs/artifacts/master/raw/ghc-x86_64-fedora27-linux.tar.xz?job=validate-x86_64-linux-fedora27' head
- DWARF bindists
ghcup install ghc -u 'https://downloads.haskell.org/~ghc/8.10.2/ghc-8.10.2-x86_64-deb10-linux-dwarf.tar.xz' 8.10.2-dwarf
Since the version parser is pretty lax,
head are both valid versions
and produce the binaries
GHCup always needs to know which version the bindist corresponds to (this is not automatically
Compiling GHC from source
Compiling from source is supported for both source tarballs and arbitrary git refs. See
ghcup compile ghc --help
for a list of all available options.
If you need to overwrite the existing
build.mk, check the default files
in data/build_mk, copy them somewhere, adjust them and
--config path/to/build.mk to
ghcup compile ghc.
build.mk options are explained here.
Make sure your system meets all the prerequisites.
ghcup can compile and install a cross GHC for any target. However, this requires that the build host has a complete cross toolchain and various libraries installed for the target platform.
Consult the GHC documentation on the prerequisites.
For distributions with non-standard locations of cross toolchain and
libraries, this may need some tweaking of
build.mk or configure args.
ghcup compile ghc --help for further information.
Before using isolated installs, make sure to have at least GHCup version 0.1.17.8!
Ghcup also enables you to install a tool (GHC, Cabal, HLS, Stack) at an isolated location of your choosing. These installs, as the name suggests, are separate from your main installs and DO NOT conflict with them.
No symlinks are made to these isolated installed tools, you'd have to manually point to them wherever you intend to use them.
These installs, can also NOT be deleted from ghcup, you'd have to go and manually delete these.
You need to use the
-i flag followed by the directory path.
install an isolated GHC version at location /home/user/isolated_dir/ghc/
ghcup install ghc 8.10.5 --isolate /home/user/isolated_dir/ghc
isolated install Cabal at a location you desire
ghcup install cabal --isolate /home/username/my_isolated_dir/
do an isolated install with a custom bindist
ghcup install ghc --isolate /home/username/my_isolated_dir/ -u 'https://gitlab.haskell.org/api/v4/projects/1/jobs/artifacts/master/raw/ghc-x86_64-fedora27-linux.tar.xz?job=validate-x86_64-linux-fedora27' head
isolated install HLS
ghcup install hls --isolate /home/username/dir/hls/
you can even compile ghc to an isolated location.
ghcup compile ghc -j 4 -v 9.0.1 -b 8.10.5 -i /home/username/my/dir/ghc
On windows, ghcup can be installed automatically on a CI runner non-interactively like so:
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 $false,$true,$true,$false,$false,$false,$false,"C:\"
On linux/darwin/freebsd, run the following on your runner:
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_MINIMAL=1 sh
This will just install
ghcup and on windows additionally
For the full list of env variables and parameters to tweak the script behavior, see:
On github workflows you can use https://github.com/haskell/actions/. GHCup itself is also pre-installed on all platforms, but may use non-standard install locations.
GHCup supports verifying the GPG signature of the metadata file. The metadata file then contains SHA256 hashes of all downloads, so this is cryptographically secure.
First, obtain the gpg keys:
gpg --batch --keyserver keys.openpgp.org --recv-keys 7784930957807690A66EBDBE3786C5262ECB4A3F gpg --batch --keyserver keyserver.ubuntu.com --recv-keys FE5AB6C91FEA597C3B31180B73EDE9E8CFBAEF01
Then verify the gpg key in one of these ways:
- find out where I live and visit me to do offline key signing
- figure out my mobile phone number and call me to verify the fingerprint
- more boring: contact me on Libera IRC (
maerwald) and verify the fingerprint
Once you've verified the key, you have to figure out if you trust me.
If you trust me, then you can configure gpg in
gpg-setting: GPGLax # GPGStrict | GPGLax | GPGNone
GPGStrict mode, ghcup will fail if verification fails. In
GPGLax mode it will just print a warning.
You can also pass the mode via
ghcup --gpg <strict|lax|none>.
Tips and tricks
If you don't want to explicitly switch the active GHC all the time and are using
tools that rely on the plain
ghc binary, GHCup provides an easy way to execute
commands with a certain toolchain prepended to PATH, e.g.:
ghcup run --ghc 8.10.7 --cabal latest --hls latest --stack latest --install -- code Setup.hs
This will execute vscode with GHC set to 8.10.7 and all other tools to their latest version.