From b46a5314546a6d7ff3f06eaa4dc8aea212c6be83 Mon Sep 17 00:00:00 2001 From: jneira Date: Mon, 24 Feb 2020 12:17:24 +0100 Subject: [PATCH] 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 --- install/hie-install.cabal | 2 +- install/shake.yaml | 14 ++++++- install/src/Cabal.hs | 75 ++++++++++++++++++++++------------- install/src/Env.hs | 6 +-- install/src/Help.hs | 21 ++++++---- install/src/HieInstall.hs | 83 +++++++++++++++++---------------------- install/src/Print.hs | 12 +++--- install/src/Stack.hs | 79 +++++++++++++++++++++---------------- install/src/Version.hs | 1 - 9 files changed, 163 insertions(+), 130 deletions(-) diff --git a/install/hie-install.cabal b/install/hie-install.cabal index 013d246f..39e73f63 100644 --- a/install/hie-install.cabal +++ b/install/hie-install.cabal @@ -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 diff --git a/install/shake.yaml b/install/shake.yaml index 8c30114f..17b5d4ab 100644 --- a/install/shake.yaml +++ b/install/shake.yaml @@ -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 ] diff --git a/install/src/Cabal.hs b/install/src/Cabal.hs index 72fd00b0..205d7571 100644 --- a/install/src/Cabal.hs +++ b/install/src/Cabal.hs @@ -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" + diff --git a/install/src/Env.hs b/install/src/Env.hs index 83c23b0f..c53557aa 100644 --- a/install/src/Env.hs +++ b/install/src/Env.hs @@ -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 diff --git a/install/src/Help.hs b/install/src/Help.hs index a512f259..547cf39a 100644 --- a/install/src/Help.hs +++ b/install/src/Help.hs @@ -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] diff --git a/install/src/HieInstall.hs b/install/src/HieInstall.hs index d46e2bff..b2afbde1 100644 --- a/install/src/HieInstall.hs +++ b/install/src/HieInstall.hs @@ -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 () diff --git a/install/src/Print.hs b/install/src/Print.hs index 41216022..063525e7 100644 --- a/install/src/Print.hs +++ b/install/src/Print.hs @@ -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 diff --git a/install/src/Stack.hs b/install/src/Stack.hs index ec8aabcd..3049ec9c 100644 --- a/install/src/Stack.hs +++ b/install/src/Stack.hs @@ -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" \ No newline at end of file diff --git a/install/src/Version.hs b/install/src/Version.hs index 0d89b4b9..46470041 100644 --- a/install/src/Version.hs +++ b/install/src/Version.hs @@ -6,7 +6,6 @@ import Data.Version ( Version , showVersion ) import Text.ParserCombinators.ReadP ( readP_to_S ) -import Control.Monad.IO.Class type VersionNumber = String