Skip to content
This repository was archived by the owner on Oct 7, 2020. It is now read-only.

Commit 8fd5cba

Browse files
committed
improve consistency in the install.hs script
1 parent e1b3157 commit 8fd5cba

File tree

1 file changed

+91
-101
lines changed

1 file changed

+91
-101
lines changed

install.hs

Lines changed: 91 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,17 @@
44
--resolver nightly-2018-12-15
55
--package shake
66
--package directory
7+
--package extra
78
-}
9+
{-# LANGUAGE LambdaCase #-}
10+
{-# LANGUAGE TupleSections #-}
811
import Development.Shake
912
import Development.Shake.Command
1013
import Development.Shake.FilePath
1114
import Control.Monad
15+
import Control.Monad.IO.Class
16+
import Control.Monad.Extra (unlessM, mapMaybeM)
17+
import Data.Maybe (isJust)
1218
import System.Directory ( findExecutable )
1319
import System.Environment ( getProgName
1420
, unsetEnv
@@ -19,6 +25,7 @@ import System.Info ( os
1925

2026
import Data.List ( dropWhileEnd
2127
, intersperse
28+
, intercalate
2229
)
2330
import Data.Char ( isSpace )
2431

@@ -57,7 +64,7 @@ main = do
5764
want ["short-help"]
5865
-- general purpose targets
5966
phony "submodules" updateSubmodules
60-
phony "cabal" (getStackGhcPath mostRecentHieVersion >>= installCabal)
67+
phony "cabal" installCabal
6168
phony "short-help" shortHelpMessage
6269
phony "all" shortHelpMessage
6370
phony "help" helpMessage
@@ -72,26 +79,21 @@ main = do
7279
)
7380
liftIO $ putStrLn $ embedInStars msg
7481

75-
7682
-- stack specific targets
7783
phony "build" (need (reverse $ map ("hie-" ++) hieVersions))
78-
phony "build-all" (need ["build-docs", "build"])
79-
phony "build-docs" (need (reverse $ map ("build-doc-" ++) hieVersions))
84+
phony "build-all" (need ["build-doc", "build"])
8085
phony "test" $ do
8186
need ["submodules"]
8287
need ["cabal"]
8388
forM_ hieVersions stackTest
8489

8590
phony "build-copy-compiler-tool" $ forM_ hieVersions buildCopyCompilerTool
8691

87-
phony "stack-build-doc" stackBuildDoc
88-
forM_
89-
hieVersions
90-
(\version -> phony ("build-doc-" ++ version) $ do
92+
phony "build-doc" $ do
9193
need ["submodules"]
92-
need ["cabal"]
93-
need ["stack-build-doc"]
94-
)
94+
stackBuildDoc
95+
96+
-- main targets for building hie with `stack`
9597
forM_
9698
hieVersions
9799
(\version -> phony ("hie-" ++ version) $ do
@@ -103,22 +105,17 @@ main = do
103105

104106
-- cabal specific targets
105107
phony "cabal-build" (need (map ("cabal-hie-" ++) ghcVersions))
106-
phony "cabal-build-all" (need ["cabal-build-docs", "cabal-build"])
107-
phony "cabal-build-docs" (need (map ("cabal-build-doc-" ++) ghcVersions))
108+
phony "cabal-build-all" (need ["cabal-build-doc", "cabal-build"])
109+
phony "cabal-build-doc" $ do
110+
need ["submodules"]
111+
need ["cabal"]
112+
cabalBuildDoc
108113

109114
phony "cabal-test" $ do
110115
need ["submodules"]
111116
need ["cabal"]
112117
forM_ ghcVersions cabalTest
113118

114-
phony "cabal-doc" cabalBuildDoc
115-
forM_
116-
hieVersions
117-
(\version -> phony ("cabal-build-doc-" ++ version) $ do
118-
need ["submodules"]
119-
need ["cabal"]
120-
need ["cabal-doc"]
121-
)
122119
forM_
123120
hieVersions
124121
(\version -> phony ("cabal-hie-" ++ version) $ do
@@ -145,6 +142,7 @@ buildIcuMacosFix version = execStackWithYaml_
145142
, "--extra-include-dirs=/usr/local/opt/icu4c/include"
146143
]
147144

145+
-- |update the submodules that the project is in the state as required by the `stack.yaml` files
148146
updateSubmodules :: Action ()
149147
updateSubmodules = do
150148
command_ [] "git" ["submodule", "sync", "--recursive"]
@@ -157,24 +155,21 @@ validateCabalNewInstallIsSupported = when (os `elem` ["mingw32", "win32"]) $ do
157155

158156
configureCabal :: VersionNumber -> Action ()
159157
configureCabal versionNumber = do
160-
ghcPath' <- liftIO $ getGhcPath versionNumber
161-
ghcPath <- case ghcPath' of
162-
Nothing -> do
158+
ghcPath <- getGhcPath versionNumber >>= \case
159+
Nothing -> do -- TODO: this is better written using a monad-transformer
163160
liftIO $ putStrLn $ embedInStars (ghcVersionNotFound versionNumber)
164161
error (ghcVersionNotFound versionNumber)
165162
Just p -> return p
166163
execCabal_
167164
["new-configure", "-w", ghcPath, "--write-ghc-environment-files=never"]
168165

169166
findInstalledGhcs :: IO [(VersionNumber, GhcPath)]
170-
findInstalledGhcs = foldM
171-
(\found version -> do
172-
path <- getGhcPath version
173-
case path of
174-
Nothing -> return found
175-
Just p -> return $ (version, p) : found
167+
findInstalledGhcs = mapMaybeM
168+
(\version -> do
169+
getGhcPath version >>= \case
170+
Nothing -> return Nothing
171+
Just p -> return $ Just (version, p)
176172
)
177-
[]
178173
hieVersions
179174

180175
cabalBuildHie :: VersionNumber -> Action ()
@@ -198,36 +193,30 @@ cabalInstallHie versionNumber = do
198193
(localBin </> "hie-" ++ dropExtension versionNumber <.> exe)
199194

200195
cabalBuildDoc :: Action ()
201-
cabalBuildDoc = generateHoogleDatabase $ do
202-
localBin <- getLocalBin
203-
execCabal_ ["new-install", "--symlink-bindir=" ++ localBin, "hoogle"]
196+
cabalBuildDoc = do
197+
execCabal_ ["new-build", "hoogle", "generate"]
204198
execCabal_ ["new-exec", "hoogle", "generate"]
205199

206-
generateHoogleDatabase :: Action () -> Action ()
207-
generateHoogleDatabase installIfNecessary = do
208-
mayHoogle <- liftIO $ findExecutable "hoogle"
209-
case mayHoogle of
210-
Nothing -> installIfNecessary
211-
Just hoogle -> command_ [] "hoogle" ["generate"]
212-
213-
214200
cabalTest :: VersionNumber -> Action ()
215201
cabalTest versionNumber = do
216202
configureCabal versionNumber
217203
execCabal_ ["new-test"]
218204

219-
installCabal :: GhcPath -> Action ()
220-
installCabal ghc = do
221-
execStack_ ["install", "--stack-yaml=shake.yaml", "cabal-install"]
205+
installCabal :: Action ()
206+
installCabal = do
207+
-- install `cabal-install` if not already installed
208+
unlessM (existsExecutable "cabal") $ do
209+
execStack_ ["install", "--stack-yaml=shake.yaml", "cabal-install"]
222210
execCabal_ ["update"]
211+
ghc <- getStackGhcPath mostRecentHieVersion
223212
execCabal_ ["install", "Cabal-2.4.1.0", "--with-compiler=" ++ ghc]
224213

225214
stackBuildHie :: VersionNumber -> Action ()
226215
stackBuildHie versionNumber = do
227-
execStackWithYaml_ versionNumber ["install", "happy"]
228216
execStackWithYaml_ versionNumber ["build"]
229217
`actionOnException` liftIO (putStrLn stackBuildFailMsg)
230218

219+
-- | copy the built binaries into the localBinDir
231220
stackInstallHie :: VersionNumber -> Action ()
232221
stackInstallHie versionNumber = do
233222
execStackWithYaml_ versionNumber ["install"]
@@ -247,10 +236,11 @@ stackTest :: VersionNumber -> Action ()
247236
stackTest versionNumber = execStackWithYaml_ versionNumber ["test"]
248237

249238
stackBuildDoc :: Action ()
250-
stackBuildDoc = generateHoogleDatabase $ do
251-
execStack_ ["--stack-yaml=shake.yaml", "install", "hoogle"]
239+
stackBuildDoc = do
240+
execStack_ ["--stack-yaml=shake.yaml", "build", "hoogle"]
252241
execStack_ ["--stack-yaml=shake.yaml", "exec", "hoogle", "generate"]
253242

243+
-- | short help message is printed by default
254244
shortHelpMessage :: Action ()
255245
shortHelpMessage = do
256246
let out = liftIO . putStrLn
@@ -275,25 +265,19 @@ shortHelpMessage = do
275265
++ allVersionMessage hieVersions
276266
++ ")"
277267
)
278-
, ( "build-all"
279-
, "Builds hie and hoogle databases for all supported GHC versions"
280-
)
268+
, stackBuildAllTarget
281269
, stackHieTarget mostRecentHieVersion
282-
, stackBuildDocTarget mostRecentHieVersion
270+
, stackBuildDocTarget
283271
, stackHieTarget "8.4.4"
284-
, stackBuildDocTarget "8.4.4"
285272
, emptyTarget
286273
, ( "cabal-ghcs"
287274
, "Show all GHC versions that can be installed via `cabal-build` and `cabal-build-all`."
288275
)
289-
, ("cabal-build", "Builds hie with cabal with all installed GHCs.")
290-
, ( "cabal-build-all"
291-
, "Builds hie and hoogle databases for all installed GHC versions with cabal"
292-
)
276+
, cabalBuildTarget
277+
, cabalBuildAllTarget
293278
, cabalHieTarget mostRecentHieVersion
294-
, cabalBuildDocTarget mostRecentHieVersion
279+
, cabalBuildDocTarget
295280
, cabalHieTarget "8.4.4"
296-
, cabalBuildDocTarget "8.4.4"
297281
]
298282

299283

@@ -315,13 +299,13 @@ helpMessage = do
315299
-- All targets the shake file supports
316300
targets :: [(String, String)]
317301
targets =
318-
generalTargets
319-
++ [emptyTarget]
320-
++ stackTargets
321-
++ [emptyTarget]
322-
++ cabalTargets
323-
++ [emptyTarget]
324-
++ macosTargets
302+
intercalate
303+
[emptyTarget]
304+
[ generalTargets
305+
, stackTargets
306+
, cabalTargets
307+
, macosTargets
308+
]
325309

326310
-- All targets with their respective help message.
327311
generalTargets =
@@ -339,39 +323,29 @@ helpMessage = do
339323
++ allVersionMessage hieVersions
340324
++ ")"
341325
)
342-
, ( "build-all"
343-
, "Builds hie and hoogle databases for all supported GHC versions"
344-
)
345-
, ( "build-docs"
346-
, "Builds the Hoogle database for all supported GHC versions"
347-
)
326+
, stackBuildAllTarget
327+
, stackBuildDocTarget
348328
, ("test", "Runs hie tests with stack")
349329
]
350330
++ map stackHieTarget hieVersions
351-
++ map stackBuildDocTarget hieVersions
352331

353332
cabalTargets =
354333
[ ( "cabal-ghcs"
355334
, "Show all GHC versions that can be installed via `cabal-build` and `cabal-build-all`."
356335
)
357-
, ("cabal-build", "Builds hie with cabal with all installed GHCs.")
358-
, ( "cabal-build-all"
359-
, "Builds hie and hoogle databases for all installed GHC versions with cabal"
360-
)
361-
, ( "cabal-build-docs"
362-
, "Builds the Hoogle database for all installed GHC versions with cabal"
363-
)
336+
, cabalBuildTarget
337+
, cabalBuildAllTarget
338+
, cabalBuildDocTarget
364339
, ("cabal-test", "Runs hie tests with cabal")
365340
]
366341
++ map cabalHieTarget hieVersions
367-
++ map cabalBuildDocTarget hieVersions
368342

369343
-- | Empty target. Purpose is to introduce a newline between the targets
370344
emptyTarget :: (String, String)
371345
emptyTarget = ("", "")
372346

373347
-- |Number of spaces the target name including whitespace should have.
374-
-- At least twenty, maybe more if target names are long. At most length of the longest target plus five.
348+
-- At least twenty, maybe more if target names are long and at least the length of the longest target plus five.
375349
space :: [(String, String)] -> Int
376350
space phonyTargets = maximum (20 : map ((+ 5) . length . fst) phonyTargets)
377351

@@ -395,20 +369,32 @@ cabalHieTarget version =
395369
, "Builds hie for GHC version " ++ version ++ " only with cabal new-build"
396370
)
397371

398-
stackBuildDocTarget :: VersionNumber -> (String, String)
399-
stackBuildDocTarget version =
400-
( "build-doc-" ++ version
401-
, "Builds the Hoogle database for GHC version "
402-
++ version
403-
++ " only with stack"
372+
stackBuildDocTarget :: (String, String)
373+
stackBuildDocTarget =
374+
( "build-doc"
375+
, "Builds the Hoogle database"
376+
)
377+
378+
stackBuildAllTarget :: (String, String)
379+
stackBuildAllTarget =
380+
( "build-all"
381+
, "Builds hie for all supported GHC versions and the hoogle database"
382+
)
383+
384+
cabalBuildTarget :: (String, String)
385+
cabalBuildTarget =
386+
("cabal-build", "Builds hie with cabal with all installed GHCs.")
387+
388+
cabalBuildDocTarget :: (String, String)
389+
cabalBuildDocTarget =
390+
( "cabal-build-doc"
391+
, "Builds the Hoogle database with cabal"
404392
)
405393

406-
cabalBuildDocTarget :: VersionNumber -> (String, String)
407-
cabalBuildDocTarget version =
408-
( "cabal-build-doc-" ++ version
409-
, "Builds the Hoogle database for GHC version "
410-
++ version
411-
++ " only with cabal"
394+
cabalBuildAllTarget :: (String, String)
395+
cabalBuildAllTarget =
396+
( "cabal-build-all"
397+
, "Builds hie for all installed GHC versions and the hoogle database with cabal"
412398
)
413399

414400
-- | Creates a message of the form "a, b, c and d", where a,b,c,d are GHC versions.
@@ -422,6 +408,9 @@ allVersionMessage wordList = case wordList of
422408
lastVersion = last msg
423409
in concat $ (init $ init msg) ++ [" and ", lastVersion]
424410

411+
412+
-- TODO: more sophisticated interface to stack and cabal
413+
425414
execStackWithYaml_ :: VersionNumber -> [String] -> Action ()
426415
execStackWithYaml_ versionNumber args = do
427416
let stackFile = "stack-" ++ versionNumber ++ ".yaml"
@@ -441,6 +430,9 @@ execStack_ = command_ [] "stack"
441430
execCabal_ :: [String] -> Action ()
442431
execCabal_ = command_ [] "cabal"
443432

433+
existsExecutable :: MonadIO m => String -> m Bool
434+
existsExecutable executable = liftIO $ isJust <$> findExecutable executable
435+
444436
-- |Get the path to the GHC compiler executable linked to the local `stack-$GHCVER.yaml`.
445437
-- Equal to the command `stack path --stack-yaml $stack-yaml --compiler-exe`.
446438
-- This might install a GHC if it is not already installed, thus, might fail if stack fails to install the GHC.
@@ -453,14 +445,12 @@ getStackGhcPath ghcVersion = do
453445
-- If no such GHC can be found, Nothing is returned.
454446
-- First, it is checked whether there is a GHC with the name `ghc-$VersionNumber`.
455447
-- If this yields no result, it is checked, whether the numeric-version of the `ghc`
456-
-- command fits to the desired version.
457-
getGhcPath :: VersionNumber -> IO (Maybe GhcPath)
458-
getGhcPath ghcVersion = do
459-
pathMay <- findExecutable ("ghc-" ++ ghcVersion)
460-
case pathMay of
448+
-- command fits to the desired version.
449+
getGhcPath :: MonadIO m => VersionNumber -> m (Maybe GhcPath)
450+
getGhcPath ghcVersion = liftIO $ do
451+
findExecutable ("ghc-" ++ ghcVersion) >>= \case
461452
Nothing -> do
462-
noPrefixPathMay <- findExecutable "ghc"
463-
case noPrefixPathMay of
453+
findExecutable "ghc" >>= \case
464454
Nothing -> return Nothing
465455
Just p -> do
466456
Stdout version <- cmd p ["--numeric-version"] :: IO (Stdout String)

0 commit comments

Comments
 (0)