From 72a6e971ab9dd3453fc2a05498efa5915814d135 Mon Sep 17 00:00:00 2001 From: Julian Ospald Date: Fri, 6 Aug 2021 20:12:15 +0200 Subject: [PATCH] Integrate stack better --- README.md | 48 +++++++++++++++++++++------- bootstrap-haskell | 42 ++++++++++++++++++++++--- bootstrap-haskell.ps1 | 31 +++++++++++++++--- ghcup-0.0.6.yaml | 64 ++++++++++++++++++++++++++++++++++++-- hooks/stack/ghc-install.sh | 23 ++++++++++++++ 5 files changed, 184 insertions(+), 24 deletions(-) create mode 100644 hooks/stack/ghc-install.sh diff --git a/README.md b/README.md index a209df5..e457aca 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ Similar in scope to [rustup](https://github.com/rust-lang-nursery/rustup.rs), [p * [Env variables](#env-variables) * [Installing custom bindists](#installing-custom-bindists) * [Tips and tricks](#tips-and-tricks) + * [Stack hooks](#stack-hooks) + * [Sharing MSys2 between stack and ghcup](#sharing-msys2-between-stack-and-ghcup) * [Design goals](#design-goals) * [How](#how) * [Known users](#known-users) @@ -139,6 +141,10 @@ This is the complete list of env variables that change GHCup behavior: * `GHCUP_SKIP_UPDATE_CHECK`: Skip the (possibly annoying) update check when you run a command * `CC`/`LD` etc.: full environment is passed to the build system when compiling GHC via GHCup +On windows, there are additional variables: + +* `GHCUP_MSYS2`: where to find msys2, so we can invoke shells and other cool stuff + ### Installing custom bindists There are a couple of good use cases to install custom bindists: @@ -202,6 +208,36 @@ with_ghc 8.10.5 code path/to/haskell/source Cabal and HLS will now see `8.10.5` as the primary GHC, without the need to run `ghcup set` all the time when switching between projects. +### Stack hooks + +GHCup distributes a patched Stack, which has support for custom installation hooks, see: + +* https://github.com/commercialhaskell/stack/pull/5585 + +Usually, the bootstrap script will already install a hook for you. If not, +download it [here](https://gitlab.haskell.org/haskell/ghcup-hs/-/tree/master/hooks/stack/ghc-install.sh), +place it in `~/.stack/hooks/ghc-install.sh` and make sure it's executable. + +Hooks aren't run when `system-ghc: true` is set in `stack.yaml`. If you want stack +to never fall back to its own installation logic if ghcup fails, run the following command: + +```sh +stack config set install-ghc false --global +``` + +### Sharing MSys2 between stack and ghcup + +You can tell stack to use GHCup's MSys2 installation. Add the following lines to `~/.stack/config.yaml`: + +```yml +skip-msys: true +extra-path: + - "C:\\ghcup\\msys64\\usr\\bin" + - "C:\\ghcup\\msys64\\mingw64\\bin" +extra-include-dirs: "C:\\ghcup\\msys64\\mingw64\\include" +extra-lib-dirs: "C:\\ghcup\\msys64\\mingw64\\lib" +``` + ## Design goals 1. simplicity @@ -278,18 +314,6 @@ to figure out whether you have the correct toolchain and the correct dependencies. Refer to [the official docs](https://ghc.haskell.org/trac/ghc/wiki/Building/Preparation/Linux) on how to prepare your environment for building GHC. -### Stack support - -There may be a number of bugs when trying to make ghcup installed GHC versions work with stack, -such as: - -- https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/188 - -Further, stack's upgrade procedure may break/confuse ghcup. There are a number of integration -issues discussed here: - -- https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/153 - ### Windows support Windows support is in early stages. Since windows doesn't support symbolic links properly, diff --git a/bootstrap-haskell b/bootstrap-haskell index cebbe41..9e90810 100755 --- a/bootstrap-haskell +++ b/bootstrap-haskell @@ -8,6 +8,7 @@ # * BOOTSTRAP_HASKELL_GHC_VERSION - the ghc version to install # * BOOTSTRAP_HASKELL_CABAL_VERSION - the cabal version to install # * BOOTSTRAP_HASKELL_INSTALL_STACK - whether to install latest stack +# * BOOTSTRAP_HASKELL_INSTALL_STACK_HOOK - whether to install stack hook as well # * BOOTSTRAP_HASKELL_INSTALL_HLS - whether to install latest hls # * BOOTSTRAP_HASKELL_ADJUST_BASHRC - whether to adjust PATH in bashrc (prepend) # * BOOTSTRAP_HASKELL_ADJUST_CABAL_CONFIG - whether to adjust mingw paths in cabal.config on windows @@ -508,17 +509,25 @@ ask_hls() { ask_stack() { if [ -n "${BOOTSTRAP_HASKELL_INSTALL_STACK}" ] ; then - return 1 + if [ -n "${BOOTSTRAP_HASKELL_INSTALL_STACK_HOOK}" ] ; then + return 2 + else + return 1 + fi fi if [ -z "${BOOTSTRAP_HASKELL_NONINTERACTIVE}" ] ; then echo "-------------------------------------------------------------------------------" - warn "Do you want to install stack?" + warn "Do you want to install stack and stack hooks?" + warn "" warn "Stack is a haskell build tool similar to cabal that is used by some projects." warn "Also see https://docs.haskellstack.org/" warn "" - warn "[Y] Yes [N] No [?] Help (default is \"N\")." + warn "Stack hooks allow stack to use ghcup for GHC installation (usually stack handles" + warn "installation itself, leading to possibly duplicated GHC versions)." + warn "" + warn "[Y] Yes, with hooks [L] Yes, no hooks [N] No [?] Help (default is \"N\")." warn "" while true; do @@ -526,13 +535,16 @@ ask_stack() { case $stack_answer in [Yy]*) + return 2 ;; + [Ll]*) return 1 ;; [Nn]* | "") return 0 ;; *) echo "Possible choices are:" echo - echo "Y - Yes, install stack" + echo "Y - Yes, install stack with hooks" + echo "L - Yes, install stack without hooks" echo "N - No, don't install anything more (default)" echo echo "Please make your choice and press ENTER." @@ -636,7 +648,27 @@ esac case $ask_stack_answer in 1) - _eghcup --cache install stack || warn "Stack installation failed, continuing anyway" + { + _eghcup --cache install stack + edo stack update + } || warn "Stack installation failed, continuing anyway" + ;; + 2) + { + _eghcup --cache install stack + edo stack update + if [ -n "${STACK_ROOT}" ] ; then + stack_root=$STACK_ROOT + else + stack_root=${HOME}/.stack + fi + edo mkdir -p "${stack_root}/hooks/" + edo curl -Lf "https://www.haskell.org/ghcup/sh/hooks/stack/ghc-install.sh" > "${stack_root}/hooks/ghc-install.sh" + edo chmod +x "${stack_root}/hooks/ghc-install.sh" + edo stack config set system-ghc false --global + edo stack config set install-ghc false --global + + } || warn "Stack installation failed, continuing anyway" ;; *) ;; esac diff --git a/bootstrap-haskell.ps1 b/bootstrap-haskell.ps1 index ae5f966..324ca89 100644 --- a/bootstrap-haskell.ps1 +++ b/bootstrap-haskell.ps1 @@ -29,6 +29,8 @@ param ( [switch]$InBash, # Whether to install stack as well [switch]$InstallStack, + # Whether to install stack hooks as well + [switch]$InstallStackHook, # Whether to install hls as well [switch]$InstallHLS, # Skip adjusting cabal.config with mingw paths @@ -223,6 +225,7 @@ $null = [Environment]::SetEnvironmentVariable("GHCUP_INSTALL_BASE_PREFIX", $Ghcu $GhcupDir = ('{0}\ghcup' -f $GhcupBasePrefix) +$StackDir = ('{0}\sr' -f $GhcupBasePrefix) $MsysDir = ('{0}\msys64' -f $GhcupDir) $Bash = ('{0}\usr\bin\bash' -f $MsysDir) if (!($BootstrapUrl)) { @@ -310,15 +313,28 @@ if (!($InstallHLS)) { } # ask whether to install stack +$InstallStackDoc = @' +Do you want to install stack and stack hooks? + +Stack is a haskell build tool similar to cabal that is used by some projects. +Also see https://docs.haskellstack.org/ + +Stack hooks allow stack to use ghcup for GHC installation (usually stack handles +installation itself, leading to possibly duplicated GHC versions). +'@ if (!($InstallStack)) { if (!($Silent)) { $StackDecision = $Host.UI.PromptForChoice('Install stack' - , 'Do you want to install stack as well?' - , [System.Management.Automation.Host.ChoiceDescription[]] @('&Yes' + , $InstallStackDoc + , [System.Management.Automation.Host.ChoiceDescription[]] @('&Yes, with hooks' + '&Light install, without hooks' '&No' - '&Abort'), 1) + '&Abort'), 2) if ($StackDecision -eq 0) { + $InstallStack = $true + $InstallStackHook = $true + } elseif ($StackDecision -eq 1) { $InstallStack = $true } elseif ($StackDecision -eq 2) { Exit 0 @@ -499,6 +515,11 @@ $SilentExport = 'export BOOTSTRAP_HASKELL_NONINTERACTIVE=1 ;' if ($InstallStack) { $StackInstallExport = 'export BOOTSTRAP_HASKELL_INSTALL_STACK=1 ;' + $null = [Environment]::SetEnvironmentVariable("STACK_ROOT", $StackDir, [System.EnvironmentVariableTarget]::User) +} + +if ($InstallStackHook) { + $StackInstallHookExport = 'export BOOTSTRAP_HASKELL_INSTALL_STACK_HOOK=1 ;' } if ($InstallHLS) { @@ -510,9 +531,9 @@ if (!($NoAdjustCabalConfig)) { } if ((Get-Process -ID $PID).ProcessName.StartsWith("bootstrap-haskell") -Or $InBash) { - Exec "$Bash" '-lc' ('{4} {6} {7} {8} [ -n ''{1}'' ] && export GHCUP_MSYS2=$(cygpath -m ''{1}'') ; [ -n ''{2}'' ] && export GHCUP_INSTALL_BASE_PREFIX=$(cygpath -m ''{2}/'') ; export PATH=$(cygpath -u ''{3}/bin''):$PATH ; export CABAL_DIR=''{5}'' ; [[ ''{0}'' = https* ]] && curl --proto ''=https'' --tlsv1.2 -sSf {0} | bash || cat $(cygpath -m ''{0}'') | bash' -f $BootstrapUrl, $MsysDir, $GhcupBasePrefix, $GhcupDir, $SilentExport, $CabalDirFull, $StackInstallExport, $HLSInstallExport, $AdjustCabalConfigExport) + Exec "$Bash" '-lc' ('{4} {6} {7} {8} {9} [ -n ''{1}'' ] && export GHCUP_MSYS2=$(cygpath -m ''{1}'') ; [ -n ''{2}'' ] && export GHCUP_INSTALL_BASE_PREFIX=$(cygpath -m ''{2}/'') ; export PATH=$(cygpath -u ''{3}/bin''):$PATH ; export CABAL_DIR=''{5}'' ; export STACK_ROOT=$(cygpath -m ''{10}/'') ; [[ ''{0}'' = https* ]] && curl --proto ''=https'' --tlsv1.2 -sSf {0} | bash || cat $(cygpath -m ''{0}'') | bash' -f $BootstrapUrl, $MsysDir, $GhcupBasePrefix, $GhcupDir, $SilentExport, $CabalDirFull, $StackInstallExport, $HLSInstallExport, $AdjustCabalConfigExport, $StackInstallHookExport, $StackDir) } else { - Exec "$Msys2Shell" '-mingw64' '-mintty' '-c' ('{4} {6} {7} {8} [ -n ''{1}'' ] && export GHCUP_MSYS2=$(cygpath -m ''{1}'') ; [ -n ''{2}'' ] && export GHCUP_INSTALL_BASE_PREFIX=$(cygpath -m ''{2}/'') ; export PATH=$(cygpath -u ''{3}/bin''):$PATH ; export CABAL_DIR=''{5}'' ; trap ''echo Press any key to exit && read -n 1 && exit'' 2 ; [[ ''{0}'' = https* ]] && curl --proto ''=https'' --tlsv1.2 -sSf {0} | bash || cat $(cygpath -m ''{0}'') | bash ; echo ''Press any key to exit'' && read -n 1' -f $BootstrapUrl, $MsysDir, $GhcupBasePrefix, $GhcupDir, $SilentExport, $CabalDirFull, $StackInstallExport, $HLSInstallExport, $AdjustCabalConfigExport) + Exec "$Msys2Shell" '-mingw64' '-mintty' '-c' ('{4} {6} {7} {8} {9} [ -n ''{1}'' ] && export GHCUP_MSYS2=$(cygpath -m ''{1}'') ; [ -n ''{2}'' ] && export GHCUP_INSTALL_BASE_PREFIX=$(cygpath -m ''{2}/'') ; export PATH=$(cygpath -u ''{3}/bin''):$PATH ; export CABAL_DIR=''{5}'' ; export STACK_ROOT=$(cygpath -m ''{10}/'') ; trap ''echo Press any key to exit && read -n 1 && exit'' 2 ; [[ ''{0}'' = https* ]] && curl --proto ''=https'' --tlsv1.2 -sSf {0} | bash || cat $(cygpath -m ''{0}'') | bash ; echo ''Press any key to exit'' && read -n 1' -f $BootstrapUrl, $MsysDir, $GhcupBasePrefix, $GhcupDir, $SilentExport, $CabalDirFull, $StackInstallExport, $HLSInstallExport, $AdjustCabalConfigExport, $StackInstallHookExport, $StackDir) } diff --git a/ghcup-0.0.6.yaml b/ghcup-0.0.6.yaml index 10ae9d2..13d734b 100644 --- a/ghcup-0.0.6.yaml +++ b/ghcup-0.0.6.yaml @@ -2206,8 +2206,7 @@ ghcupDownloads: unknown_versioning: *stack-271-64 2.7.3: viTags: - - Latest - - Recommended + - old viChangeLog: https://github.com/commercialhaskell/stack/blob/master/ChangeLog.md#v273 viPostInstall: *stack-post viArch: @@ -2232,4 +2231,65 @@ ghcupDownloads: RegexDir: "stack-.*" Linux_Alpine: unknown_versioning: *stack-273-64 + 2.7.3.1: + viTags: + - Latest + - Recommended + viChangeLog: https://github.com/commercialhaskell/stack/blob/master/ChangeLog.md#v273 + viPostInstall: &stack-post-new | + Stack manages GHC versions internally by default. It can also use hooks to automatically + install and locate GHC versions utilizing GHCup: + https://gitlab.haskell.org/haskell/ghcup-hs#stack-hooks + Alternatively, you can also tell stack to use the system GHC version (whatever is in PATH): + stack config set system-ghc true --global + + If you want stack to use GHCup's provided MSys2, follow the instructions here (not recommended): + https://gitlab.haskell.org/haskell/ghcup-hs/-/tree/stack-fork#sharing-msys2-between-stack-and-ghcup + + Also check out: https://docs.haskellstack.org/en/stable/yaml_configuration + + !!! GHCup ships a patched version of stack. Before reporting bugs to stack developers !!! + !!! make sure it is reproducible with the original stack version: !!! + !!! https://docs.haskellstack.org/en/stable/install_and_upgrade/ !!! + viArch: + A_64: + Linux_UnknownLinux: + unknown_versioning: &stack-2731-64 + dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/stack/2.7.3.1/stack-2.7.3.1-linux-x86_64.tar.gz + dlSubdir: + RegexDir: "stack-.*" + dlHash: 7c10090d568651208b6d6c003c8d78ef79099f4b472aea5ca800f3e4a7a1c6ce + Darwin: + unknown_versioning: + dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/stack/2.7.3.1/stack-2.7.3.1-osx-x86_64.tar.gz + dlSubdir: + RegexDir: "stack-.*" + dlHash: 23030868be377d62ed324332d239ddd915b12f7a64c887f297e1b60a3f65894f + Windows: + unknown_versioning: + dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/stack/2.7.3.1/stack-2.7.3.1-windows-x86_64.tar.bz2 + dlHash: 983ac24219370cdf220f47f9edb17d0aeb831a1253fd777d322fd1bff358c511 + Linux_Alpine: + unknown_versioning: *stack-2731-64 + FreeBSD: + unknown_versioning: + dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/stack/2.7.3.1/stack-2.7.3.1-freebsd-x86_64.tar.gz + dlHash: b6b1eb59981b8c1d3a04b061f03296b1540ecbadbc34cbd4fe712a575a155ee9 + A_32: + Linux_UnknownLinux: + unknown_versioning: &stack-2731-32 + dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/stack/2.7.3.1/stack-2.7.3.1-linux-i386.tar.gz + dlHash: da2081d84517d16a8216e929582dd39caa19643c819b77c6f68f138bd177a758 + Linux_Alpine: + unknown_versioning: *stack-2731-32 + A_ARM64: + Linux_UnknownLinux: + unknown_versioning: + dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/stack/2.7.3.1/stack-2.7.3.1-linux-aarch64.tar.gz + dlHash: 0e1789852a476dd87f495fa0b481309398b2bafc00cf7c8d980c91977b39d9a6 + A_ARM: + Linux_UnknownLinux: + unknown_versioning: + dlUri: https://downloads.haskell.org/ghcup/unofficial-bindists/stack/2.7.3.1/stack-2.7.3.1-linux-armv7.tar.gz + dlHash: 13d61616c169615d80381ea0c84e13540410b736a553565cd48d10b4d2bd7f23 diff --git a/hooks/stack/ghc-install.sh b/hooks/stack/ghc-install.sh new file mode 100644 index 0000000..01ee76d --- /dev/null +++ b/hooks/stack/ghc-install.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +set -eu + +case $HOOK_GHC_TYPE in + bindist) + ghcup --offline whereis ghc $HOOK_GHC_VERSION || { + ghcup --cache install ghc $HOOK_GHC_VERSION && ghcup whereis ghc $HOOK_GHC_VERSION + } + ;; + git) + >&2 echo "Hook doesn't support installing from source." + >&2 echo "Consider enabling stack GHC installs for this project, via:" + >&2 echo " stack config set install-ghc true" + exit 1 + ;; + *) + >&2 echo "Unsupported GHC installation type: ${HOOK_GHC_TYPE}." + >&2 echo "Consider enabling stack GHC installs for this project, via:" + >&2 echo " stack config set install-ghc true" + exit 2 + ;; +esac