Use Cabal directly in place of ghc-cabal + make build root configurable (#531)
[hadrian.git] / src / Expression.hs
1 module Expression (
2 -- * Expressions
3 Expr, Predicate, Args, Ways,
4
5 -- ** Construction and modification
6 expr, exprIO, arg, remove,
7
8 -- ** Predicates
9 (?), stage, stage0, stage1, stage2, notStage0, package, notPackage,
10 libraryPackage, builder, way, input, inputs, output, outputs,
11
12 -- ** Evaluation
13 interpret, interpretInContext,
14
15 -- * Convenient accessors
16 getBuildRoot, getContext, getOutputs, getInputs,
17 getInput, getOutput, getPackageData,
18
19 -- * Re-exports
20 module Base,
21 module Builder,
22 module Context,
23 ) where
24
25 import Base
26 import {-# SOURCE #-} Builder
27 import Context hiding (stage, package, way)
28 import Expression.Type
29 import Hadrian.Expression hiding (Expr, Predicate, Args)
30 import Hadrian.Haskell.Cabal.PackageData (PackageData)
31 import Hadrian.Oracles.TextFile (readPackageDataFile)
32
33 -- | Get values from a configured cabal stage.
34 getPackageData :: (PackageData -> a) -> Expr a
35 getPackageData key = do
36 ctx <- getContext
37 Just cabal <- expr (readPackageDataFile ctx)
38 return $ key cabal
39
40 -- | Is the build currently in the provided stage?
41 stage :: Stage -> Predicate
42 stage s = (s ==) <$> getStage
43
44 -- | Is a particular package being built?
45 package :: Package -> Predicate
46 package p = (p ==) <$> getPackage
47
48 -- | This type class allows the user to construct both precise builder
49 -- predicates, such as @builder (Ghc CompileHs Stage1)@, as well as predicates
50 -- covering a set of similar builders. For example, @builder (Ghc CompileHs)@
51 -- matches any stage, and @builder Ghc@ matches any stage and any GHC mode.
52 class BuilderPredicate a where
53 -- | Is a particular builder being used?
54 builder :: a -> Predicate
55
56 instance BuilderPredicate Builder where
57 builder b = (b ==) <$> getBuilder
58
59 instance BuilderPredicate a => BuilderPredicate (Stage -> a) where
60 builder f = builder . f =<< getStage
61
62 instance BuilderPredicate a => BuilderPredicate (CcMode -> a) where
63 builder f = do
64 b <- getBuilder
65 case b of
66 Cc c _ -> builder (f c)
67 _ -> return False
68
69 instance BuilderPredicate a => BuilderPredicate (GhcMode -> a) where
70 builder f = do
71 b <- getBuilder
72 case b of
73 Ghc c _ -> builder (f c)
74 _ -> return False
75
76 instance BuilderPredicate a => BuilderPredicate (FilePath -> a) where
77 builder f = do
78 b <- getBuilder
79 case b of
80 Configure path -> builder (f path)
81 _ -> return False
82
83 -- | Is the current build 'Way' equal to a certain value?
84 way :: Way -> Predicate
85 way w = (w ==) <$> getWay
86
87 -- | Is the build currently in stage 0?
88 stage0 :: Predicate
89 stage0 = stage Stage0
90
91 -- | Is the build currently in stage 1?
92 stage1 :: Predicate
93 stage1 = stage Stage1
94
95 -- | Is the build currently in stage 2?
96 stage2 :: Predicate
97 stage2 = stage Stage2
98
99 -- | Is the build /not/ in stage 0 right now?
100 notStage0 :: Predicate
101 notStage0 = notM stage0
102
103 -- | Is a certain package /not/ built right now?
104 notPackage :: Package -> Predicate
105 notPackage = notM . package
106
107 -- | Is a library package currently being built?
108 libraryPackage :: Predicate
109 libraryPackage = isLibrary <$> getPackage