Fix wrapper build
[hadrian.git] / src / Builder.hs
1 module Builder (
2 CcMode (..), GhcMode (..), GhcPkgMode (..), Builder (..),
3 builderProvenance, systemBuilderPath, builderPath, getBuilderPath,
4 isSpecified, needBuilder,
5 ) where
6
7 import Development.Shake.Classes
8 import GHC.Generics
9 import Hadrian.Expression
10 import Hadrian.Oracles.Path
11 import Hadrian.Oracles.TextFile
12
13 import Base
14 import Context
15 import GHC
16
17 -- | C compiler can be used in two different modes:
18 -- * Compile or preprocess a source file.
19 -- * Extract source dependencies by passing @-MM@ command line argument.
20 data CcMode = CompileC | FindCDependencies deriving (Eq, Generic, Show)
21
22 instance Binary CcMode
23 instance Hashable CcMode
24 instance NFData CcMode
25
26 -- | GHC can be used in four different modes:
27 -- * Compile a Haskell source file.
28 -- * Compile a C source file.
29 -- * Extract source dependencies by passing @-M@ command line argument.
30 -- * Link object files & static libraries into an executable.
31 data GhcMode = CompileHs | CompileCWithGhc | FindHsDependencies | LinkHs
32 deriving (Eq, Generic, Show)
33
34 instance Binary GhcMode
35 instance Hashable GhcMode
36 instance NFData GhcMode
37
38 -- | GhcPkg can initialise a package database and register packages in it.
39 data GhcPkgMode = Init | Update deriving (Eq, Generic, Show)
40
41 instance Binary GhcPkgMode
42 instance Hashable GhcPkgMode
43 instance NFData GhcPkgMode
44
45 -- | A 'Builder' is an external command invoked in a separate process via 'cmd'.
46 -- @Ghc Stage0@ is the bootstrapping compiler.
47 -- @Ghc StageN@, N > 0, is the one built in stage (N - 1).
48 -- @GhcPkg Stage0@ is the bootstrapping @GhcPkg@.
49 -- @GhcPkg Stage1@ is the one built in Stage0.
50 data Builder = Alex
51 | Ar Stage
52 | DeriveConstants
53 | Cc CcMode Stage
54 | Configure FilePath
55 | GenApply
56 | GenPrimopCode
57 | Ghc GhcMode Stage
58 | GhcCabal
59 | GhcCabalHsColour -- synonym for 'GhcCabal hscolour'
60 | GhcPkg GhcPkgMode Stage
61 | Haddock
62 | Happy
63 | Hpc
64 | HsColour
65 | HsCpp
66 | Hsc2Hs
67 | Ld
68 | Make FilePath
69 | Nm
70 | Objdump
71 | Patch
72 | Perl
73 | Ranlib
74 | Tar
75 | Unlit
76 deriving (Eq, Generic, Show)
77
78 instance Binary Builder
79 instance Hashable Builder
80 instance NFData Builder
81
82 -- | Some builders are built by this very build system, in which case
83 -- 'builderProvenance' returns the corresponding build 'Context' (which includes
84 -- 'Stage' and GHC 'Package').
85 builderProvenance :: Builder -> Maybe Context
86 builderProvenance = \case
87 DeriveConstants -> context Stage0 deriveConstants
88 GenApply -> context Stage0 genapply
89 GenPrimopCode -> context Stage0 genprimopcode
90 Ghc _ Stage0 -> Nothing
91 Ghc _ stage -> context (pred stage) ghc
92 GhcCabal -> context Stage0 ghcCabal
93 GhcCabalHsColour -> builderProvenance $ GhcCabal
94 GhcPkg _ Stage0 -> Nothing
95 GhcPkg _ _ -> context Stage0 ghcPkg
96 Haddock -> context Stage2 haddock
97 Hpc -> context Stage1 hpcBin
98 Hsc2Hs -> context Stage0 hsc2hs
99 Unlit -> context Stage0 unlit
100 _ -> Nothing
101 where
102 context s p = Just $ vanillaContext s p
103
104 -- | Make sure a 'Builder' exists and rebuild it if out of date.
105 needBuilder :: Builder -> Action ()
106 needBuilder (Configure dir) = need [dir -/- "configure"]
107 needBuilder (Make dir) = need [dir -/- "Makefile"]
108 needBuilder builder = when (isJust $ builderProvenance builder) $ do
109 path <- builderPath builder
110 need [path]
111
112 -- TODO: Some builders are required only on certain platforms. For example,
113 -- Objdump is only required on OpenBSD and AIX, as mentioned in #211. Add
114 -- support for platform-specific optional builders as soon as we can reliably
115 -- test this feature.
116 isOptional :: Builder -> Bool
117 isOptional = \case
118 HsColour -> True
119 Objdump -> True
120 _ -> False
121
122 -- | Determine the location of a system 'Builder'.
123 systemBuilderPath :: Builder -> Action FilePath
124 systemBuilderPath builder = case builder of
125 Alex -> fromKey "alex"
126 Ar Stage0 -> fromKey "system-ar"
127 Ar _ -> fromKey "ar"
128 Cc _ Stage0 -> fromKey "system-cc"
129 Cc _ _ -> fromKey "cc"
130 -- We can't ask configure for the path to configure!
131 Configure _ -> return "sh configure"
132 Ghc _ Stage0 -> fromKey "system-ghc"
133 GhcPkg _ Stage0 -> fromKey "system-ghc-pkg"
134 Happy -> fromKey "happy"
135 HsColour -> fromKey "hscolour"
136 HsCpp -> fromKey "hs-cpp"
137 Ld -> fromKey "ld"
138 Make _ -> fromKey "make"
139 Nm -> fromKey "nm"
140 Objdump -> fromKey "objdump"
141 Patch -> fromKey "patch"
142 Perl -> fromKey "perl"
143 Ranlib -> fromKey "ranlib"
144 Tar -> fromKey "tar"
145 _ -> error $ "No entry for " ++ show builder ++ inCfg
146 where
147 inCfg = " in " ++ quote configFile ++ " file."
148 fromKey key = do
149 let unpack = fromMaybe . error $ "Cannot find path to builder "
150 ++ quote key ++ inCfg ++ " Did you skip configure?"
151 path <- unpack <$> lookupValue configFile key
152 if null path
153 then do
154 unless (isOptional builder) . error $ "Non optional builder "
155 ++ quote key ++ " is not specified" ++ inCfg
156 return "" -- TODO: Use a safe interface.
157 else fixAbsolutePathOnWindows =<< lookupInPath path
158
159 -- | Determine the location of a 'Builder'.
160 builderPath :: Builder -> Action FilePath
161 builderPath builder = case builderProvenance builder of
162 Nothing -> systemBuilderPath builder
163 Just context -> programPath context
164
165 -- | Was the path to a given system 'Builder' specified in configuration files?
166 isSpecified :: Builder -> Action Bool
167 isSpecified = fmap (not . null) . systemBuilderPath
168
169 getBuilderPath :: Builder -> Expr c Builder FilePath
170 getBuilderPath = expr . builderPath