diff --git a/docs/guide.md b/docs/guide.md index 99ef5575..1b986f00 100644 --- a/docs/guide.md +++ b/docs/guide.md @@ -105,6 +105,7 @@ This is the complete list of env variables that change GHCup behavior: On windows, there's additionally: * `GHCUP_MSYS2`: Has to point to the root of an existing MSYS2 installation (when installed by GHCup, that's e.g. `C:\ghcup\msys64`). GHCup bootstrap takes care of this usually. +* `GHCUP_MSYS2_ENV`: The [MSYS2 environment](https://www.msys2.org/docs/environments/) to use when executing e.g. `ghcup run --mingw-path`. Possible values are `MSYS`, `UCRT64`, `CLANG64`, `CLANGARM64`, `CLANG32`, `MINGW64`, `MINGW32`. Defauts to MINGW64, MINGW32 or CLANGARM64, depending on the architecture. ### XDG support @@ -508,7 +509,7 @@ See `ghcup compile ghc --help` for further information. Since ghcup version 0.1.20.0, we provide cross bindists for GHC JS and WASM. These can be installed conveniently. However, these are intended as a developer preview only. By using these GHC variants, you are implicitly signing up to participate in GHC development! -If you run into bugs or missing behavior, join the dev chat at https://matrix.to/#/#GHC:matrix.org. +If you run into bugs or missing behavior, join the dev chat at https://matrix.to/#/#GHC:matrix.org. First, add the cross release channel: diff --git a/lib/GHCup/Prelude/Process/Windows.hs b/lib/GHCup/Prelude/Process/Windows.hs index 22ef5290..23290f3d 100644 --- a/lib/GHCup/Prelude/Process/Windows.hs +++ b/lib/GHCup/Prelude/Process/Windows.hs @@ -263,12 +263,9 @@ createProcessWithMingwPath :: MonadIO m => CreateProcess -> m CreateProcess createProcessWithMingwPath cp = do - msys2Dir <- liftIO ghcupMsys2Dir cEnv <- Map.fromList <$> maybe (liftIO getEnvironment) pure (env cp) - let mingWPaths = [msys2Dir "mingw64" "bin" - ,msys2Dir "usr" "bin" - ] - paths = ["PATH", "Path"] + mingWPaths <- liftIO ghcupMsys2BinDirs' + let paths = ["PATH", "Path"] curPaths = (\x -> maybe [] splitSearchPath (Map.lookup x cEnv)) =<< paths newPath = intercalate [searchPathSeparator] (mingWPaths ++ curPaths) envWithoutPath = foldr (\x y -> Map.delete x y) cEnv paths @@ -276,11 +273,4 @@ createProcessWithMingwPath cp = do liftIO $ setEnv "Path" newPath pure $ cp { env = Just $ Map.toList envWithNewPath } -ghcupMsys2Dir :: IO FilePath -ghcupMsys2Dir = - lookupEnv "GHCUP_MSYS2" >>= \case - Just fp -> pure fp - Nothing -> do - baseDir <- liftIO ghcupBaseDir - pure (fromGHCupPath baseDir "msys64") diff --git a/lib/GHCup/Types.hs b/lib/GHCup/Types.hs index fa8a65da..48eede24 100644 --- a/lib/GHCup/Types.hs +++ b/lib/GHCup/Types.hs @@ -544,11 +544,23 @@ data Dirs = Dirs , dbDir :: GHCupPath , recycleDir :: GHCupPath -- mainly used on windows , tmpDir :: GHCupPath + , msys2Dir :: FilePath } deriving (Show, GHC.Generic) instance NFData Dirs +data MSYS2Env = MSYS + | UCRT64 + | CLANG64 + | CLANGARM64 + | CLANG32 + | MINGW64 + | MINGW32 + deriving (Eq, Show, Ord, GHC.Generic, Read) + +instance NFData MSYS2Env + data KeepDirs = Always | Errors | Never diff --git a/lib/GHCup/Utils.hs b/lib/GHCup/Utils.hs index 551e6795..2ca562b6 100644 --- a/lib/GHCup/Utils.hs +++ b/lib/GHCup/Utils.hs @@ -1155,7 +1155,7 @@ ensureShimGen -- | Ensure ghcup directory structure exists. ensureDirectories :: Dirs -> IO () -ensureDirectories (Dirs baseDir binDir cacheDir logsDir confDir trashDir dbDir tmpDir) = do +ensureDirectories (Dirs baseDir binDir cacheDir logsDir confDir trashDir dbDir tmpDir _) = do createDirRecursive' (fromGHCupPath baseDir) createDirRecursive' (fromGHCupPath baseDir "ghc") createDirRecursive' (fromGHCupPath baseDir "hls") diff --git a/lib/GHCup/Utils/Dirs.hs b/lib/GHCup/Utils/Dirs.hs index 838341ea..68b8310e 100644 --- a/lib/GHCup/Utils/Dirs.hs +++ b/lib/GHCup/Utils/Dirs.hs @@ -32,6 +32,8 @@ module GHCup.Utils.Dirs , getConfigFilePath' , useXDG , cleanupTrash + , ghcupMsys2BinDirs + , ghcupMsys2BinDirs' , GHCupPath , appendGHCupPath @@ -136,6 +138,7 @@ import GHC.IO.Exception ( IOErrorType(NoSuchThing) ) import Haskus.Utils.Variant.Excepts import Optics hiding ( uncons ) import Safe +import System.Info import System.Directory hiding ( removeDirectory , removeDirectoryRecursive , removePathForcibly @@ -338,6 +341,48 @@ ghcupTMPDir else ghcupBaseDir <&> (\(GHCupPath gp) -> GHCupPath (gp "tmp")) +ghcupMsys2Dir :: IO FilePath +ghcupMsys2Dir = + lookupEnv "GHCUP_MSYS2" >>= \case + Just fp -> pure fp + Nothing -> do + baseDir <- liftIO ghcupBaseDir + pure (fromGHCupPath baseDir "msys64") + +ghcupMsys2BinDirs :: (MonadFail m, MonadIO m, MonadReader env m, HasDirs env) => m [FilePath] +ghcupMsys2BinDirs = do + Dirs{..} <- getDirs + liftIO $ ghcupMsys2BinDirs_ msys2Dir + +ghcupMsys2BinDirs' :: IO [FilePath] +ghcupMsys2BinDirs' = do + msys2Dir <- ghcupMsys2Dir + ghcupMsys2BinDirs_ msys2Dir + +ghcupMsys2BinDirs_ :: FilePath -> IO [FilePath] +ghcupMsys2BinDirs_ msys2Dir' = do + env <- liftIO (lookupEnv "GHCUP_MSYS2_ENV") >>= \case + Just env -> maybe (fail parseFailMsg) pure $ readMay @MSYS2Env env + Nothing + | "x86_64" <- arch -> pure MINGW64 + | "i386" <- arch -> pure MINGW32 + | "aarch64" <- arch -> pure CLANGARM64 + | otherwise -> fail "No compatible architecture for msys2" + pure [msys2Dir' toEnvDir env, msys2Dir' toEnvDir MSYS] + where + -- https://www.msys2.org/docs/environments/ + toEnvDir :: MSYS2Env -> FilePath + toEnvDir MSYS = "usr" + toEnvDir UCRT64 = "ucrt64" + toEnvDir CLANG64 = "clang64" + toEnvDir CLANGARM64 = "clangarm64" + toEnvDir CLANG32 = "clang32" + toEnvDir MINGW64 = "mingw64" + toEnvDir MINGW32 = "mingw32" + + parseFailMsg = "Invalid value for GHCUP_MSYS2_ENV. Valid values are: MSYS, UCRT64, CLANG64, CLANGARM64, CLANG32, MINGW64, MINGW32" + + getAllDirs :: IO Dirs getAllDirs = do baseDir <- ghcupBaseDir @@ -348,6 +393,7 @@ getAllDirs = do recycleDir <- ghcupRecycleDir tmpDir <- ghcupTMPDir dbDir <- ghcupDbDir + msys2Dir <- ghcupMsys2Dir pure Dirs { .. } diff --git a/scripts/bootstrap/bootstrap-haskell b/scripts/bootstrap/bootstrap-haskell index e145c1c3..16decc30 100755 --- a/scripts/bootstrap/bootstrap-haskell +++ b/scripts/bootstrap/bootstrap-haskell @@ -20,6 +20,7 @@ # * BOOTSTRAP_HASKELL_ADJUST_CABAL_CONFIG - whether to adjust mingw paths in cabal.config on windows # * BOOTSTRAP_HASKELL_DOWNLOADER - which downloader to use (default: curl) # * GHCUP_BASE_URL - the base url for ghcup binary download (use this to overwrite https://downloads.haskell.org/~ghcup with a mirror) +# * GHCUP_MSYS2_ENV - the msys2 environment to use on windows, see https://www.msys2.org/docs/environments/ (defauts to MINGW64, MINGW32 or CLANGARM64, depending on the architecture) # License: LGPL-3.0 @@ -27,6 +28,15 @@ # safety subshell to avoid executing anything in case this script is not downloaded properly ( +die() { + if [ -n "${NO_COLOR}" ] ; then + (>&2 printf "%s\\n" "$1") + else + (>&2 printf "\\033[0;31m%s\\033[0m\\n" "$1") + fi + exit 2 +} + plat="$(uname -s)" arch=$(uname -m) ghver="0.1.20.0" @@ -55,18 +65,40 @@ case "${plat}" in ;; esac +case "${GHCUP_MSYS2_ENV}" in + "") + case "${arch}" in + x86_64|amd64) + GHCUP_MSYS2_ENV_DIR="mingw64" ;; + i*86) + GHCUP_MSYS2_ENV_DIR="mingw32" ;; + aarch64|arm64) + GHCUP_MSYS2_ENV_DIR="clangarm64" ;; + *) die "Unknown architecture: ${arch}" ;; + esac + ;; + MSYS) + GHCUP_MSYS2_ENV_DIR="usr" ;; + UCRT64) + GHCUP_MSYS2_ENV_DIR="ucrt64" ;; + CLANG64) + GHCUP_MSYS2_ENV_DIR="clang64" ;; + CLANGARM64) + GHCUP_MSYS2_ENV_DIR="clangarm64" ;; + CLANG32) + GHCUP_MSYS2_ENV_DIR="clang32" ;; + MINGW64) + GHCUP_MSYS2_ENV_DIR="mingw64" ;; + MINGW32) + GHCUP_MSYS2_ENV_DIR="mingw32" ;; + *) + die "Invalid value for GHCUP_MSYS2_ENV. Valid values are: MSYS, UCRT64, CLANG64, CLANGARM64, CLANG32, MINGW64, MINGW32" ;; +esac + : "${BOOTSTRAP_HASKELL_GHC_VERSION:=recommended}" : "${BOOTSTRAP_HASKELL_CABAL_VERSION:=recommended}" -die() { - if [ -n "${NO_COLOR}" ] ; then - (>&2 printf "%s\\n" "$1") - else - (>&2 printf "\\033[0;31m%s\\033[0m\\n" "$1") - fi - exit 2 -} warn() { if [ -n "${NO_COLOR}" ] ; then @@ -591,7 +623,7 @@ adjust_cabal_config() { else cabal_bin="$HOME/AppData/Roaming/cabal/bin" fi - ecabal user-config -a "extra-prog-path: $(cygpath -w "$GHCUP_BIN"), $(cygpath -w "$cabal_bin"), $(cygpath -w "$GHCUP_MSYS2"/mingw64/bin), $(cygpath -w "$GHCUP_MSYS2"/usr/bin)" -a "extra-include-dirs: $(cygpath -w "$GHCUP_MSYS2"/mingw64/include)" -a "extra-lib-dirs: $(cygpath -w "$GHCUP_MSYS2"/mingw64/lib)" -f init + ecabal user-config -a "extra-prog-path: $(cygpath -w "$GHCUP_BIN"), $(cygpath -w "$cabal_bin"), $(cygpath -w "$GHCUP_MSYS2"/${GHCUP_MSYS2_ENV_DIR}/bin), $(cygpath -w "$GHCUP_MSYS2"/usr/bin)" -a "extra-include-dirs: $(cygpath -w "$GHCUP_MSYS2"/${GHCUP_MSYS2_ENV_DIR}/include)" -a "extra-lib-dirs: $(cygpath -w "$GHCUP_MSYS2"/${GHCUP_MSYS2_ENV_DIR}/lib)" -f init } ask_cabal_config_init() { diff --git a/scripts/bootstrap/bootstrap-haskell.ps1 b/scripts/bootstrap/bootstrap-haskell.ps1 index 7e2cc2c4..0da990cf 100644 --- a/scripts/bootstrap/bootstrap-haskell.ps1 +++ b/scripts/bootstrap/bootstrap-haskell.ps1 @@ -46,7 +46,9 @@ param ( # Whether to disable creation of several desktop shortcuts [switch]$DontWriteDesktopShortcuts, # Whether to disable adjusting bashrc (in msys2 env) with PATH - [switch]$DontAdjustBashRc + [switch]$DontAdjustBashRc, + # The msys2 environment to use, see https://www.msys2.org/docs/environments/ (defauts to MINGW64, MINGW32 or CLANGARM64, depending on the architecture) + [string]$Msys2Env ) $DefaultMsys2Version = "20221216" @@ -653,10 +655,15 @@ if (!($DontAdjustBashRc)) { $AdjustBashRcExport = 'export BOOTSTRAP_HASKELL_ADJUST_BASHRC=1 ;' } +if (!($Msys2Env)) { + $Msys2EnvExport = ('export GHCUP_MSYS2_ENV={0} ;' -f $Msys2Env) + $null = [Environment]::SetEnvironmentVariable("GHCUP_MSYS2_ENV", $Msys2Env, [System.EnvironmentVariableTarget]::User) +} + if ((Get-Process -ID $PID).ProcessName.StartsWith("bootstrap-haskell") -Or $InBash) { - Exec "$Bash" '-lc' ('{4} {6} {7} {8} {9} {10} {12} [ -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* ]] && {11} {0} | bash || cat $(cygpath -m ''{0}'') | bash' -f $BootstrapUrl, $MsysDir, $GhcupBasePrefix, $GhcupDir, $SilentExport, $CabalDirFull, $StackInstallExport, $HLSInstallExport, $AdjustCabalConfigExport, $MinimalExport, $BootstrapDownloader, $DownloadScript, $AdjustBashRcExport) + Exec "$Bash" '-lc' ('{4} {6} {7} {8} {9} {10} {12} {13} [ -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* ]] && {11} {0} | bash || cat $(cygpath -m ''{0}'') | bash' -f $BootstrapUrl, $MsysDir, $GhcupBasePrefix, $GhcupDir, $SilentExport, $CabalDirFull, $StackInstallExport, $HLSInstallExport, $AdjustCabalConfigExport, $MinimalExport, $BootstrapDownloader, $DownloadScript, $AdjustBashRcExport, $Msys2EnvExport) } else { - Exec "$Msys2Shell" '-mingw64' '-mintty' '-shell' 'bash' '-c' ('{4} {6} {7} {8} {9} {10} {12} [ -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* ]] && {11} {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, $MinimalExport, $BootstrapDownloader, $DownloadScript, $AdjustBashRcExport) + Exec "$Msys2Shell" '-mingw64' '-mintty' '-shell' 'bash' '-c' ('{4} {6} {7} {8} {9} {10} {12} {13} [ -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* ]] && {11} {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, $MinimalExport, $BootstrapDownloader, $DownloadScript, $AdjustBashRcExport, $Msys2EnvExport) }