Several improvements to install script

* Remove unused imports
* Pass number of jobs and verbosity shake args to build tools
* Use custom cabal.project-${ghcVersion} if exists
* Add comments with the possible resolvers to shake.yaml
This commit is contained in:
jneira 2020-02-24 12:17:24 +01:00
parent 4d048938d4
commit b46a531454
9 changed files with 163 additions and 130 deletions

View File

@ -1,5 +1,5 @@
name: hie-install
version: 0.8.0.0
version: 0.8.1.0
synopsis: Install the haskell-ide-engine
license: BSD3
author: Many, TBD when we release

View File

@ -1,8 +1,20 @@
# Used to provide a different environment for the shake build script
resolver: lts-14.11 # GHC 8.6.5
resolver: lts-13.19 # last lts with GHC 8.6.5
# resolver: nightly-2020-01-31 # GHC 8.8.2
# resolver: nightly-2020-01-21 # last nightly GHC 8.8.1
# resolver: lts-13.19 # last lts GHC 8.6.4
# resolver: lts-12.26 # last lts GHC 8.4.4
# resolver: lts-12.14 # last lts GHC 8.4.3
# resolver: nightly-2018-05-30 # last nightly for GHC 8.4.2
packages:
- .
extra-deps:
- shake-0.18.5
# for resolvers with ghc < 8.6
# - shake-0.17
nix:
packages: [ zlib ]

View File

@ -1,23 +1,14 @@
{-# LANGUAGE CPP #-}
module Cabal where
import Development.Shake
import Development.Shake.Command
import Development.Shake.FilePath
import Control.Monad
import Data.Maybe ( isNothing
, isJust
)
import Control.Monad.Extra ( whenMaybe )
import System.Directory ( findExecutable
, copyFile
)
import System.Directory ( copyFile )
import Version
import Print
import Env
import Data.Functor.Identity
#if RUN_FROM_STACK
import Control.Exception ( throwIO )
#else
@ -38,23 +29,23 @@ execCabal = command [] "cabal"
execCabal_ :: [String] -> Action ()
execCabal_ = execCabal
cabalBuildData :: Action ()
cabalBuildData = do
execCabal_ ["v2-build", "hoogle"]
execCabal_ ["v2-exec", "hoogle", "generate"]
cabalBuildData :: [String] -> Action ()
cabalBuildData args = do
execCabal_ $ ["v2-build", "hoogle"] ++ args
execCabal_ $ ["v2-exec", "hoogle", "generate"] ++ args
getGhcPathOfOrThrowError :: VersionNumber -> Action GhcPath
getGhcPathOfOrThrowError versionNumber =
getGhcPathOfOrThrowError versionNumber =
getGhcPathOf versionNumber >>= \case
Nothing -> do
printInStars $ ghcVersionNotFoundFailMsg versionNumber
error (ghcVersionNotFoundFailMsg versionNumber)
Just p -> return p
cabalInstallHie :: VersionNumber -> Action ()
cabalInstallHie versionNumber = do
cabalInstallHie :: VersionNumber -> [String] -> Action ()
cabalInstallHie versionNumber args = do
localBin <- liftIO $ getInstallDir
cabalVersion <- getCabalVersion
cabalVersion <- getCabalVersion args
ghcPath <- getGhcPathOfOrThrowError versionNumber
let isCabal3 = checkVersion [3,0,0,0] cabalVersion
@ -62,19 +53,24 @@ cabalInstallHie versionNumber = do
| otherwise = "--symlink-bindir"
installMethod | isWindowsSystem && isCabal3 = ["--install-method=copy"]
| otherwise = []
projectFile <- getProjectFile versionNumber
execCabal_ $
[ "v2-install"
, "-w", ghcPath
, "--write-ghc-environment-files=never"
, installDirOpt, localBin
, "--max-backjumps=5000"
, "exe:hie"
, "exe:hie", "exe:hie-wrapper"
, "--overwrite-policy=always"
, "--project-file=" ++ projectFile
]
++ installMethod
++ args
let minorVerExe = "hie-" ++ versionNumber <.> exe
majorVerExe = "hie-" ++ dropExtension versionNumber <.> exe
majorVerExe = "hie-" ++ dropExtension versionNumber <.> exe
liftIO $ do
copyFile (localBin </> "hie" <.> exe) (localBin </> minorVerExe)
@ -87,20 +83,27 @@ cabalInstallHie versionNumber = do
++ minorVerExe
++ " to " ++ localBin
checkCabal_ :: Action ()
checkCabal_ = checkCabal >> return ()
getProjectFile :: VersionNumber -> Action FilePath
getProjectFile ver = do
existFile <- doesFileExist $ "cabal.project-" ++ ver
return $ if existFile
then "cabal.project-" ++ ver
else "cabal.project"
checkCabal_ :: [String] -> Action ()
checkCabal_ args = checkCabal args >> return ()
-- | check `cabal` has the required version
checkCabal :: Action String
checkCabal = do
cabalVersion <- getCabalVersion
checkCabal :: [String] -> Action String
checkCabal args = do
cabalVersion <- getCabalVersion args
unless (checkVersion requiredCabalVersion cabalVersion) $ do
printInStars $ cabalInstallIsOldFailMsg cabalVersion
error $ cabalInstallIsOldFailMsg cabalVersion
return cabalVersion
getCabalVersion :: Action String
getCabalVersion = trimmedStdout <$> execCabal ["--numeric-version"]
getCabalVersion :: [String] -> Action String
getCabalVersion args = trimmedStdout <$> (execCabal $ ["--numeric-version"] ++ args)
-- | Error message when the `cabal` binary is an older version
cabalInstallIsOldFailMsg :: String -> String
@ -119,3 +122,21 @@ requiredCabalVersion | isWindowsSystem = requiredCabalVersionForWindows
requiredCabalVersionForWindows :: RequiredVersion
requiredCabalVersionForWindows = [3, 0, 0, 0]
getVerbosityArg :: Verbosity -> String
getVerbosityArg v = "-v" ++ cabalVerbosity
where cabalVerbosity = case v of
Silent -> "0"
#if MIN_VERSION_shake(0,18,4)
Error -> "0"
Warn -> "1"
Info -> "1"
Verbose -> "2"
#else
Quiet -> "0"
Normal -> "1"
Loud -> "2"
Chatty -> "2"
#endif
Diagnostic -> "3"

View File

@ -1,15 +1,11 @@
module Env where
import Development.Shake
import Development.Shake.Command
import Control.Monad.IO.Class
import Control.Monad
import Development.Shake.FilePath
import System.Info ( os
, arch
)
import System.Info ( os )
import Data.Maybe ( isJust
, isNothing
, mapMaybe
)
import System.Directory ( findExecutable

View File

@ -2,21 +2,18 @@
module Help where
import Development.Shake
import Data.List ( intersperse
, intercalate
)
import Data.List ( intercalate )
import Env
import Print
import Version
import BuildSystem
import Cabal
stackCommand :: TargetDescription -> String
stackCommand target = "stack install.hs " ++ fst target
stackCommand target = "stack install.hs " ++ fst target ++ " [options]"
cabalCommand :: TargetDescription -> String
cabalCommand target = "cabal v2-run install.hs --project-file install/shake.project " ++ fst target
cabalCommand target = "cabal v2-run install.hs --project-file install/shake.project -- " ++ fst target ++ " [options]"
buildCommand :: TargetDescription -> String
buildCommand | isRunFromCabal = cabalCommand
@ -37,7 +34,7 @@ shortHelpMessage = do
printUsage
printLine ""
printLine "Targets:"
mapM_ (printLineIndented . showTarget (spaces hieVersions)) (targets hieVersions)
mapM_ (printLineIndented . showHelpItem (spaces hieVersions)) (targets hieVersions)
printLine ""
where
spaces hieVersions = space (targets hieVersions)
@ -68,7 +65,10 @@ helpMessage versions@BuildableVersions {..} = do
printUsage
printLine ""
printLine "Targets:"
mapM_ (printLineIndented . showTarget spaces) targets
mapM_ (printLineIndented . showHelpItem spaces) targets
printLine ""
printLine "Options:"
mapM_ (printLineIndented . showHelpItem spaces) options
printLine ""
where
spaces = space targets
@ -81,6 +81,11 @@ helpMessage versions@BuildableVersions {..} = do
, if isRunFromCabal then [cabalGhcsTarget] else [stackDevTarget]
, [macosIcuTarget]
]
options = [ ("-j[N], --jobs[=N]", "Allow N jobs/threads at once [default number of CPUs].")
, ("-s, --silent", "Don't print anything.")
, ("-q, --quiet", "Print less (pass repeatedly for even less).")
, ("-V, --verbose", "Print more (pass repeatedly for even more).")
]
-- All targets with their respective help message.
generalTargets = [helpTarget]

View File

@ -1,43 +1,13 @@
module HieInstall where
import Development.Shake
import Development.Shake.Command
import Development.Shake.FilePath
import Control.Monad
import Control.Monad.IO.Class
import Control.Monad.Extra ( unlessM
, mapMaybeM
)
import Data.Maybe ( isJust )
import System.Directory ( listDirectory )
import System.Environment ( unsetEnv )
import System.Info ( os
, arch
)
import Data.Maybe ( isNothing
, mapMaybe
)
import Data.List ( dropWhileEnd
, intersperse
, intercalate
, sort
, sortOn
)
import qualified Data.Text as T
import Data.Char ( isSpace )
import Data.Version ( parseVersion
, makeVersion
, showVersion
)
import Data.Function ( (&) )
import Text.ParserCombinators.ReadP ( readP_to_S )
import BuildSystem
import Stack
import Cabal
import Version
import Print
import Env
import Help
@ -53,37 +23,53 @@ defaultMain = do
-- used for stack-based targets
stackVersions <- getHieVersions
let versions = if isRunFromStack then stackVersions else cabalVersions
let versions = if isRunFromStack then stackVersions else cabalVersions
let toolsVersions = BuildableVersions stackVersions cabalVersions
let latestVersion = last versions
shakeArgs shakeOptions { shakeFiles = "_build" } $ do
shakeArgs shakeOptions { shakeFiles = "_build", shakeThreads = 0 } $ do
shakeOptionsRules <- getShakeOptionsRules
let jobsArg = "-j" ++ show (shakeThreads shakeOptionsRules)
let verbosityArg = if isRunFromStack then Stack.getVerbosityArg else Cabal.getVerbosityArg
let args = [jobsArg, verbosityArg (shakeVerbosity shakeOptionsRules)]
phony "show-options" $ do
putNormal $ "Options:"
putNormal $ " Number of jobs: " ++ show (shakeThreads shakeOptionsRules)
putNormal $ " Verbosity level: " ++ show (shakeVerbosity shakeOptionsRules)
want ["short-help"]
-- general purpose targets
phony "submodules" updateSubmodules
phony "short-help" shortHelpMessage
phony "help" (helpMessage toolsVersions)
phony "check" (if isRunFromStack then checkStack else checkCabal_)
phony "check" (if isRunFromStack then checkStack args else checkCabal_ args)
phony "data" $ do
need ["show-options"]
need ["submodules"]
need ["check"]
if isRunFromStack then stackBuildData else cabalBuildData
if isRunFromStack then stackBuildData args else cabalBuildData args
forM_
versions
(\version -> phony ("hie-" ++ version) $ do
need ["show-options"]
need ["submodules"]
need ["check"]
if isRunFromStack then
stackInstallHieWithErrMsg (Just version)
stackInstallHieWithErrMsg (Just version) args
else
cabalInstallHie version
cabalInstallHie version args
)
unless (null versions) $ do
phony "latest" (need ["hie-" ++ latestVersion])
phony "hie" (need ["data", "latest"])
@ -92,7 +78,9 @@ defaultMain = do
-- Default `stack.yaml` uses ghc-8.8.2 and we can't build hie in windows
-- TODO: Enable for windows when it uses ghc-8.8.3
when (isRunFromStack && not isWindowsSystem) $
phony "dev" $ stackInstallHieWithErrMsg Nothing
phony "dev" $ do
need ["show-options"]
stackInstallHieWithErrMsg Nothing args
-- cabal specific targets
when isRunFromCabal $ do
@ -101,20 +89,23 @@ defaultMain = do
phony "ghcs" $ showInstalledGhcs ghcPaths
-- macos specific targets
phony "icu-macos-fix"
(need ["icu-macos-fix-install"] >> need ["icu-macos-fix-build"])
phony "icu-macos-fix" $ do
need ["show-options"]
need ["icu-macos-fix-install"]
need ["icu-macos-fix-build"]
phony "icu-macos-fix-install" (command_ [] "brew" ["install", "icu4c"])
phony "icu-macos-fix-build" $ mapM_ buildIcuMacosFix versions
phony "icu-macos-fix-build" $ mapM_ (flip buildIcuMacosFix $ args) versions
buildIcuMacosFix :: VersionNumber -> Action ()
buildIcuMacosFix version = execStackWithGhc_
version
buildIcuMacosFix :: VersionNumber -> [String] -> Action ()
buildIcuMacosFix version args = execStackWithGhc_
version $
[ "build"
, "text-icu"
, "--extra-lib-dirs=/usr/local/opt/icu4c/lib"
, "--extra-include-dirs=/usr/local/opt/icu4c/include"
]
] ++ args
-- | update the submodules that the project is in the state as required by the `stack.yaml` files
updateSubmodules :: Action ()

View File

@ -1,10 +1,8 @@
module Print where
import Development.Shake
import Development.Shake.Command
import Control.Monad.IO.Class
import Data.List ( dropWhileEnd
, dropWhile
)
import Data.Char ( isSpace )
@ -37,11 +35,11 @@ type TargetDescription = (String, String)
-- | Number of spaces the target name including whitespace should have.
-- At least twenty, maybe more if target names are long. At most the length of the longest target plus five.
space :: [TargetDescription] -> Int
space phonyTargets = maximum (20 : map ((+ 5) . length . fst) phonyTargets)
space :: [(String,String)] -> Int
space helpItems = maximum (20 : map ((+ 5) . length . fst) helpItems)
-- | Show a target.
-- Concatenates the target with its help message and inserts whitespace between them.
showTarget :: Int -> TargetDescription -> String
showTarget spaces (target, msg) =
target ++ replicate (spaces - length target) ' ' ++ msg
showHelpItem :: Int -> (String,String) -> String
showHelpItem spaces (helpItemKey, msg) =
helpItemKey ++ replicate (spaces - length helpItemKey) ' ' ++ msg

View File

@ -1,38 +1,32 @@
{-# LANGUAGE CPP #-}
module Stack where
import Development.Shake
import Development.Shake.Command
import Development.Shake.FilePath
import Control.Exception
import Control.Monad
import Data.List
import System.Directory ( copyFile )
import System.FilePath ( splitSearchPath, searchPathSeparator, (</>) )
import System.Environment ( lookupEnv, setEnv, getEnvironment )
import System.IO.Error ( isDoesNotExistError )
import BuildSystem
-- import System.FilePath ( (</>) )
import Version
import Print
import Env
stackInstallHieWithErrMsg :: Maybe VersionNumber -> Action ()
stackInstallHieWithErrMsg mbVersionNumber =
stackInstallHie mbVersionNumber
stackInstallHieWithErrMsg :: Maybe VersionNumber -> [String] -> Action ()
stackInstallHieWithErrMsg mbVersionNumber args =
stackInstallHie mbVersionNumber args
`actionOnException` liftIO (putStrLn stackBuildFailMsg)
-- | copy the built binaries into the localBinDir
stackInstallHie :: Maybe VersionNumber -> Action ()
stackInstallHie mbVersionNumber = do
versionNumber <-
stackInstallHie :: Maybe VersionNumber -> [String] -> Action ()
stackInstallHie mbVersionNumber args = do
versionNumber <-
case mbVersionNumber of
Nothing -> do
execStackWithCfgFile_ "stack.yaml" ["install"]
getGhcVersionOfCfgFile "stack.yaml"
execStackWithCfgFile_ "stack.yaml" $ ["install"] ++ args
getGhcVersionOfCfgFile "stack.yaml" args
Just vn -> do
execStackWithGhc_ vn ["install"]
execStackWithGhc_ vn $ ["install"] ++ args
return vn
localBinDir <- getLocalBin
localBinDir <- getLocalBin args
let hie = "hie" <.> exe
liftIO $ do
copyFile (localBinDir </> hie)
@ -40,31 +34,31 @@ stackInstallHie mbVersionNumber = do
copyFile (localBinDir </> hie)
(localBinDir </> "hie-" ++ dropExtension versionNumber <.> exe)
getGhcVersionOfCfgFile :: String -> Action VersionNumber
getGhcVersionOfCfgFile stackFile = do
Stdout ghcVersion <-
execStackWithCfgFile stackFile ["exec", "ghc", "--", "--numeric-version"]
getGhcVersionOfCfgFile :: String -> [String] -> Action VersionNumber
getGhcVersionOfCfgFile stackFile args = do
Stdout ghcVersion <-
execStackWithCfgFile stackFile $ ["exec", "ghc"] ++ args ++ ["--", "--numeric-version"]
return $ trim ghcVersion
-- | check `stack` has the required version
checkStack :: Action ()
checkStack = do
stackVersion <- trimmedStdout <$> execStackShake ["--numeric-version"]
checkStack :: [String] -> Action ()
checkStack args = do
stackVersion <- trimmedStdout <$> (execStackShake $ ["--numeric-version"] ++ args)
unless (checkVersion requiredStackVersion stackVersion) $ do
printInStars $ stackExeIsOldFailMsg stackVersion
error $ stackExeIsOldFailMsg stackVersion
-- | Get the local binary path of stack.
-- Equal to the command `stack path --local-bin`
getLocalBin :: Action FilePath
getLocalBin = do
Stdout stackLocalDir' <- execStackShake ["path", "--local-bin"]
getLocalBin :: [String] -> Action FilePath
getLocalBin args = do
Stdout stackLocalDir' <- execStackShake $ ["path", "--local-bin"] ++ args
return $ trim stackLocalDir'
stackBuildData :: Action ()
stackBuildData = do
execStackShake_ ["build", "hoogle"]
execStackShake_ ["exec", "hoogle", "generate"]
stackBuildData :: [String] -> Action ()
stackBuildData args = do
execStackShake_ $ ["build", "hoogle"] ++ args
execStackShake_ $ ["exec", "hoogle", "generate"] ++ args
-- | Execute a stack command for a specified ghc, discarding the output
execStackWithGhc_ :: VersionNumber -> [String] -> Action ()
@ -82,7 +76,7 @@ execStackWithCfgFile_ = execStackWithCfgFile
-- | Execute a stack command for a specified stack.yaml file
execStackWithCfgFile :: CmdResult r => String -> [String] -> Action r
execStackWithCfgFile stackFile args =
execStackWithCfgFile stackFile args =
command [] "stack" (("--stack-yaml=" ++ stackFile) : args)
-- | Execute a stack command with the same resolver as the build script
@ -118,3 +112,20 @@ stackBuildFailMsg =
++ "If this does not work, open an issue at \n"
++ "\thttps://github.com/haskell/haskell-ide-engine"
getVerbosityArg :: Verbosity -> String
getVerbosityArg v = "--verbosity=" ++ stackVerbosity
where stackVerbosity = case v of
Silent -> "silent"
#if MIN_VERSION_shake(0,18,4)
Error -> "error"
Warn -> "warn"
Info -> "info"
Verbose -> "info"
#else
Quiet -> "error"
Normal -> "warn"
Loud -> "info"
Chatty -> "info"
#endif
Diagnostic -> "debug"

View File

@ -6,7 +6,6 @@ import Data.Version ( Version
, showVersion
)
import Text.ParserCombinators.ReadP ( readP_to_S )
import Control.Monad.IO.Class
type VersionNumber = String