Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
5787a662ed
|
|||
|
fce654f3c7
|
|||
|
0f052c3465
|
|||
|
a34d9b7b89
|
|||
|
4e62f559fa
|
|||
|
8c3d2b6740
|
|||
|
b6779f4d75
|
|||
|
b036c9861f
|
|||
|
02cd773c2a
|
|||
|
3964d06f5d
|
|||
|
|
e83612a06c | ||
|
cf6c666b59
|
|||
|
ee0ec370c7
|
|||
|
ea0e35ddf0
|
|||
|
99c8501d47
|
|||
|
f8a1fed1f2
|
|||
|
9ad1f7cb97
|
|||
|
0856a96738
|
|||
|
ee9801a8c2
|
|||
|
cfecc11b43
|
|||
|
3d36348563
|
|||
|
dcbee9c7dc
|
|||
|
2d88b1197e
|
|||
|
6c12dc0d6f
|
|||
|
a4b69f29dc
|
|||
|
1680c5c448
|
|||
|
e74fb45680
|
|||
|
d19ab05a11
|
|||
|
433c73b23c
|
|||
|
2aa5211886
|
|||
|
81e7c02807
|
|||
|
a2373f2056
|
|||
|
ba8e4f6ac6
|
|||
|
76acc9a5f5
|
11
CHANGELOG.md
11
CHANGELOG.md
@@ -1,6 +1,14 @@
|
|||||||
# Revision history for ghcup
|
# Revision history for ghcup
|
||||||
|
|
||||||
## 0.1.17.6 -- ????-??-??
|
## 0.1.17.8 -- XXXX-XX-XX
|
||||||
|
|
||||||
|
* Re-enable upgrade functionality for all configurations wrt [#250](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/250)
|
||||||
|
|
||||||
|
## 0.1.17.7 -- 2022-04-21
|
||||||
|
|
||||||
|
* Fix `ghcup run` on windows wrt [#345](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/345)
|
||||||
|
|
||||||
|
## 0.1.17.6 -- 2022-03-18
|
||||||
|
|
||||||
* Vastly improve shell completions wrt [#242](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/242)
|
* Vastly improve shell completions wrt [#242](https://gitlab.haskell.org/haskell/ghcup-hs/-/merge_requests/242)
|
||||||
* Fix 'ghcup install cabal/hls/stack --set' wrt [#324](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/324)
|
* Fix 'ghcup install cabal/hls/stack --set' wrt [#324](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/324)
|
||||||
@@ -10,6 +18,7 @@
|
|||||||
* Add `--no-set` to install commands, fixes [#330](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/330)
|
* Add `--no-set` to install commands, fixes [#330](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/330)
|
||||||
* Fix serious bug in `ghcup list --raw-format -t <tool> -c installed`
|
* Fix serious bug in `ghcup list --raw-format -t <tool> -c installed`
|
||||||
* Overhaul metadata merging and add `ghcup config add-release-channel URI` wrt [#328](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/328)
|
* Overhaul metadata merging and add `ghcup config add-release-channel URI` wrt [#328](https://gitlab.haskell.org/haskell/ghcup-hs/-/issues/328)
|
||||||
|
* Fix max path issues on windows with `ghcup run`
|
||||||
|
|
||||||
## 0.1.17.5 -- 2022-02-26
|
## 0.1.17.5 -- 2022-02-26
|
||||||
|
|
||||||
|
|||||||
@@ -437,6 +437,7 @@ install' _ (_, ListResult {..}) = do
|
|||||||
, TarDirDoesNotExist
|
, TarDirDoesNotExist
|
||||||
, FileAlreadyExistsError
|
, FileAlreadyExistsError
|
||||||
, ProcessError
|
, ProcessError
|
||||||
|
, GHCupShadowed
|
||||||
]
|
]
|
||||||
|
|
||||||
run (do
|
run (do
|
||||||
@@ -452,7 +453,7 @@ install' _ (_, ListResult {..}) = do
|
|||||||
liftE $ installCabalBin lVer Nothing False $> (vi, dirs, ce)
|
liftE $ installCabalBin lVer Nothing False $> (vi, dirs, ce)
|
||||||
GHCup -> do
|
GHCup -> do
|
||||||
let vi = snd <$> getLatest dls GHCup
|
let vi = snd <$> getLatest dls GHCup
|
||||||
liftE $ upgradeGHCup Nothing False $> (vi, dirs, ce)
|
liftE $ upgradeGHCup Nothing False False $> (vi, dirs, ce)
|
||||||
HLS -> do
|
HLS -> do
|
||||||
let vi = getVersionInfo lVer HLS dls
|
let vi = getVersionInfo lVer HLS dls
|
||||||
liftE $ installHLSBin lVer Nothing False $> (vi, dirs, ce)
|
liftE $ installHLSBin lVer Nothing False $> (vi, dirs, ce)
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ data Command
|
|||||||
| Config ConfigCommand
|
| Config ConfigCommand
|
||||||
| Whereis WhereisOptions WhereisCommand
|
| Whereis WhereisOptions WhereisCommand
|
||||||
#ifndef DISABLE_UPGRADE
|
#ifndef DISABLE_UPGRADE
|
||||||
| Upgrade UpgradeOpts Bool
|
| Upgrade UpgradeOpts Bool Bool
|
||||||
#endif
|
#endif
|
||||||
| ToolRequirements ToolReqOpts
|
| ToolRequirements ToolReqOpts
|
||||||
| ChangeLog ChangeLogOptions
|
| ChangeLog ChangeLogOptions
|
||||||
@@ -222,18 +222,18 @@ com =
|
|||||||
(info (List <$> listOpts <**> helper)
|
(info (List <$> listOpts <**> helper)
|
||||||
(progDesc "Show available GHCs and other tools")
|
(progDesc "Show available GHCs and other tools")
|
||||||
)
|
)
|
||||||
#ifndef DISABLE_UPGRADE
|
|
||||||
<> command
|
<> command
|
||||||
"upgrade"
|
"upgrade"
|
||||||
(info
|
(info
|
||||||
( (Upgrade <$> upgradeOptsP <*> switch
|
( (Upgrade <$> upgradeOptsP <*> switch
|
||||||
(short 'f' <> long "force" <> help "Force update")
|
(short 'f' <> long "force" <> help "Force update")
|
||||||
|
<*> switch
|
||||||
|
(long "fail-if-shadowed" <> help "Fails after upgrading if the upgraded ghcup binary is shadowed by something else in PATH (useful for CI)")
|
||||||
)
|
)
|
||||||
<**> helper
|
<**> helper
|
||||||
)
|
)
|
||||||
(progDesc "Upgrade ghcup")
|
(progDesc "Upgrade ghcup")
|
||||||
)
|
)
|
||||||
#endif
|
|
||||||
<> command
|
<> command
|
||||||
"compile"
|
"compile"
|
||||||
( Compile
|
( Compile
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ hlsCompileOpts =
|
|||||||
(short 'g' <> long "git-ref" <> metavar "GIT_REFERENCE" <> help
|
(short 'g' <> long "git-ref" <> metavar "GIT_REFERENCE" <> help
|
||||||
"The git commit/branch/ref to build from"
|
"The git commit/branch/ref to build from"
|
||||||
) <*>
|
) <*>
|
||||||
optional (option str (short 'r' <> long "repository" <> metavar "GIT_REPOSITORY" <> help "The git repository to build from (defaults to GHC upstream)"
|
optional (option str (short 'r' <> long "repository" <> metavar "GIT_REPOSITORY" <> help "The git repository to build from (defaults to HLS upstream)"
|
||||||
<> completer (gitFileUri ["https://github.com/haskell/haskell-language-server.git"])
|
<> completer (gitFileUri ["https://github.com/haskell/haskell-language-server.git"])
|
||||||
))
|
))
|
||||||
)))
|
)))
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ data RunOptions = RunOptions
|
|||||||
, runHLSVer :: Maybe ToolVersion
|
, runHLSVer :: Maybe ToolVersion
|
||||||
, runStackVer :: Maybe ToolVersion
|
, runStackVer :: Maybe ToolVersion
|
||||||
, runBinDir :: Maybe FilePath
|
, runBinDir :: Maybe FilePath
|
||||||
|
, runQuick :: Bool
|
||||||
, runCOMMAND :: [String]
|
, runCOMMAND :: [String]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +122,8 @@ runOpts =
|
|||||||
<> completer (bashCompleter "directory")
|
<> completer (bashCompleter "directory")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
<*> switch
|
||||||
|
(short 'q' <> long "quick" <> help "Avoid any expensive work (such as downloads, version/tag resolution etc.). Disables --install.")
|
||||||
<*> many (argument str (metavar "COMMAND" <> help "The command to run, with arguments (use longopts --). If omitted, just prints the created bin/ dir to stdout and exits."))
|
<*> many (argument str (metavar "COMMAND" <> help "The command to run, with arguments (use longopts --). If omitted, just prints the created bin/ dir to stdout and exits."))
|
||||||
|
|
||||||
|
|
||||||
@@ -219,29 +222,15 @@ run :: forall m.
|
|||||||
-> (ReaderT LeanAppState m () -> m ())
|
-> (ReaderT LeanAppState m () -> m ())
|
||||||
-> m ExitCode
|
-> m ExitCode
|
||||||
run RunOptions{..} runAppState leanAppstate runLogger = do
|
run RunOptions{..} runAppState leanAppstate runLogger = do
|
||||||
r <- if or (fmap (maybe False isToolTag) [runGHCVer, runCabalVer, runHLSVer, runStackVer]) || runInstTool'
|
r <- if not runQuick
|
||||||
then runRUN runAppState $ do
|
then runRUN runAppState $ do
|
||||||
toolchain <- liftE resolveToolchainFull
|
toolchain <- liftE resolveToolchainFull
|
||||||
tmp <- case runBinDir of
|
tmp <- liftIO $ createTmpDir toolchain
|
||||||
Just bindir -> do
|
|
||||||
liftIO $ createDirRecursive' bindir
|
|
||||||
liftIO $ canonicalizePath bindir
|
|
||||||
Nothing -> do
|
|
||||||
d <- liftIO $ predictableTmpDir toolchain
|
|
||||||
liftIO $ createDirRecursive' d
|
|
||||||
liftIO $ canonicalizePath d
|
|
||||||
liftE $ installToolChainFull toolchain tmp
|
liftE $ installToolChainFull toolchain tmp
|
||||||
pure tmp
|
pure tmp
|
||||||
else runLeanRUN leanAppstate $ do
|
else runLeanRUN leanAppstate $ do
|
||||||
toolchain <- resolveToolchain
|
toolchain <- resolveToolchain
|
||||||
tmp <- case runBinDir of
|
tmp <- liftIO $ createTmpDir toolchain
|
||||||
Just bindir -> do
|
|
||||||
liftIO $ createDirRecursive' bindir
|
|
||||||
liftIO $ canonicalizePath bindir
|
|
||||||
Nothing -> do
|
|
||||||
d <- liftIO $ predictableTmpDir toolchain
|
|
||||||
liftIO $ createDirRecursive' d
|
|
||||||
liftIO $ canonicalizePath d
|
|
||||||
liftE $ installToolChain toolchain tmp
|
liftE $ installToolChain toolchain tmp
|
||||||
pure tmp
|
pure tmp
|
||||||
case r of
|
case r of
|
||||||
@@ -269,9 +258,16 @@ run RunOptions{..} runAppState leanAppstate runLogger = do
|
|||||||
|
|
||||||
where
|
where
|
||||||
|
|
||||||
isToolTag :: ToolVersion -> Bool
|
createTmpDir :: Toolchain -> IO FilePath
|
||||||
isToolTag (ToolTag _) = True
|
createTmpDir toolchain =
|
||||||
isToolTag _ = False
|
case runBinDir of
|
||||||
|
Just bindir -> do
|
||||||
|
createDirRecursive' bindir
|
||||||
|
canonicalizePath bindir
|
||||||
|
Nothing -> do
|
||||||
|
d <- predictableTmpDir toolchain
|
||||||
|
createDirRecursive' d
|
||||||
|
canonicalizePath d
|
||||||
|
|
||||||
-- TODO: doesn't work for cross
|
-- TODO: doesn't work for cross
|
||||||
resolveToolchainFull :: ( MonadFail m
|
resolveToolchainFull :: ( MonadFail m
|
||||||
|
|||||||
@@ -65,9 +65,10 @@ upgradeOptsP =
|
|||||||
flag'
|
flag'
|
||||||
UpgradeInplace
|
UpgradeInplace
|
||||||
(short 'i' <> long "inplace" <> help
|
(short 'i' <> long "inplace" <> help
|
||||||
"Upgrade ghcup in-place (wherever it's at)"
|
"Upgrade ghcup in-place"
|
||||||
)
|
)
|
||||||
<|> ( UpgradeAt
|
<|>
|
||||||
|
( UpgradeAt
|
||||||
<$> option
|
<$> option
|
||||||
str
|
str
|
||||||
(short 't' <> long "target" <> metavar "TARGET_DIR" <> help
|
(short 't' <> long "target" <> metavar "TARGET_DIR" <> help
|
||||||
@@ -92,6 +93,7 @@ type UpgradeEffects = '[ DigestError
|
|||||||
, FileDoesNotExistError
|
, FileDoesNotExistError
|
||||||
, CopyError
|
, CopyError
|
||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
|
, GHCupShadowed
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -120,18 +122,19 @@ upgrade :: ( Monad m
|
|||||||
)
|
)
|
||||||
=> UpgradeOpts
|
=> UpgradeOpts
|
||||||
-> Bool
|
-> Bool
|
||||||
|
-> Bool
|
||||||
-> Dirs
|
-> Dirs
|
||||||
-> (forall a. ReaderT AppState m (VEither UpgradeEffects a) -> m (VEither UpgradeEffects a))
|
-> (forall a. ReaderT AppState m (VEither UpgradeEffects a) -> m (VEither UpgradeEffects a))
|
||||||
-> (ReaderT LeanAppState m () -> m ())
|
-> (ReaderT LeanAppState m () -> m ())
|
||||||
-> m ExitCode
|
-> m ExitCode
|
||||||
upgrade uOpts force' Dirs{..} runAppState runLogger = do
|
upgrade uOpts force' fatal Dirs{..} runAppState runLogger = do
|
||||||
target <- case uOpts of
|
target <- case uOpts of
|
||||||
UpgradeInplace -> Just <$> liftIO getExecutablePath
|
UpgradeInplace -> Just <$> liftIO getExecutablePath
|
||||||
(UpgradeAt p) -> pure $ Just p
|
(UpgradeAt p) -> pure $ Just p
|
||||||
UpgradeGHCupDir -> pure (Just (binDir </> "ghcup" <> exeExt))
|
UpgradeGHCupDir -> pure (Just (binDir </> "ghcup" <> exeExt))
|
||||||
|
|
||||||
runUpgrade runAppState (do
|
runUpgrade runAppState (do
|
||||||
v' <- liftE $ upgradeGHCup target force'
|
v' <- liftE $ upgradeGHCup target force' fatal
|
||||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
pure (v', dls)
|
pure (v', dls)
|
||||||
) >>= \case
|
) >>= \case
|
||||||
|
|||||||
@@ -141,9 +141,7 @@ main = do
|
|||||||
)
|
)
|
||||||
let listCommands = infoOption
|
let listCommands = infoOption
|
||||||
("install set rm install-cabal list"
|
("install set rm install-cabal list"
|
||||||
#ifndef DISABLE_UPGRADE
|
|
||||||
<> " upgrade"
|
<> " upgrade"
|
||||||
#endif
|
|
||||||
<> " compile debug-info tool-requirements changelog"
|
<> " compile debug-info tool-requirements changelog"
|
||||||
)
|
)
|
||||||
( long "list-commands"
|
( long "list-commands"
|
||||||
@@ -245,14 +243,10 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
|||||||
alreadyInstalling' <- alreadyInstalling optCommand newTool
|
alreadyInstalling' <- alreadyInstalling optCommand newTool
|
||||||
when (not alreadyInstalling') $
|
when (not alreadyInstalling') $
|
||||||
case t of
|
case t of
|
||||||
#ifdef DISABLE_UPGRADE
|
|
||||||
GHCup -> pure ()
|
|
||||||
#else
|
|
||||||
GHCup -> runLogger $
|
GHCup -> runLogger $
|
||||||
logWarn ("New GHCup version available: "
|
logWarn ("New GHCup version available: "
|
||||||
<> prettyVer l
|
<> prettyVer l
|
||||||
<> ". To upgrade, run 'ghcup upgrade'")
|
<> ". To upgrade, run 'ghcup upgrade'")
|
||||||
#endif
|
|
||||||
_ -> runLogger $
|
_ -> runLogger $
|
||||||
logWarn ("New "
|
logWarn ("New "
|
||||||
<> T.pack (prettyShow t)
|
<> T.pack (prettyShow t)
|
||||||
@@ -296,26 +290,24 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
|||||||
s' <- appState
|
s' <- appState
|
||||||
liftIO $ brickMain s' >> pure ExitSuccess
|
liftIO $ brickMain s' >> pure ExitSuccess
|
||||||
#endif
|
#endif
|
||||||
Install installCommand -> install installCommand settings appState runLogger
|
Install installCommand -> install installCommand settings appState runLogger
|
||||||
InstallCabalLegacy iopts -> install (Left (InstallCabal iopts)) settings appState runLogger
|
InstallCabalLegacy iopts -> install (Left (InstallCabal iopts)) settings appState runLogger
|
||||||
Set setCommand -> set setCommand runAppState runLeanAppState runLogger
|
Set setCommand -> set setCommand runAppState runLeanAppState runLogger
|
||||||
UnSet unsetCommand -> unset unsetCommand runLeanAppState runLogger
|
UnSet unsetCommand -> unset unsetCommand runLeanAppState runLogger
|
||||||
List lo -> list lo no_color runAppState
|
List lo -> list lo no_color runAppState
|
||||||
Rm rmCommand -> rm rmCommand runAppState runLogger
|
Rm rmCommand -> rm rmCommand runAppState runLogger
|
||||||
DInfo -> dinfo runAppState runLogger
|
DInfo -> dinfo runAppState runLogger
|
||||||
Compile compileCommand -> compile compileCommand settings dirs runAppState runLogger
|
Compile compileCommand -> compile compileCommand settings dirs runAppState runLogger
|
||||||
Config configCommand -> config configCommand settings keybindings runLogger
|
Config configCommand -> config configCommand settings keybindings runLogger
|
||||||
Whereis whereisOptions
|
Whereis whereisOptions
|
||||||
whereisCommand -> whereis whereisCommand whereisOptions runAppState leanAppstate runLogger
|
whereisCommand -> whereis whereisCommand whereisOptions runAppState leanAppstate runLogger
|
||||||
#ifndef DISABLE_UPGRADE
|
Upgrade uOpts force' fatal -> upgrade uOpts force' fatal dirs runAppState runLogger
|
||||||
Upgrade uOpts force' -> upgrade uOpts force' dirs runAppState runLogger
|
ToolRequirements topts -> toolRequirements topts runAppState runLogger
|
||||||
#endif
|
ChangeLog changelogOpts -> changelog changelogOpts runAppState runLogger
|
||||||
ToolRequirements topts -> toolRequirements topts runAppState runLogger
|
Nuke -> nuke appState runLogger
|
||||||
ChangeLog changelogOpts -> changelog changelogOpts runAppState runLogger
|
Prefetch pfCom -> prefetch pfCom runAppState runLogger
|
||||||
Nuke -> nuke appState runLogger
|
GC gcOpts -> gc gcOpts runAppState runLogger
|
||||||
Prefetch pfCom -> prefetch pfCom runAppState runLogger
|
Run runCommand -> run runCommand appState leanAppstate runLogger
|
||||||
GC gcOpts -> gc gcOpts runAppState runLogger
|
|
||||||
Run runCommand -> run runCommand appState leanAppstate runLogger
|
|
||||||
|
|
||||||
case res of
|
case res of
|
||||||
ExitSuccess -> pure ()
|
ExitSuccess -> pure ()
|
||||||
@@ -353,9 +345,7 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
|
|||||||
(HLS, ver) = cmp' HLS (Just $ ToolVersion (mkTVer over)) ver
|
(HLS, ver) = cmp' HLS (Just $ ToolVersion (mkTVer over)) ver
|
||||||
alreadyInstalling (Compile (CompileHLS HLSCompileOptions{ targetHLS = Left tver }))
|
alreadyInstalling (Compile (CompileHLS HLSCompileOptions{ targetHLS = Left tver }))
|
||||||
(HLS, ver) = cmp' HLS (Just $ ToolVersion (mkTVer tver)) ver
|
(HLS, ver) = cmp' HLS (Just $ ToolVersion (mkTVer tver)) ver
|
||||||
#ifndef DISABLE_UPGRADE
|
alreadyInstalling (Upgrade _ _ _) (GHCup, _) = pure True
|
||||||
alreadyInstalling (Upgrade _ _) (GHCup, _) = pure True
|
|
||||||
#endif
|
|
||||||
alreadyInstalling _ _ = pure False
|
alreadyInstalling _ _ = pure False
|
||||||
|
|
||||||
cmp' :: ( HasLog env
|
cmp' :: ( HasLog env
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ source-repository-package
|
|||||||
|
|
||||||
constraints: http-io-streams -brotli,
|
constraints: http-io-streams -brotli,
|
||||||
any.Cabal ==3.6.2.0,
|
any.Cabal ==3.6.2.0,
|
||||||
any.aeson >= 2.0.1.0
|
any.aeson >= 2.0.1.0,
|
||||||
|
-- https://github.com/typeable/generic-arbitrary/issues/14
|
||||||
|
any.generic-arbitrary < 0.2.1
|
||||||
|
|
||||||
package libarchive
|
package libarchive
|
||||||
flags: -system-libarchive
|
flags: -system-libarchive
|
||||||
|
|||||||
208
docs/guide.md
208
docs/guide.md
@@ -1,6 +1,6 @@
|
|||||||
# User Guide
|
# User Guide
|
||||||
|
|
||||||
`ghcup --help` is your friend.
|
This is a more in-depth guide specific to GHCup. `ghcup --help` is your friend.
|
||||||
|
|
||||||
## Basic usage
|
## Basic usage
|
||||||
|
|
||||||
@@ -43,13 +43,6 @@ All of the following are valid arguments to `ghcup install ghc`:
|
|||||||
|
|
||||||
If the argument is omitted, the default is `recommended`.
|
If the argument is omitted, the default is `recommended`.
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
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](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/data/config.yaml).
|
|
||||||
|
|
||||||
Partial configuration is fine. Command line options always override the config file settings.
|
|
||||||
|
|
||||||
## Manpages
|
## Manpages
|
||||||
|
|
||||||
For man pages to work you need [man-db](http://man-db.nongnu.org/) as your `man` provider, then issue `man ghc`. Manpages only work for the currently set ghc.
|
For man pages to work you need [man-db](http://man-db.nongnu.org/) as your `man` provider, then issue `man ghc`. Manpages only work for the currently set ghc.
|
||||||
@@ -64,6 +57,47 @@ as e.g. `/etc/bash_completion.d/ghcup` (depending on distro)
|
|||||||
and make sure your bashrc sources the startup script
|
and make sure your bashrc sources the startup script
|
||||||
(`/usr/share/bash-completion/bash_completion` on some distros).
|
(`/usr/share/bash-completion/bash_completion` on some distros).
|
||||||
|
|
||||||
|
## Portability
|
||||||
|
|
||||||
|
`ghcup` is very portable. There are a few exceptions though:
|
||||||
|
|
||||||
|
1. `ghcup tui` is only available on non-windows platforms
|
||||||
|
2. legacy subcommands `ghcup install` (without a tool identifier) and `ghcup install-cabal` may be removed in the future
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
|
||||||
|
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](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/data/config.yaml).
|
||||||
|
|
||||||
|
Partial configuration is fine. Command line options always override the config file settings.
|
||||||
|
|
||||||
|
## Env variables
|
||||||
|
|
||||||
|
This is the complete list of env variables that change GHCup behavior:
|
||||||
|
|
||||||
|
* `GHCUP_USE_XDG_DIRS`: see [XDG support](#xdg-support) above
|
||||||
|
* `TMPDIR`: where ghcup does the work (unpacking, building, ...)
|
||||||
|
* `GHCUP_INSTALL_BASE_PREFIX`: the base of ghcup (default: `$HOME`)
|
||||||
|
* `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
|
||||||
|
* `CC`/`LD` etc.: full environment is passed to the build system when compiling GHC via GHCup
|
||||||
|
|
||||||
|
### XDG support
|
||||||
|
|
||||||
|
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 `ghcup/ghc` subdir (default: `~/.local/share`)
|
||||||
|
* `XDG_CACHE_HOME`: logs and download files will be stored in `ghcup` subdir (default: `~/.cache`)
|
||||||
|
* `XDG_BIN_HOME`: binaries end up here (default: `~/.local/bin`)
|
||||||
|
* `XDG_CONFIG_HOME`: the config file is stored in `ghcup` subdir as `config.yaml` (default: `~/.config`)
|
||||||
|
|
||||||
|
**Note that `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.**
|
||||||
|
|
||||||
## Caching
|
## Caching
|
||||||
|
|
||||||
GHCup has a few caching mechanisms to avoid redownloads. All cached files end up in `~/.ghcup/cache` by default.
|
GHCup has a few caching mechanisms to avoid redownloads. All cached files end up in `~/.ghcup/cache` by default.
|
||||||
@@ -83,6 +117,92 @@ have a 5 minutes cache per default depending on the last access time of the file
|
|||||||
|
|
||||||
If you experience problems, consider clearing the cache via `ghcup gc --cache`.
|
If you experience problems, consider clearing the cache via `ghcup gc --cache`.
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
|
||||||
|
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](https://github.com/haskell/ghcup-metadata)
|
||||||
|
|
||||||
|
### Mirrors
|
||||||
|
|
||||||
|
GHCup allows to use custom mirrors/download-info hosted by yourself or 3rd parties.
|
||||||
|
|
||||||
|
To use a mirror, set the following option in `~/.ghcup/config.yaml`:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
url-source:
|
||||||
|
# Accepts file/http/https scheme
|
||||||
|
OwnSource: "https://some-url/ghcup-0.0.6.yaml"
|
||||||
|
```
|
||||||
|
|
||||||
|
See [config.yaml](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/data/config.yaml)
|
||||||
|
for more options.
|
||||||
|
|
||||||
|
Alternatively you can do it via a cli switch:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ghcup --url-source=https://some-url/ghcup-0.0.6.yaml list
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Known mirrors
|
||||||
|
|
||||||
|
1. [https://mirror.sjtu.edu.cn/docs/ghcup](https://mirror.sjtu.edu.cn/docs/ghcup)
|
||||||
|
|
||||||
|
### (Pre-)Release channels
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
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:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
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:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
url-source:
|
||||||
|
GHCupURL: []
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to combine your release channel with a mirror, you'd do it like so:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
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:
|
||||||
|
|
||||||
|
1. manually built bindists (e.g. with patches)
|
||||||
|
- example: `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`
|
||||||
|
2. GHC head CI bindists
|
||||||
|
- example: `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`
|
||||||
|
3. DWARF bindists
|
||||||
|
- example: `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, `8.10.2-eff` and `head` are both valid versions
|
||||||
|
and produce the binaries `ghc-8.10.2-eff` and `ghc-head` respectively.
|
||||||
|
GHCup always needs to know which version the bindist corresponds to (this is not automatically
|
||||||
|
detected).
|
||||||
|
|
||||||
## Compiling GHC from source
|
## Compiling GHC from source
|
||||||
|
|
||||||
Compiling from source is supported for both source tarballs and arbitrary git refs. See `ghcup compile ghc --help`
|
Compiling from source is supported for both source tarballs and arbitrary git refs. See `ghcup compile ghc --help`
|
||||||
@@ -106,74 +226,6 @@ For distributions with non-standard locations of cross toolchain and
|
|||||||
libraries, this may need some tweaking of `build.mk` or configure args.
|
libraries, this may need some tweaking of `build.mk` or configure args.
|
||||||
See `ghcup compile ghc --help` for further information.
|
See `ghcup compile ghc --help` for further information.
|
||||||
|
|
||||||
## XDG support
|
|
||||||
|
|
||||||
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 `ghcup/ghc` subdir (default: `~/.local/share`)
|
|
||||||
* `XDG_CACHE_HOME`: logs and download files will be stored in `ghcup` subdir (default: `~/.cache`)
|
|
||||||
* `XDG_BIN_HOME`: binaries end up here (default: `~/.local/bin`)
|
|
||||||
* `XDG_CONFIG_HOME`: the config file is stored in `ghcup` subdir as `config.yaml` (default: `~/.config`)
|
|
||||||
|
|
||||||
**Note that `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.**
|
|
||||||
|
|
||||||
## Env variables
|
|
||||||
|
|
||||||
This is the complete list of env variables that change GHCup behavior:
|
|
||||||
|
|
||||||
* `GHCUP_USE_XDG_DIRS`: see [XDG support](#xdg-support) above
|
|
||||||
* `TMPDIR`: where ghcup does the work (unpacking, building, ...)
|
|
||||||
* `GHCUP_INSTALL_BASE_PREFIX`: the base of ghcup (default: `$HOME`)
|
|
||||||
* `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
|
|
||||||
* `CC`/`LD` etc.: full environment is passed to the build system when compiling GHC via GHCup
|
|
||||||
|
|
||||||
## Installing custom bindists
|
|
||||||
|
|
||||||
There are a couple of good use cases to install custom bindists:
|
|
||||||
|
|
||||||
1. manually built bindists (e.g. with patches)
|
|
||||||
- example: `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`
|
|
||||||
2. GHC head CI bindists
|
|
||||||
- example: `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`
|
|
||||||
3. DWARF bindists
|
|
||||||
- example: `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, `8.10.2-eff` and `head` are both valid versions
|
|
||||||
and produce the binaries `ghc-8.10.2-eff` and `ghc-head` respectively.
|
|
||||||
GHCup always needs to know which version the bindist corresponds to (this is not automatically
|
|
||||||
detected).
|
|
||||||
|
|
||||||
## Mirrors
|
|
||||||
|
|
||||||
GHCup allows to use custom mirrors/download-info hosted by yourself or 3rd parties.
|
|
||||||
|
|
||||||
To use a mirror, set the following option in `~/.ghcup/config.yaml`:
|
|
||||||
|
|
||||||
```yml
|
|
||||||
url-source:
|
|
||||||
# Accepts file/http/https scheme
|
|
||||||
OwnSource: "https://some-url/ghcup-0.0.6.yaml"
|
|
||||||
```
|
|
||||||
|
|
||||||
See [config.yaml](https://gitlab.haskell.org/haskell/ghcup-hs/-/blob/master/data/config.yaml)
|
|
||||||
for more options.
|
|
||||||
|
|
||||||
Alternatively you can do it via a cli switch:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ghcup --url-source=https://some-url/ghcup-0.0.6.yaml list
|
|
||||||
```
|
|
||||||
|
|
||||||
### Known mirrors
|
|
||||||
|
|
||||||
1. [https://mirror.sjtu.edu.cn/docs/ghcup](https://mirror.sjtu.edu.cn/docs/ghcup)
|
|
||||||
|
|
||||||
## Isolated installs
|
## Isolated installs
|
||||||
|
|
||||||
Ghcup also enables you to install a tool (GHC, Cabal, HLS, Stack) at an isolated location of your choosing.
|
Ghcup also enables you to install a tool (GHC, Cabal, HLS, Stack) at an isolated location of your choosing.
|
||||||
@@ -257,9 +309,9 @@ gpg-setting: GPGLax # GPGStrict | GPGLax | GPGNone
|
|||||||
In `GPGStrict` mode, ghcup will fail if verification fails. In `GPGLax` mode it will just print a warning.
|
In `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>`.
|
You can also pass the mode via `ghcup --gpg <strict|lax|none>`.
|
||||||
|
|
||||||
## Tips and tricks
|
# Tips and tricks
|
||||||
|
|
||||||
### Execute command with certain GHC in PATH
|
## ghcup run
|
||||||
|
|
||||||
If you don't want to explicitly switch the active GHC all the time and are using
|
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
|
tools that rely on the plain `ghc` binary, GHCup provides an easy way to execute
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ hide:
|
|||||||
|
|
||||||
<div class="text-center main-buttons">
|
<div class="text-center main-buttons">
|
||||||
<a href="install/" class="btn btn-primary" role="button">Getting Started</a>
|
<a href="install/" class="btn btn-primary" role="button">Getting Started</a>
|
||||||
|
<a href="steps/" class="btn btn-primary" role="button">First steps</a>
|
||||||
<a href="guide/" class="btn btn-primary" role="button">User Guide</a>
|
<a href="guide/" class="btn btn-primary" role="button">User Guide</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
119
docs/install.md
119
docs/install.md
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
GHCup makes it easy to install specific versions of GHC on GNU/Linux,
|
GHCup makes it easy to install specific versions of GHC on GNU/Linux,
|
||||||
macOS (aka Darwin), FreeBSD and Windows and can also bootstrap a fresh [Haskell developer environment](./install/#supported-tools) from scratch.
|
macOS (aka Darwin), FreeBSD and Windows and can also bootstrap a fresh [Haskell developer environment](./install/#supported-tools) from scratch.
|
||||||
It follows the unix UNIX philosophy of [do one thing and do it well](https://en.wikipedia.org/wiki/Unix_philosophy#Do_One_Thing_and_Do_It_Well). Similar in scope to [rustup](https://github.com/rust-lang-nursery/rustup.rs), [pyenv](https://github.com/pyenv/pyenv) and [jenv](http://www.jenv.be).
|
It follows the UNIX philosophy of [do one thing and do it well](https://en.wikipedia.org/wiki/Unix_philosophy#Do_One_Thing_and_Do_It_Well). Similar in scope to [rustup](https://github.com/rust-lang-nursery/rustup.rs), [pyenv](https://github.com/pyenv/pyenv) and [jenv](http://www.jenv.be).
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@@ -22,6 +22,8 @@ For Windows, run this in a PowerShell session:
|
|||||||
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
|
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
|
||||||
```
|
```
|
||||||
|
|
||||||
|
There's also a [youtube video](https://www.youtube.com/watch?v=bB4fmQiUYPw) explaining installation on windows.
|
||||||
|
|
||||||
If you want to know what these scripts do, check out the [source code at the repository](https://gitlab.haskell.org/haskell/ghcup-hs/-/tree/master/scripts/bootstrap). Advanced users may want to perform a [manual installation](#manual-install) and GPG verify the binaries.
|
If you want to know what these scripts do, check out the [source code at the repository](https://gitlab.haskell.org/haskell/ghcup-hs/-/tree/master/scripts/bootstrap). Advanced users may want to perform a [manual installation](#manual-install) and GPG verify the binaries.
|
||||||
|
|
||||||
### Which versions get installed?
|
### Which versions get installed?
|
||||||
@@ -32,105 +34,98 @@ GHCup has two main channels for every tool: **recommended** and **latest**. By d
|
|||||||
|
|
||||||
Also see [tags and shortcuts](../guide/#tags-and-shortcuts) for more information.
|
Also see [tags and shortcuts](../guide/#tags-and-shortcuts) for more information.
|
||||||
|
|
||||||
## First steps
|
## Next steps
|
||||||
|
|
||||||
1. To get started with creating a Haskell project, follow the [Getting Started with Haskell and Cabal](https://cabal.readthedocs.io/en/stable/getting-started.html) guide
|
1. Follow the [First steps guide](../steps) on how to build a "Hello world" program, use `ghc`, run an interactive REPL and create a Haskell project
|
||||||
2. To learn Haskell, try any of those:
|
2. To understand the difference and overlap of `stack` and `cabal`, read on [here](https://gist.github.com/merijn/8152d561fb8b011f9313c48d876ceb07)
|
||||||
- A beginner friendly [4-lectures course](https://github.com/haskell-beginners-2022/course-plan) with exercises (by [Kowainik](https://kowainik.github.io/))
|
3. To learn Haskell proper check out the links at [How to learn Haskell proper](../steps#how-to-learn-haskell-proper)
|
||||||
- An in-depth university [CIS 194 Haskell course](https://www.cis.upenn.edu/~cis194/spring13/) including exercises (by [Brent Yorgey](https://byorgey.wordpress.com/))
|
4. To learn more about Haskell Toolchain management, check out the [ghcup user guide](./guide.md)
|
||||||
3. To learn more about Haskell Toolchain management, check out the [ghcup user guide](./guide.md)
|
|
||||||
|
|
||||||
## Uninstallation
|
## Uninstallation
|
||||||
|
|
||||||
On linux, just run `ghcup nuke`, then make sure any ghcup added lines in your `~/.bashrc` (or similar) are removed.
|
On linux, just run `ghcup nuke`, then make sure any ghcup added lines in your `~/.bashrc` (or similar) are removed.
|
||||||
|
|
||||||
On windows, double-click on the `Uninstall Haskell.ps1` PowerShell script on your Desktop.
|
On windows, right click on the `Uninstall Haskell.ps1` PowerShell script on your Desktop and select *Run with PowerShell*.
|
||||||
|
|
||||||
## Supported tools
|
## Supported tools
|
||||||
|
|
||||||
GHCup supports the following tools, which are also known as the **Haskell Toolchain**:
|
GHCup supports the following tools, which are also known as the **Haskell Toolchain**:
|
||||||
|
|
||||||
<details>
|
<details> <summary>Show all supported <a href='https://www.haskell.org/ghc/'>GHC</a> versions</summary>
|
||||||
<summary>Show all supported <a href='https://www.haskell.org/ghc/'>GHC</a> versions</summary>
|
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<thead><tr><th>GHC Version</th><th>Tags</th></tr></thead>
|
<thead><tr><th>GHC Version</th><th>Tags</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td>7.10.3</td><td>base-4.8.2.0</td></tr>
|
|
||||||
<tr><td>8.0.2</td><td>base-4.9.1.0</td></tr>
|
|
||||||
<tr><td>8.2.2</td><td>base-4.10.1.0</td></tr>
|
|
||||||
<tr><td>8.4.1</td><td>base-4.11.0.0</td></tr>
|
|
||||||
<tr><td>8.4.2</td><td>base-4.11.1.0</td></tr>
|
|
||||||
<tr><td>8.4.3</td><td>base-4.11.1.0</td></tr>
|
|
||||||
<tr><td>8.4.4</td><td>base-4.11.1.0</td></tr>
|
|
||||||
<tr><td>8.6.1</td><td>base-4.12.0.0</td></tr>
|
|
||||||
<tr><td>8.6.2</td><td>base-4.12.0.0</td></tr>
|
|
||||||
<tr><td>8.6.3</td><td>base-4.12.0.0</td></tr>
|
|
||||||
<tr><td>8.6.4</td><td>base-4.12.0.0</td></tr>
|
|
||||||
<tr><td>8.6.5</td><td>base-4.12.0.0</td></tr>
|
|
||||||
<tr><td>8.8.1</td><td>base-4.13.0.0</td></tr>
|
|
||||||
<tr><td>8.8.2</td><td>base-4.13.0.0</td></tr>
|
|
||||||
<tr><td>8.8.3</td><td>base-4.13.0.0</td></tr>
|
|
||||||
<tr><td>8.8.4</td><td>base-4.13.0.0</td></tr>
|
|
||||||
<tr><td>8.10.1</td><td>base-4.14.0.0</td></tr>
|
|
||||||
<tr><td>8.10.2</td><td>base-4.14.1.0</td></tr>
|
|
||||||
<tr><td>8.10.3</td><td>base-4.14.1.0</td></tr>
|
|
||||||
<tr><td>8.10.4</td><td>base-4.14.1.0</td></tr>
|
|
||||||
<tr><td>8.10.5</td><td>base-4.14.2.0</td></tr>
|
|
||||||
<tr><td>8.10.6</td><td>base-4.14.3.0</td></tr>
|
|
||||||
<tr><td>8.10.7</td><td><span style="color:green">recommended</span>, base-4.14.3.0</td></tr>
|
|
||||||
<tr><td>9.0.1</td><td>base-4.15.0.0</td></tr>
|
|
||||||
<tr><td>9.0.2</td><td>base-4.15.1.0</td></tr>
|
|
||||||
<tr><td>9.2.1</td><td>base-4.16.0.0</td></tr>
|
|
||||||
<tr><td>9.2.2</td><td><span style="color:blue">latest</span>, base-4.16.1.0</td></tr>
|
<tr><td>9.2.2</td><td><span style="color:blue">latest</span>, base-4.16.1.0</td></tr>
|
||||||
|
<tr><td>9.2.1</td><td>base-4.16.0.0</td></tr>
|
||||||
|
<tr><td>9.0.2</td><td>base-4.15.1.0</td></tr>
|
||||||
|
<tr><td>9.0.1</td><td>base-4.15.0.0</td></tr>
|
||||||
|
<tr><td>8.10.7</td><td><span style="color:green">recommended</span>, base-4.14.3.0</td></tr>
|
||||||
|
<tr><td>8.10.6</td><td>base-4.14.3.0</td></tr>
|
||||||
|
<tr><td>8.10.5</td><td>base-4.14.2.0</td></tr>
|
||||||
|
<tr><td>8.10.4</td><td>base-4.14.1.0</td></tr>
|
||||||
|
<tr><td>8.10.3</td><td>base-4.14.1.0</td></tr>
|
||||||
|
<tr><td>8.10.2</td><td>base-4.14.1.0</td></tr>
|
||||||
|
<tr><td>8.10.1</td><td>base-4.14.0.0</td></tr>
|
||||||
|
<tr><td>8.8.4</td><td>base-4.13.0.0</td></tr>
|
||||||
|
<tr><td>8.8.3</td><td>base-4.13.0.0</td></tr>
|
||||||
|
<tr><td>8.8.2</td><td>base-4.13.0.0</td></tr>
|
||||||
|
<tr><td>8.8.1</td><td>base-4.13.0.0</td></tr>
|
||||||
|
<tr><td>8.6.5</td><td>base-4.12.0.0</td></tr>
|
||||||
|
<tr><td>8.6.4</td><td>base-4.12.0.0</td></tr>
|
||||||
|
<tr><td>8.6.3</td><td>base-4.12.0.0</td></tr>
|
||||||
|
<tr><td>8.6.2</td><td>base-4.12.0.0</td></tr>
|
||||||
|
<tr><td>8.6.1</td><td>base-4.12.0.0</td></tr>
|
||||||
|
<tr><td>8.4.4</td><td>base-4.11.1.0</td></tr>
|
||||||
|
<tr><td>8.4.3</td><td>base-4.11.1.0</td></tr>
|
||||||
|
<tr><td>8.4.2</td><td>base-4.11.1.0</td></tr>
|
||||||
|
<tr><td>8.4.1</td><td>base-4.11.0.0</td></tr>
|
||||||
|
<tr><td>8.2.2</td><td>base-4.10.1.0</td></tr>
|
||||||
|
<tr><td>8.0.2</td><td>base-4.9.1.0</td></tr>
|
||||||
|
<tr><td>7.10.3</td><td>base-4.8.2.0</td></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
<details> <summary>Show all supported <a href='https://cabal.readthedocs.io/en/stable/'>cabal-install</a> versions</summary>
|
||||||
<summary>Show all supported <a href='https://cabal.readthedocs.io/en/stable/'>cabal-install</a> versions</summary>
|
<table>
|
||||||
<table>
|
|
||||||
<thead><tr><th>Cabal Version</th><th>Tags</th></tr></thead>
|
<thead><tr><th>Cabal Version</th><th>Tags</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td>2.4.1.0</td><td></td></tr>
|
|
||||||
<tr><td>3.0.0.0</td><td></td></tr>
|
|
||||||
<tr><td>3.2.0.0</td><td></td></tr>
|
|
||||||
<tr><td>3.4.0.0</td><td></td></tr>
|
|
||||||
<tr><td>3.4.1.0</td><td></td></tr>
|
|
||||||
<tr><td>3.6.0.0</td><td></td></tr>
|
|
||||||
<tr><td>3.6.2.0</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
<tr><td>3.6.2.0</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
||||||
|
<tr><td>3.6.0.0</td><td></td></tr>
|
||||||
|
<tr><td>3.4.1.0</td><td></td></tr>
|
||||||
|
<tr><td>3.4.0.0</td><td></td></tr>
|
||||||
|
<tr><td>3.2.0.0</td><td></td></tr>
|
||||||
|
<tr><td>3.0.0.0</td><td></td></tr>
|
||||||
|
<tr><td>2.4.1.0</td><td></td></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
<details> <summary>Show all supported <a href='https://haskell-language-server.readthedocs.io/en/stable/'>HLS</a> versions</summary>
|
||||||
<summary>Show all supported <a href='https://haskell-language-server.readthedocs.io/en/stable/'>HLS</a> versions</summary>
|
|
||||||
<table>
|
<table>
|
||||||
<thead><tr><th>HLS Version</th><th>Tags</th></tr></thead>
|
<thead><tr><th>HLS Version</th><th>Tags</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td>1.1.0</td><td></td></tr>
|
<tr><td>1.7.0.0</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
||||||
<tr><td>1.2.0</td><td></td></tr>
|
<tr><td>1.6.1.0</td><td></td></tr>
|
||||||
<tr><td>1.3.0</td><td></td></tr>
|
|
||||||
<tr><td>1.4.0</td><td></td></tr>
|
|
||||||
<tr><td>1.5.0</td><td></td></tr>
|
|
||||||
<tr><td>1.5.1</td><td></td></tr>
|
|
||||||
<tr><td>1.6.0.0</td><td></td></tr>
|
<tr><td>1.6.0.0</td><td></td></tr>
|
||||||
<tr><td>1.6.1.0</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
<tr><td>1.5.1</td><td></td></tr>
|
||||||
|
<tr><td>1.5.0</td><td></td></tr>
|
||||||
|
<tr><td>1.4.0</td><td></td></tr>
|
||||||
|
<tr><td>1.3.0</td><td></td></tr>
|
||||||
|
<tr><td>1.2.0</td><td></td></tr>
|
||||||
|
<tr><td>1.1.0</td><td></td></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
<details> <summary>Show all supported <a href='https://docs.haskellstack.org/en/stable/README/'>Stack</a> versions</summary>
|
||||||
<summary>Show all supported <a href='https://docs.haskellstack.org/en/stable/README/'>Stack</a> versions</summary>
|
|
||||||
<table>
|
<table>
|
||||||
<thead><tr><th>Stack Version</th><th>Tags</th></tr></thead>
|
<thead><tr><th>Stack Version</th><th>Tags</th></tr></thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td>2.5.1</td><td></td></tr>
|
|
||||||
<tr><td>2.7.1</td><td></td></tr>
|
|
||||||
<tr><td>2.7.3</td><td></td></tr>
|
|
||||||
<tr><td>2.7.5</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
<tr><td>2.7.5</td><td><span style="color:blue">latest</span>, <span style="color:green">recommended</span></td></tr>
|
||||||
|
<tr><td>2.7.3</td><td></td></tr>
|
||||||
|
<tr><td>2.7.1</td><td></td></tr>
|
||||||
|
<tr><td>2.5.1</td><td></td></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</details>
|
</details>
|
||||||
|
|||||||
349
docs/steps.md
Normal file
349
docs/steps.md
Normal file
@@ -0,0 +1,349 @@
|
|||||||
|
# First steps
|
||||||
|
|
||||||
|
In this guide we'll take a look at a few core tools that are installed
|
||||||
|
with the Haskell toolchain, namely, `ghc`, `runghc` and `ghci`.
|
||||||
|
These tools can be used to compile, interpret or explore Haskell programs.
|
||||||
|
|
||||||
|
First, let's start by opening your system's command line interface
|
||||||
|
and running `ghc --version` to make sure we have successfully
|
||||||
|
installed a Haskell toolchain:
|
||||||
|
|
||||||
|
```
|
||||||
|
➜ ghc --version
|
||||||
|
The Glorious Glasgow Haskell Compilation System, version 8.10.7
|
||||||
|
```
|
||||||
|
|
||||||
|
If this fails, consult [the Getting started page](../install) for information on
|
||||||
|
how to install Haskell on your computer.
|
||||||
|
|
||||||
|
This guide is partly based on [Gil Mizrahi's blog](https://gilmi.me/blog/post/2021/08/14/hs-core-tools).
|
||||||
|
|
||||||
|
## Compiling programs with ghc
|
||||||
|
|
||||||
|
Running `ghc` invokes the Glasgow Haskell Compiler (GHC), and can be used to
|
||||||
|
compile Haskell modules and programs into native executables and libraries.
|
||||||
|
|
||||||
|
Create a new Haskell source file named `hello.hs`,
|
||||||
|
and write the following code in it:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
main = putStrLn "Hello, Haskell!"
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, we can compile the program by invoking `ghc` with the file name:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
➜ ghc hello.hs
|
||||||
|
[1 of 1] Compiling Main ( hello.hs, hello.o )
|
||||||
|
Linking hello ...
|
||||||
|
```
|
||||||
|
|
||||||
|
For more in-depth information about the files `ghc` produces,
|
||||||
|
follow the [GHC user guide](https://downloads.haskell.org/ghc/latest/docs/html/users_guide/using.html#getting-started-compiling-programs) guide.
|
||||||
|
|
||||||
|
Now we run our program:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
➜ ./hello
|
||||||
|
Hello, Haskell!
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, we can skip the compilation phase by using the command `runghc`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
➜ runghc hello.hs
|
||||||
|
Hello, Haskell!
|
||||||
|
```
|
||||||
|
|
||||||
|
`runghc` interprets the source file instead of compiling it and does not
|
||||||
|
create build artifacts. This makes it very useful when developing programs
|
||||||
|
and can help accelerate the feedback loop. More information about `runghc`
|
||||||
|
can be found in the
|
||||||
|
[GHC user guide](https://downloads.haskell.org/ghc/latest/docs/html/users_guide/runghc.html).
|
||||||
|
|
||||||
|
### Turning on warnings
|
||||||
|
|
||||||
|
The `-Wall` flag will enable GHC to emit warnings about our code.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
➜ ghc -Wall hello.hs -fforce-recomp
|
||||||
|
[1 of 1] Compiling Main ( hello.hs, hello.o )
|
||||||
|
|
||||||
|
hello.hs:1:1: warning: [-Wmissing-signatures]
|
||||||
|
Top-level binding with no type signature: main :: IO ()
|
||||||
|
|
|
||||||
|
1 | main = putStrLn "Hello, Haskell!"
|
||||||
|
| ^^^^
|
||||||
|
Linking hello ...
|
||||||
|
```
|
||||||
|
|
||||||
|
While Haskell can infer
|
||||||
|
the types of most expressions, it is recommended that top-level definitions
|
||||||
|
are annotated with their types.
|
||||||
|
|
||||||
|
Now our `hello.hs` source file should looks like this:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
main :: IO ()
|
||||||
|
main = putStrLn "Hello, world!"
|
||||||
|
```
|
||||||
|
|
||||||
|
And now GHC will compile `hello.hs` without warnings.
|
||||||
|
|
||||||
|
## An interactive environment
|
||||||
|
|
||||||
|
GHC provides an interactive environment in a form of a
|
||||||
|
Read-Evaluate-Print Loop (REPL) called GHCi.
|
||||||
|
To enter the environment run the program `ghci`.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
➜ ghci
|
||||||
|
GHCi, version 9.0.2: https://www.haskell.org/ghc/ :? for help
|
||||||
|
ghci>
|
||||||
|
```
|
||||||
|
|
||||||
|
It provides an interactive prompt where Haskell expressions can be written and
|
||||||
|
evaluated.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ghci> 1 + 1
|
||||||
|
2
|
||||||
|
ghci> putStrLn "Hello, world!"
|
||||||
|
Hello, world!
|
||||||
|
```
|
||||||
|
|
||||||
|
We can define new names:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ghci> double x = x + x
|
||||||
|
ghci> double 2
|
||||||
|
4
|
||||||
|
```
|
||||||
|
|
||||||
|
We can write multi-line code by surrounding it with `:{` and `:}`:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
ghci> :{
|
||||||
|
| map f list =
|
||||||
|
| case list of
|
||||||
|
| [] -> []
|
||||||
|
| x : xs -> f x : map f xs
|
||||||
|
| :}
|
||||||
|
ghci> map (+1) [1, 2, 3]
|
||||||
|
[2,3,4]
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
We can import Haskell source files using the `:load` command (`:l` for short):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ghci> :load hello.hs
|
||||||
|
[1 of 1] Compiling Main ( hello.hs, interpreted )
|
||||||
|
Ok, one module loaded.
|
||||||
|
ghci> main
|
||||||
|
Hello, Haskell!
|
||||||
|
```
|
||||||
|
|
||||||
|
As well as import library modules:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ghci> import Data.Bits
|
||||||
|
ghci> shiftL 32 1
|
||||||
|
64
|
||||||
|
ghci> clearBit 33 0
|
||||||
|
32
|
||||||
|
```
|
||||||
|
|
||||||
|
We can even ask what the type of an expression is using the `:type` command
|
||||||
|
(`:t` for short):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
λ> :type putStrLn
|
||||||
|
putStrLn :: String -> IO ()
|
||||||
|
```
|
||||||
|
|
||||||
|
To exit `ghci`, use the `:quit` command (or `:q` for short)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ghci> :quit
|
||||||
|
Leaving GHCi.
|
||||||
|
```
|
||||||
|
|
||||||
|
A more thorough introduction to GHCi can be found in the
|
||||||
|
[GHC user guide](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html).
|
||||||
|
|
||||||
|
### Using external packages in ghci
|
||||||
|
|
||||||
|
By default, GHCi can only load and use packages that are
|
||||||
|
[included with the GHC installation](https://downloads.haskell.org/ghc/latest/docs/html/users_guide/9.2.2-notes.html#included-libraries).
|
||||||
|
|
||||||
|
However, users of the [cabal-install](https://www.haskell.org/cabal) and
|
||||||
|
[stack](http://haskellstack.org) build tools can download and load external packages
|
||||||
|
very easily using the following commands:
|
||||||
|
|
||||||
|
cabal-install:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cabal repl --build-depends async,say
|
||||||
|
```
|
||||||
|
|
||||||
|
Stack:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
stack exec --package async --package say -- ghci
|
||||||
|
```
|
||||||
|
|
||||||
|
And the modules of the relevant packages will be available for import:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
GHCi, version 9.0.1: https://www.haskell.org/ghc/ :? for help
|
||||||
|
ghci> import Control.Concurrent.Async
|
||||||
|
ghci> import Say
|
||||||
|
ghci> concurrently_ (sayString "Hello") (sayString "World")
|
||||||
|
Hello
|
||||||
|
World
|
||||||
|
```
|
||||||
|
|
||||||
|
Stack users can also use this feature with `runghc` and `ghc` by replacing
|
||||||
|
`ghci` in the command above, and cabal-install users can generate an
|
||||||
|
environment file that will make `async` and `say` visible for GHC tools
|
||||||
|
in the current directory using this command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cabal install --lib async say --package-env .
|
||||||
|
```
|
||||||
|
|
||||||
|
Many more packages are waiting for you on [Hackage](https://hackage.haskell.org).
|
||||||
|
|
||||||
|
## Creating a proper package with modules
|
||||||
|
|
||||||
|
The previous methods to compile Haskell code are for quick experiments and small
|
||||||
|
programs. Usually in Haskell, we create cabal projects, where build tools such as
|
||||||
|
`cabal-install` or `stack` will install necessary dependencies and compile modules
|
||||||
|
in correct order. For simplicity's sake, this section will only use `cabal-install`.
|
||||||
|
|
||||||
|
To get started, run:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mkdir haskell-project
|
||||||
|
cd haskell-project
|
||||||
|
cabal init --interactive
|
||||||
|
```
|
||||||
|
|
||||||
|
If you let it generate a simple project with sensible defaults, then you should have these files:
|
||||||
|
|
||||||
|
* `src/MyLib.hs`: the library module of your project
|
||||||
|
* `app/Main.hs`: the entry point of your project
|
||||||
|
* `haskell-project.cabal`: the "cabal" file, describing your project, its dependencies and how it's built
|
||||||
|
|
||||||
|
To build the project, run:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cabal build
|
||||||
|
```
|
||||||
|
|
||||||
|
To run the main executable, run:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
➜ cabal run
|
||||||
|
Hello, Haskell!
|
||||||
|
someFunc
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding dependencies
|
||||||
|
|
||||||
|
Now let's add a dependency and adjust our library module. Open `haskell-project.cabal`
|
||||||
|
and find the library section:
|
||||||
|
|
||||||
|
```
|
||||||
|
library
|
||||||
|
exposed-modules: MyLib
|
||||||
|
|
||||||
|
-- Modules included in this library but not exported.
|
||||||
|
-- other-modules:
|
||||||
|
|
||||||
|
-- LANGUAGE extensions used by modules in this package.
|
||||||
|
-- other-extensions:
|
||||||
|
build-depends: base ^>=4.14.3.0
|
||||||
|
hs-source-dirs: src
|
||||||
|
default-language: Haskell2010
|
||||||
|
```
|
||||||
|
|
||||||
|
The interesting parts here are `exposed-modules` and `build-depends`.
|
||||||
|
To add a dependency, it should look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
build-depends: base ^>=4.14.3.0
|
||||||
|
, directory
|
||||||
|
```
|
||||||
|
|
||||||
|
Now open `src/MyLib.hs` and change it to:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
module MyLib (someFunc) where
|
||||||
|
|
||||||
|
import System.Directory
|
||||||
|
|
||||||
|
someFunc :: IO ()
|
||||||
|
someFunc = do
|
||||||
|
contents <- listDirectory "src"
|
||||||
|
putStrLn (show contents)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding modules
|
||||||
|
|
||||||
|
To add a module to your package, adjust `exposed-modules`, like so
|
||||||
|
|
||||||
|
```
|
||||||
|
exposed-modules: MyLib
|
||||||
|
OtherLib
|
||||||
|
```
|
||||||
|
|
||||||
|
then create `src/OtherLib.hs` with the following contents:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
module OtherLib where
|
||||||
|
|
||||||
|
otherFunc :: String -> Int
|
||||||
|
otherFunc str = length str
|
||||||
|
```
|
||||||
|
|
||||||
|
To use this function interactively, we can run:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
➜ cabal repl
|
||||||
|
ghci> import OtherLib
|
||||||
|
ghci> otherFunc "Hello Haskell"
|
||||||
|
13
|
||||||
|
```
|
||||||
|
|
||||||
|
For further information about how to manage Haskell projects
|
||||||
|
see the [Cabal user guide](https://cabal.readthedocs.io/en/stable/getting-started.html).
|
||||||
|
|
||||||
|
# Where to go from here
|
||||||
|
|
||||||
|
<div class="text-center main-buttons">
|
||||||
|
<a href="https://hackage.haskell.org/" class="btn btn-primary" role="button">Discover Haskell packages</a>
|
||||||
|
<a href="https://hackage.haskell.org/package/base" class="btn btn-primary" role="button">The standard library</a>
|
||||||
|
<a href="https://haskell-language-server.readthedocs.io/en/stable/installation.html" class="btn btn-primary" role="button">Editor setup with HLS</a>
|
||||||
|
<a href="https://play-haskell.tomsmeding.com/play" class="btn btn-primary" role="button">Online playground</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## How to learn Haskell proper
|
||||||
|
|
||||||
|
To learn Haskell, try any of those:
|
||||||
|
|
||||||
|
- A beginner friendly [4-lectures course](https://github.com/haskell-beginners-2022/course-plan) with exercises (by [Kowainik](https://kowainik.github.io/))
|
||||||
|
- An in-depth university [CIS 194 Haskell course](https://www.cis.upenn.edu/~cis194/spring13/) including exercises (by [Brent Yorgey](https://byorgey.wordpress.com/))
|
||||||
|
|
||||||
|
## Projects to contribute to
|
||||||
|
|
||||||
|
* [https://github.com/haskell/haskell-language-server](https://github.com/haskell/haskell-language-server)
|
||||||
|
* [https://github.com/haskell/cabal](https://github.com/haskell/cabal)
|
||||||
|
* [https://github.com/commercialhaskell/stack](https://github.com/commercialhaskell/stack)
|
||||||
|
* [https://gitlab.haskell.org/haskell/ghcup-hs](https://gitlab.haskell.org/haskell/ghcup-hs)
|
||||||
|
* [https://github.com/jgm/pandoc](https://github.com/jgm/pandoc)
|
||||||
|
* [https://github.com/simonmichael/hledger](https://github.com/simonmichael/hledger)
|
||||||
|
* [https://github.com/koalaman/shellcheck](https://github.com/koalaman/shellcheck)
|
||||||
15
ghcup.cabal
15
ghcup.cabal
@@ -1,6 +1,6 @@
|
|||||||
cabal-version: 3.0
|
cabal-version: 3.0
|
||||||
name: ghcup
|
name: ghcup
|
||||||
version: 0.1.17.6
|
version: 0.1.17.7
|
||||||
license: LGPL-3.0-only
|
license: LGPL-3.0-only
|
||||||
license-file: LICENSE
|
license-file: LICENSE
|
||||||
copyright: Julian Ospald 2020
|
copyright: Julian Ospald 2020
|
||||||
@@ -48,13 +48,6 @@ flag no-exe
|
|||||||
default: False
|
default: False
|
||||||
manual: True
|
manual: True
|
||||||
|
|
||||||
flag disable-upgrade
|
|
||||||
description:
|
|
||||||
Disable upgrade functionality. This is mainly to support brew packagers.
|
|
||||||
|
|
||||||
default: False
|
|
||||||
manual: True
|
|
||||||
|
|
||||||
library
|
library
|
||||||
exposed-modules:
|
exposed-modules:
|
||||||
GHCup
|
GHCup
|
||||||
@@ -204,6 +197,7 @@ executable ghcup
|
|||||||
GHCup.OptParse.Set
|
GHCup.OptParse.Set
|
||||||
GHCup.OptParse.ToolRequirements
|
GHCup.OptParse.ToolRequirements
|
||||||
GHCup.OptParse.UnSet
|
GHCup.OptParse.UnSet
|
||||||
|
GHCup.OptParse.Upgrade
|
||||||
GHCup.OptParse.Whereis
|
GHCup.OptParse.Whereis
|
||||||
|
|
||||||
hs-source-dirs: app/ghcup
|
hs-source-dirs: app/ghcup
|
||||||
@@ -277,11 +271,6 @@ executable ghcup
|
|||||||
if flag(no-exe)
|
if flag(no-exe)
|
||||||
buildable: False
|
buildable: False
|
||||||
|
|
||||||
if flag(disable-upgrade)
|
|
||||||
cpp-options: -DDISABLE_UPGRADE
|
|
||||||
|
|
||||||
else
|
|
||||||
other-modules: GHCup.OptParse.Upgrade
|
|
||||||
|
|
||||||
test-suite ghcup-test
|
test-suite ghcup-test
|
||||||
type: exitcode-stdio-1.0
|
type: exitcode-stdio-1.0
|
||||||
|
|||||||
27
lib/GHCup.hs
27
lib/GHCup.hs
@@ -2587,6 +2587,7 @@ upgradeGHCup :: ( MonadMask m
|
|||||||
=> Maybe FilePath -- ^ full file destination to write ghcup into
|
=> Maybe FilePath -- ^ full file destination to write ghcup into
|
||||||
-> Bool -- ^ whether to force update regardless
|
-> Bool -- ^ whether to force update regardless
|
||||||
-- of currently installed version
|
-- of currently installed version
|
||||||
|
-> Bool -- ^ whether to throw an error if ghcup is shadowed
|
||||||
-> Excepts
|
-> Excepts
|
||||||
'[ CopyError
|
'[ CopyError
|
||||||
, DigestError
|
, DigestError
|
||||||
@@ -2595,15 +2596,16 @@ upgradeGHCup :: ( MonadMask m
|
|||||||
, DownloadFailed
|
, DownloadFailed
|
||||||
, NoDownload
|
, NoDownload
|
||||||
, NoUpdate
|
, NoUpdate
|
||||||
|
, GHCupShadowed
|
||||||
]
|
]
|
||||||
m
|
m
|
||||||
Version
|
Version
|
||||||
upgradeGHCup mtarget force' = do
|
upgradeGHCup mtarget force' fatal = do
|
||||||
Dirs {..} <- lift getDirs
|
Dirs {..} <- lift getDirs
|
||||||
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
GHCupInfo { _ghcupDownloads = dls } <- lift getGHCupInfo
|
||||||
|
|
||||||
lift $ logInfo "Upgrading GHCup..."
|
lift $ logInfo "Upgrading GHCup..."
|
||||||
let latestVer = fromJust $ fst <$> getLatest dls GHCup
|
let latestVer = fst (fromJust (getLatest dls GHCup))
|
||||||
(Just ghcupPVPVer) <- pure $ pvpToVersion ghcUpVer ""
|
(Just ghcupPVPVer) <- pure $ pvpToVersion ghcUpVer ""
|
||||||
when (not force' && (latestVer <= ghcupPVPVer)) $ throwE NoUpdate
|
when (not force' && (latestVer <= ghcupPVPVer)) $ throwE NoUpdate
|
||||||
dli <- liftE $ getDownloadInfo GHCup latestVer
|
dli <- liftE $ getDownloadInfo GHCup latestVer
|
||||||
@@ -2625,15 +2627,18 @@ upgradeGHCup mtarget force' = do
|
|||||||
lift $ logWarn $ T.pack (takeFileName destFile) <> " is not in PATH! You have to add it in order to use ghcup."
|
lift $ logWarn $ T.pack (takeFileName destFile) <> " is not in PATH! You have to add it in order to use ghcup."
|
||||||
liftIO (isShadowed destFile) >>= \case
|
liftIO (isShadowed destFile) >>= \case
|
||||||
Nothing -> pure ()
|
Nothing -> pure ()
|
||||||
Just pa -> lift $ logWarn $ "ghcup is shadowed by "
|
Just pa
|
||||||
<> T.pack pa
|
| fatal -> throwE (GHCupShadowed pa destFile latestVer)
|
||||||
<> ". The upgrade will not be in effect, unless you remove "
|
| otherwise ->
|
||||||
<> T.pack pa
|
lift $ logWarn $ "ghcup is shadowed by "
|
||||||
<> " or make sure "
|
<> T.pack pa
|
||||||
<> T.pack destDir
|
<> ". The upgrade will not be in effect, unless you remove "
|
||||||
<> " comes before "
|
<> T.pack pa
|
||||||
<> T.pack (takeFileName pa)
|
<> " or make sure "
|
||||||
<> " in PATH."
|
<> T.pack destDir
|
||||||
|
<> " comes before "
|
||||||
|
<> T.pack (takeDirectory pa)
|
||||||
|
<> " in PATH."
|
||||||
|
|
||||||
pure latestVer
|
pure latestVer
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import Data.CaseInsensitive ( CI )
|
|||||||
import Data.Text ( Text )
|
import Data.Text ( Text )
|
||||||
import Data.Versions
|
import Data.Versions
|
||||||
import Haskus.Utils.Variant
|
import Haskus.Utils.Variant
|
||||||
|
import System.FilePath
|
||||||
import Text.PrettyPrint hiding ( (<>) )
|
import Text.PrettyPrint hiding ( (<>) )
|
||||||
import Text.PrettyPrint.HughesPJClass hiding ( (<>) )
|
import Text.PrettyPrint.HughesPJClass hiding ( (<>) )
|
||||||
import URI.ByteString
|
import URI.ByteString
|
||||||
@@ -291,6 +292,24 @@ instance Pretty HadrianNotFound where
|
|||||||
pPrint HadrianNotFound =
|
pPrint HadrianNotFound =
|
||||||
text "Could not find Hadrian build files. Does this GHC version support Hadrian builds?"
|
text "Could not find Hadrian build files. Does this GHC version support Hadrian builds?"
|
||||||
|
|
||||||
|
data GHCupShadowed = GHCupShadowed
|
||||||
|
FilePath -- shadow binary
|
||||||
|
FilePath -- upgraded binary
|
||||||
|
Version -- upgraded version
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
instance Pretty GHCupShadowed where
|
||||||
|
pPrint (GHCupShadowed sh up _) =
|
||||||
|
text ("ghcup is shadowed by "
|
||||||
|
<> sh
|
||||||
|
<> ". The upgrade will not be in effect, unless you remove "
|
||||||
|
<> sh
|
||||||
|
<> " or make sure "
|
||||||
|
<> takeDirectory up
|
||||||
|
<> " comes before "
|
||||||
|
<> takeDirectory sh
|
||||||
|
<> " in PATH."
|
||||||
|
)
|
||||||
|
|
||||||
-------------------------
|
-------------------------
|
||||||
--[ High-level errors ]--
|
--[ High-level errors ]--
|
||||||
|
|||||||
@@ -317,10 +317,10 @@ ghcSet mtarget = do
|
|||||||
MP.setInput rest
|
MP.setInput rest
|
||||||
pure x
|
pure x
|
||||||
)
|
)
|
||||||
<* pathSep
|
<* MP.some pathSep
|
||||||
<* MP.takeRest
|
<* MP.takeRest
|
||||||
<* MP.eof
|
<* MP.eof
|
||||||
ghcSubPath = pathSep <* MP.chunk "ghc" *> pathSep
|
ghcSubPath = MP.some pathSep <* MP.chunk "ghc" *> MP.some pathSep
|
||||||
|
|
||||||
-- | Get all installed GHCs by reading ~/.ghcup/ghc/<dir>.
|
-- | Get all installed GHCs by reading ~/.ghcup/ghc/<dir>.
|
||||||
-- If a dir cannot be parsed, returns left.
|
-- If a dir cannot be parsed, returns left.
|
||||||
@@ -398,10 +398,10 @@ cabalSet = do
|
|||||||
cabalParse = MP.chunk "cabal-" *> version'
|
cabalParse = MP.chunk "cabal-" *> version'
|
||||||
-- parses any path component ending with path separator,
|
-- parses any path component ending with path separator,
|
||||||
-- e.g. "foo/"
|
-- e.g. "foo/"
|
||||||
stripPathComponet = parseUntil1 pathSep *> pathSep
|
stripPathComponet = parseUntil1 pathSep *> MP.some pathSep
|
||||||
-- parses an absolute path up until the last path separator,
|
-- parses an absolute path up until the last path separator,
|
||||||
-- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"
|
-- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"
|
||||||
stripAbsolutePath = pathSep *> MP.many (MP.try stripPathComponet)
|
stripAbsolutePath = MP.some pathSep *> MP.many (MP.try stripPathComponet)
|
||||||
-- parses a relative path up until the last path separator,
|
-- parses a relative path up until the last path separator,
|
||||||
-- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"
|
-- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"
|
||||||
stripRelativePath = MP.many (MP.try stripPathComponet)
|
stripRelativePath = MP.many (MP.try stripPathComponet)
|
||||||
@@ -492,10 +492,10 @@ stackSet = do
|
|||||||
cabalParse = MP.chunk "stack-" *> version'
|
cabalParse = MP.chunk "stack-" *> version'
|
||||||
-- parses any path component ending with path separator,
|
-- parses any path component ending with path separator,
|
||||||
-- e.g. "foo/"
|
-- e.g. "foo/"
|
||||||
stripPathComponet = parseUntil1 pathSep *> pathSep
|
stripPathComponet = parseUntil1 pathSep *> MP.some pathSep
|
||||||
-- parses an absolute path up until the last path separator,
|
-- parses an absolute path up until the last path separator,
|
||||||
-- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"
|
-- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"
|
||||||
stripAbsolutePath = pathSep *> MP.many (MP.try stripPathComponet)
|
stripAbsolutePath = MP.some pathSep *> MP.many (MP.try stripPathComponet)
|
||||||
-- parses a relative path up until the last path separator,
|
-- parses a relative path up until the last path separator,
|
||||||
-- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"
|
-- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"
|
||||||
stripRelativePath = MP.many (MP.try stripPathComponet)
|
stripRelativePath = MP.many (MP.try stripPathComponet)
|
||||||
@@ -543,10 +543,10 @@ hlsSet = do
|
|||||||
cabalParse = MP.chunk "haskell-language-server-wrapper-" *> version'
|
cabalParse = MP.chunk "haskell-language-server-wrapper-" *> version'
|
||||||
-- parses any path component ending with path separator,
|
-- parses any path component ending with path separator,
|
||||||
-- e.g. "foo/"
|
-- e.g. "foo/"
|
||||||
stripPathComponet = parseUntil1 pathSep *> pathSep
|
stripPathComponet = parseUntil1 pathSep *> MP.some pathSep
|
||||||
-- parses an absolute path up until the last path separator,
|
-- parses an absolute path up until the last path separator,
|
||||||
-- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"
|
-- e.g. "/bar/baz/foo" -> "/bar/baz/", leaving "foo"
|
||||||
stripAbsolutePath = pathSep *> MP.many (MP.try stripPathComponet)
|
stripAbsolutePath = MP.some pathSep *> MP.many (MP.try stripPathComponet)
|
||||||
-- parses a relative path up until the last path separator,
|
-- parses a relative path up until the last path separator,
|
||||||
-- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"
|
-- e.g. "bar/baz/foo" -> "bar/baz/", leaving "foo"
|
||||||
stripRelativePath = MP.many (MP.try stripPathComponet)
|
stripRelativePath = MP.many (MP.try stripPathComponet)
|
||||||
|
|||||||
@@ -473,7 +473,7 @@ recyclePathForcibly fp
|
|||||||
liftIO (moveFile fp dest)
|
liftIO (moveFile fp dest)
|
||||||
`catch`
|
`catch`
|
||||||
(\e -> if | isDoesNotExistError e -> pure ()
|
(\e -> if | isDoesNotExistError e -> pure ()
|
||||||
| isPermissionError e {- EXDEV on windows -} -> recover (liftIO $ removePathForcibly fp)
|
| isPermissionError e || ioeGetErrorType e == UnsupportedOperation {- EXDEV on windows -} -> recover (liftIO $ removePathForcibly fp)
|
||||||
| otherwise -> throwIO e)
|
| otherwise -> throwIO e)
|
||||||
`finally`
|
`finally`
|
||||||
liftIO (handleIO (\_ -> pure ()) $ removePathForcibly tmp)
|
liftIO (handleIO (\_ -> pure ()) $ removePathForcibly tmp)
|
||||||
@@ -515,7 +515,7 @@ recycleFile fp
|
|||||||
let dest = tmp </> takeFileName fp
|
let dest = tmp </> takeFileName fp
|
||||||
liftIO (moveFile fp dest)
|
liftIO (moveFile fp dest)
|
||||||
`catch`
|
`catch`
|
||||||
(\e -> if isPermissionError e {- EXDEV on windows -} then recover (liftIO $ removePathForcibly fp) else throwIO e)
|
(\e -> if isPermissionError e || ioeGetErrorType e == UnsupportedOperation {- EXDEV on windows -} then recover (liftIO $ removePathForcibly fp) else throwIO e)
|
||||||
`finally`
|
`finally`
|
||||||
liftIO (handleIO (\_ -> pure ()) $ removePathForcibly tmp)
|
liftIO (handleIO (\_ -> pure ()) $ removePathForcibly tmp)
|
||||||
| otherwise = liftIO $ removeFile fp
|
| otherwise = liftIO $ removeFile fp
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ theme:
|
|||||||
|
|
||||||
nav:
|
nav:
|
||||||
- Home: index.md
|
- Home: index.md
|
||||||
- "Getting Started": install.md
|
- "Getting started": install.md
|
||||||
|
- "First steps": steps.md
|
||||||
- "User Guide": guide.md
|
- "User Guide": guide.md
|
||||||
- "Developer Guide": dev.md
|
- "Developer Guide": dev.md
|
||||||
- About: about.md
|
- About: about.md
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
# * BOOTSTRAP_HASKELL_INSTALL_HLS - whether to install latest hls
|
# * BOOTSTRAP_HASKELL_INSTALL_HLS - whether to install latest hls
|
||||||
# * BOOTSTRAP_HASKELL_ADJUST_BASHRC - whether to adjust PATH in bashrc (prepend)
|
# * 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
|
# * BOOTSTRAP_HASKELL_ADJUST_CABAL_CONFIG - whether to adjust mingw paths in cabal.config on windows
|
||||||
|
# * GHCUP_BASE_URL - the base url for ghcup binary download (use this to overwrite https://downloads.haskell.org/~ghcup with a mirror)
|
||||||
|
|
||||||
# License: LGPL-3.0
|
# License: LGPL-3.0
|
||||||
|
|
||||||
@@ -25,8 +26,8 @@
|
|||||||
|
|
||||||
plat="$(uname -s)"
|
plat="$(uname -s)"
|
||||||
arch=$(uname -m)
|
arch=$(uname -m)
|
||||||
ghver="0.1.17.5"
|
ghver="0.1.17.7"
|
||||||
base_url="https://downloads.haskell.org/~ghcup"
|
: "${GHCUP_BASE_URL:=https://downloads.haskell.org/~ghcup}"
|
||||||
|
|
||||||
export GHCUP_SKIP_UPDATE_CHECK=yes
|
export GHCUP_SKIP_UPDATE_CHECK=yes
|
||||||
|
|
||||||
@@ -157,7 +158,7 @@ _done() {
|
|||||||
green "and the \"Mingw package management docs\""
|
green "and the \"Mingw package management docs\""
|
||||||
green "desktop shortcuts."
|
green "desktop shortcuts."
|
||||||
green
|
green
|
||||||
green "If you are new to Haskell, check out https://www.haskell.org/ghcup/install/#first-steps"
|
green "If you are new to Haskell, check out https://www.haskell.org/ghcup/steps/"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
green
|
green
|
||||||
@@ -172,7 +173,7 @@ _done() {
|
|||||||
green "To install other GHC versions and tools, run:"
|
green "To install other GHC versions and tools, run:"
|
||||||
green " ghcup tui"
|
green " ghcup tui"
|
||||||
green
|
green
|
||||||
green "If you are new to Haskell, check out https://www.haskell.org/ghcup/install/#first-steps"
|
green "If you are new to Haskell, check out https://www.haskell.org/ghcup/steps/"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
esac
|
esac
|
||||||
@@ -197,12 +198,15 @@ posix_realpath() {
|
|||||||
current_loop=0
|
current_loop=0
|
||||||
max_loops=50
|
max_loops=50
|
||||||
mysource=$1
|
mysource=$1
|
||||||
|
# readlink and '[ -h $path ]' behave different wrt '/sbin/' and '/sbin', so we strip it
|
||||||
|
mysource=${mysource%/}
|
||||||
|
[ -z "${mysource}" ] && mysource=$1
|
||||||
|
|
||||||
while [ -h "${mysource}" ]; do
|
while [ -h "${mysource}" ]; do
|
||||||
current_loop=$((current_loop+1))
|
current_loop=$((current_loop+1))
|
||||||
mydir="$( cd -P "$( dirname "${mysource}" )" > /dev/null 2>&1 && pwd )"
|
mydir="$( cd -P "$( dirname "${mysource}" )" > /dev/null 2>&1 && pwd )"
|
||||||
mysource="$(readlink "${mysource}")"
|
mysource="$(readlink "${mysource}")"
|
||||||
[ "${mysource%${mysource#?}}"x != '/x' ] && mysource="${mydir}/${mysource}"
|
[ "${mysource%"${mysource#?}"}"x != '/x' ] && mysource="${mydir%/}/${mysource}"
|
||||||
|
|
||||||
if [ ${current_loop} -gt ${max_loops} ] ; then
|
if [ ${current_loop} -gt ${max_loops} ] ; then
|
||||||
(>&2 echo "${1}: Too many levels of symbolic links")
|
(>&2 echo "${1}: Too many levels of symbolic links")
|
||||||
@@ -232,26 +236,26 @@ download_ghcup() {
|
|||||||
# we could be in a 32bit docker container, in which
|
# we could be in a 32bit docker container, in which
|
||||||
# case uname doesn't give us what we want
|
# case uname doesn't give us what we want
|
||||||
if [ "$(getconf LONG_BIT)" = "32" ] ; then
|
if [ "$(getconf LONG_BIT)" = "32" ] ; then
|
||||||
_url=${base_url}/${ghver}/i386-linux-ghcup-${ghver}
|
_url=${GHCUP_BASE_URL}/${ghver}/i386-linux-ghcup-${ghver}
|
||||||
elif [ "$(getconf LONG_BIT)" = "64" ] ; then
|
elif [ "$(getconf LONG_BIT)" = "64" ] ; then
|
||||||
_url=${base_url}/${ghver}/x86_64-linux-ghcup-${ghver}
|
_url=${GHCUP_BASE_URL}/${ghver}/x86_64-linux-ghcup-${ghver}
|
||||||
else
|
else
|
||||||
die "Unknown long bit size: $(getconf LONG_BIT)"
|
die "Unknown long bit size: $(getconf LONG_BIT)"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
i*86)
|
i*86)
|
||||||
_url=${base_url}/${ghver}/i386-linux-ghcup-${ghver}
|
_url=${GHCUP_BASE_URL}/${ghver}/i386-linux-ghcup-${ghver}
|
||||||
;;
|
;;
|
||||||
armv7*|*armv8l*)
|
armv7*|*armv8l*)
|
||||||
_url=${base_url}/${ghver}/armv7-linux-ghcup-${ghver}
|
_url=${GHCUP_BASE_URL}/${ghver}/armv7-linux-ghcup-${ghver}
|
||||||
;;
|
;;
|
||||||
aarch64|arm64)
|
aarch64|arm64)
|
||||||
# we could be in a 32bit docker container, in which
|
# we could be in a 32bit docker container, in which
|
||||||
# case uname doesn't give us what we want
|
# case uname doesn't give us what we want
|
||||||
if [ "$(getconf LONG_BIT)" = "32" ] ; then
|
if [ "$(getconf LONG_BIT)" = "32" ] ; then
|
||||||
_url=${base_url}/${ghver}/armv7-linux-ghcup-${ghver}
|
_url=${GHCUP_BASE_URL}/${ghver}/armv7-linux-ghcup-${ghver}
|
||||||
elif [ "$(getconf LONG_BIT)" = "64" ] ; then
|
elif [ "$(getconf LONG_BIT)" = "64" ] ; then
|
||||||
_url=${base_url}/${ghver}/aarch64-linux-ghcup-${ghver}
|
_url=${GHCUP_BASE_URL}/${ghver}/aarch64-linux-ghcup-${ghver}
|
||||||
else
|
else
|
||||||
die "Unknown long bit size: $(getconf LONG_BIT)"
|
die "Unknown long bit size: $(getconf LONG_BIT)"
|
||||||
fi
|
fi
|
||||||
@@ -278,15 +282,15 @@ download_ghcup() {
|
|||||||
*) die "Unknown architecture: ${arch}"
|
*) die "Unknown architecture: ${arch}"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
_url=${base_url}/${ghver}/x86_64-freebsd${freebsd_ver}-ghcup-${ghver}
|
_url=${GHCUP_BASE_URL}/${ghver}/x86_64-freebsd${freebsd_ver}-ghcup-${ghver}
|
||||||
;;
|
;;
|
||||||
"Darwin"|"darwin")
|
"Darwin"|"darwin")
|
||||||
case "${arch}" in
|
case "${arch}" in
|
||||||
x86_64|amd64)
|
x86_64|amd64)
|
||||||
_url=${base_url}/${ghver}/x86_64-apple-darwin-ghcup-${ghver}
|
_url=${GHCUP_BASE_URL}/${ghver}/x86_64-apple-darwin-ghcup-${ghver}
|
||||||
;;
|
;;
|
||||||
aarch64|arm64|armv8l)
|
aarch64|arm64|armv8l)
|
||||||
_url=${base_url}/${ghver}/aarch64-apple-darwin-ghcup-${ghver}
|
_url=${GHCUP_BASE_URL}/${ghver}/aarch64-apple-darwin-ghcup-${ghver}
|
||||||
;;
|
;;
|
||||||
i*86)
|
i*86)
|
||||||
die "i386 currently not supported!"
|
die "i386 currently not supported!"
|
||||||
@@ -298,7 +302,7 @@ download_ghcup() {
|
|||||||
MSYS*|MINGW*)
|
MSYS*|MINGW*)
|
||||||
case "${arch}" in
|
case "${arch}" in
|
||||||
x86_64|amd64)
|
x86_64|amd64)
|
||||||
_url=${base_url}/${ghver}/x86_64-mingw64-ghcup-${ghver}.exe
|
_url=${GHCUP_BASE_URL}/${ghver}/x86_64-mingw64-ghcup-${ghver}.exe
|
||||||
;;
|
;;
|
||||||
*) die "Unknown architecture: ${arch}"
|
*) die "Unknown architecture: ${arch}"
|
||||||
;;
|
;;
|
||||||
|
|||||||
@@ -239,7 +239,27 @@ if ($Silent -and !($InstallDir)) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while ($true) {
|
while ($true) {
|
||||||
Print-Msg -color Magenta -msg ('Where to install to (this should be a short Path, preferably a Drive like ''C:\''){1}Press enter to accept the default [{0}]:' -f $defaultGhcupBasePrefix, "`n")
|
Print-Msg -color Magenta -msg (@'
|
||||||
|
Welcome to Haskell!
|
||||||
|
|
||||||
|
This script will download and install the following programs:
|
||||||
|
* ghcup - The Haskell toolchain installer
|
||||||
|
* ghc - The Glasgow Haskell Compiler
|
||||||
|
* msys2 - A linux-style toolchain environment required for many operations
|
||||||
|
* cabal - The Cabal build tool for managing Haskell software
|
||||||
|
* stack - (optional) A cross-platform program for developing Haskell projects
|
||||||
|
* hls - (optional) A language server for developers to integrate with their editor/IDE
|
||||||
|
|
||||||
|
Please note that ANTIVIRUS may interfere with the installation. If you experience problems, consider
|
||||||
|
disabling it temporarily.
|
||||||
|
|
||||||
|
Where to install to (this should be a short Path, preferably a Drive like 'C:\')?
|
||||||
|
If you accept this path, binaries will be installed into '{0}ghcup\bin' and msys2 into '{0}ghcup\msys64'.
|
||||||
|
Press enter to accept the default [{0}]:
|
||||||
|
|
||||||
|
'@ -f $defaultGhcupBasePrefix)
|
||||||
|
|
||||||
|
|
||||||
$basePrefixPrompt = Read-Host
|
$basePrefixPrompt = Read-Host
|
||||||
$GhcupBasePrefix = ($defaultGhcupBasePrefix,$basePrefixPrompt)[[bool]$basePrefixPrompt]
|
$GhcupBasePrefix = ($defaultGhcupBasePrefix,$basePrefixPrompt)[[bool]$basePrefixPrompt]
|
||||||
if (!($GhcupBasePrefix.EndsWith('\'))) {
|
if (!($GhcupBasePrefix.EndsWith('\'))) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
resolver: lts-18.27
|
resolver: lts-18.28
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
- .
|
- .
|
||||||
|
|||||||
Reference in New Issue
Block a user