a3a3f547fd0c38e1ce8dc8a2b59f5c18e5827433
[ghc.git] / hadrian / src / Builder.hs
1 {-# LANGUAGE InstanceSigs #-}
2 module Builder (
3 -- * Data types
4 ArMode (..), CcMode (..), ConfigurationInfo (..), GhcMode (..),
5 GhcPkgMode (..), HaddockMode (..), SphinxMode (..), TarMode (..),
6 Builder (..),
7
8 -- * Builder properties
9 builderProvenance, systemBuilderPath, builderPath, isSpecified, needBuilder,
10 runBuilder, runBuilderWith, runBuilderWithCmdOptions, getBuilderPath,
11 builderEnvironment,
12
13 -- * Ad hoc builder invocation
14 applyPatch
15 ) where
16
17 import Development.Shake.Classes
18 import GHC.Generics
19 import qualified Hadrian.Builder as H
20 import Hadrian.Builder hiding (Builder)
21 import Hadrian.Builder.Ar
22 import Hadrian.Builder.Sphinx
23 import Hadrian.Builder.Tar
24 import Hadrian.Oracles.Path
25 import Hadrian.Oracles.TextFile
26 import Hadrian.Utilities
27
28 import Base
29 import Context
30 import Oracles.Flag
31 import Oracles.Setting
32 import Packages
33
34 -- | C compiler can be used in two different modes:
35 -- * Compile or preprocess a source file.
36 -- * Extract source dependencies by passing @-MM@ command line argument.
37 data CcMode = CompileC | FindCDependencies deriving (Eq, Generic, Show)
38
39 instance Binary CcMode
40 instance Hashable CcMode
41 instance NFData CcMode
42
43 -- | GHC can be used in four different modes:
44 -- * Compile a Haskell source file.
45 -- * Compile a C source file.
46 -- * Extract source dependencies by passing @-M@ command line argument.
47 -- * Link object files & static libraries into an executable.
48 data GhcMode = CompileHs | CompileCWithGhc | FindHsDependencies | LinkHs
49 deriving (Eq, Generic, Show)
50
51 instance Binary GhcMode
52 instance Hashable GhcMode
53 instance NFData GhcMode
54
55 -- | To configure a package we need two pieces of information, which we choose
56 -- to record separately for convenience.
57 --
58 -- * Command line arguments to be passed to the setup script.
59 --
60 -- * Package configuration flags that enable/disable certain package features.
61 -- Here is an example from "Settings.Packages":
62 --
63 -- > package rts
64 -- > ? builder (Cabal Flags)
65 -- > ? any (wayUnit Profiling) rtsWays
66 -- > ? arg "profiling"
67 --
68 -- This instructs package configuration functions (such as 'configurePackage')
69 -- to enable the @profiling@ Cabal flag when processing @rts.cabal@ and
70 -- building RTS with profiling information.
71 data ConfigurationInfo = Setup | Flags deriving (Eq, Generic, Show)
72
73 instance Binary ConfigurationInfo
74 instance Hashable ConfigurationInfo
75 instance NFData ConfigurationInfo
76
77 -- TODO: Do we really need all these modes? Why do we need 'Dependencies'? We
78 -- can extract dependencies using the Cabal library.
79 -- | 'GhcPkg' can initialise a package database and register packages in it.
80 data GhcPkgMode = Init -- ^ Initialize a new database.
81 | Update -- ^ Update a package.
82 | Copy -- ^ Copy a package from one database to another.
83 | Unregister -- ^ Unregister a package.
84 | Dependencies -- ^ Compute package dependencies.
85 deriving (Eq, Generic, Show)
86
87 instance Binary GhcPkgMode
88 instance Hashable GhcPkgMode
89 instance NFData GhcPkgMode
90
91 -- | Haddock can be used in two different modes:
92 -- * Generate documentation for a single package
93 -- * Generate an index page for a collection of packages
94 data HaddockMode = BuildPackage | BuildIndex deriving (Eq, Generic, Show)
95
96 instance Binary HaddockMode
97 instance Hashable HaddockMode
98 instance NFData HaddockMode
99
100 -- | A 'Builder' is a (usually external) command invoked in a separate process
101 -- via 'cmd'. Here are some examples:
102 -- * 'Alex' is a lexical analyser generator that builds @Lexer.hs@ from @Lexer.x@.
103 -- * 'Ghc' 'Stage0' is the bootstrapping Haskell compiler used in 'Stage0'.
104 -- * 'Ghc' @StageN@ (N > 0) is the GHC built in stage (N - 1) and used in @StageN@.
105 --
106 -- The 'Cabal' builder is unusual in that it does not correspond to an external
107 -- program but instead relies on the Cabal library for package configuration.
108 data Builder = Alex
109 | Ar ArMode Stage
110 | Autoreconf FilePath
111 | DeriveConstants
112 | Cabal ConfigurationInfo Stage
113 | Cc CcMode Stage
114 | Configure FilePath
115 | GenApply
116 | GenPrimopCode
117 | Ghc GhcMode Stage
118 | GhcPkg GhcPkgMode Stage
119 | Haddock HaddockMode
120 | Happy
121 | Hpc
122 | Hp2Ps
123 | HsCpp
124 | Hsc2Hs Stage
125 | Ld Stage
126 | Make FilePath
127 | Nm
128 | Objdump
129 | Patch
130 | Perl
131 | Python
132 | Ranlib
133 | RunTest
134 | Sphinx SphinxMode
135 | Tar TarMode
136 | Unlit
137 | Xelatex
138 deriving (Eq, Generic, Show)
139
140 instance Binary Builder
141 instance Hashable Builder
142 instance NFData Builder
143
144 -- | Some builders are built by this very build system, in which case
145 -- 'builderProvenance' returns the corresponding build 'Context' (which includes
146 -- 'Stage' and GHC 'Package').
147 builderProvenance :: Builder -> Maybe Context
148 builderProvenance = \case
149 DeriveConstants -> context Stage0 deriveConstants
150 GenApply -> context Stage0 genapply
151 GenPrimopCode -> context Stage0 genprimopcode
152 Ghc _ Stage0 -> Nothing
153 Ghc _ stage -> context (pred stage) ghc
154 GhcPkg _ Stage0 -> Nothing
155 GhcPkg _ s -> context (pred s) ghcPkg
156 Haddock _ -> context Stage1 haddock
157 Hpc -> context Stage1 hpcBin
158 Hp2Ps -> context Stage0 hp2ps
159 Hsc2Hs _ -> context Stage0 hsc2hs
160 Unlit -> context Stage0 unlit
161 _ -> Nothing
162 where
163 context s p = Just $ vanillaContext s p
164
165 instance H.Builder Builder where
166 builderPath :: Builder -> Action FilePath
167 builderPath builder = case builderProvenance builder of
168 Nothing -> systemBuilderPath builder
169 Just context -> programPath context
170
171 runtimeDependencies :: Builder -> Action [FilePath]
172 runtimeDependencies = \case
173 Autoreconf dir -> return [dir -/- "configure.ac"]
174 Configure dir -> return [dir -/- "configure"]
175
176 Ghc _ Stage0 -> return []
177 Ghc _ stage -> do
178 root <- buildRoot
179 win <- windowsHost
180 touchyPath <- programPath (vanillaContext Stage0 touchy)
181 unlitPath <- builderPath Unlit
182 ghcdeps <- ghcDeps stage
183 return $ [ root -/- ghcSplitPath stage -- TODO: Make conditional on --split-objects
184 , unlitPath ]
185 ++ ghcdeps
186 ++ [ touchyPath | win ]
187
188 Hsc2Hs stage -> (\p -> [p]) <$> templateHscPath stage
189 Make dir -> return [dir -/- "Makefile"]
190 _ -> return []
191
192 -- query the builder for some information.
193 -- contrast this with runBuilderWith, which returns @Action ()@
194 -- this returns the @stdout@ from running the builder.
195 -- For now this only implements asking @ghc-pkg@ about package
196 -- dependencies.
197 askBuilderWith :: Builder -> BuildInfo -> Action String
198 askBuilderWith builder BuildInfo {..} = case builder of
199 GhcPkg Dependencies _ -> do
200 let input = fromSingleton msgIn buildInputs
201 msgIn = "[askBuilder] Exactly one input file expected."
202 needBuilder builder
203 path <- H.builderPath builder
204 need [path]
205 Stdout stdout <- cmd [path] ["--no-user-package-db", "field", input, "depends"]
206 return stdout
207 _ -> error $ "Builder " ++ show builder ++ " can not be asked!"
208
209 runBuilderWith :: Builder -> BuildInfo -> Action ()
210 runBuilderWith builder BuildInfo {..} = do
211 path <- builderPath builder
212 withResources buildResources $ do
213 verbosity <- getVerbosity
214 let input = fromSingleton msgIn buildInputs
215 msgIn = "[runBuilderWith] Exactly one input file expected."
216 output = fromSingleton msgOut buildOutputs
217 msgOut = "[runBuilderWith] Exactly one output file expected."
218 -- Suppress stdout depending on the Shake's verbosity setting.
219 echo = EchoStdout (verbosity >= Loud)
220 -- Capture stdout and write it to the output file.
221 captureStdout = do
222 Stdout stdout <- cmd [path] buildArgs
223 writeFileChanged output stdout
224 case builder of
225 Ar Pack _ -> do
226 useTempFile <- flag ArSupportsAtFile
227 if useTempFile then runAr path buildArgs
228 else runArWithoutTempFile path buildArgs
229
230 Ar Unpack _ -> cmd echo [Cwd output] [path] buildArgs
231
232 Autoreconf dir -> cmd echo [Cwd dir] [path] buildArgs
233 Configure dir -> do
234 -- Inject /bin/bash into `libtool`, instead of /bin/sh,
235 -- otherwise Windows breaks. TODO: Figure out why.
236 bash <- bashPath
237 let env = AddEnv "CONFIG_SHELL" bash
238 cmd echo env [Cwd dir] ["sh", path] buildOptions buildArgs
239
240 HsCpp -> captureStdout
241 GenApply -> captureStdout
242
243 GenPrimopCode -> do
244 stdin <- readFile' input
245 Stdout stdout <- cmd (Stdin stdin) [path] buildArgs
246 writeFileChanged output stdout
247
248 Make dir -> cmd echo path ["-C", dir] buildArgs
249
250 Xelatex -> do
251 unit $ cmd [Cwd output] [path] buildArgs
252 unit $ cmd [Cwd output] [path] buildArgs
253 unit $ cmd [Cwd output] [path] buildArgs
254 unit $ cmd [Cwd output] ["makeindex"] (input -<.> "idx")
255 unit $ cmd [Cwd output] [path] buildArgs
256 unit $ cmd [Cwd output] [path] buildArgs
257
258 GhcPkg Copy _ -> do
259 Stdout pkgDesc <- cmd [path]
260 [ "--expand-pkgroot"
261 , "--no-user-package-db"
262 , "describe"
263 , input -- the package name
264 ]
265 cmd (Stdin pkgDesc) [path] (buildArgs ++ ["-"])
266
267 GhcPkg Unregister _ -> do
268 Exit _ <- cmd echo [path] (buildArgs ++ [input])
269 return ()
270
271 _ -> cmd echo [path] buildArgs
272
273 -- TODO: Some builders are required only on certain platforms. For example,
274 -- 'Objdump' is only required on OpenBSD and AIX. Add support for platform
275 -- specific optional builders as soon as we can reliably test this feature.
276 -- See https://github.com/snowleopard/hadrian/issues/211.
277 isOptional :: Builder -> Bool
278 isOptional = \case
279 Objdump -> True
280 _ -> False
281
282 -- | Determine the location of a system 'Builder'.
283 systemBuilderPath :: Builder -> Action FilePath
284 systemBuilderPath builder = case builder of
285 Alex -> fromKey "alex"
286 Ar _ Stage0 -> fromKey "system-ar"
287 Ar _ _ -> fromKey "ar"
288 Autoreconf _ -> fromKey "autoreconf"
289 Cc _ Stage0 -> fromKey "system-cc"
290 Cc _ _ -> fromKey "cc"
291 -- We can't ask configure for the path to configure!
292 Configure _ -> return "configure"
293 Ghc _ Stage0 -> fromKey "system-ghc"
294 GhcPkg _ Stage0 -> fromKey "system-ghc-pkg"
295 Happy -> fromKey "happy"
296 HsCpp -> fromKey "hs-cpp"
297 Ld _ -> fromKey "ld"
298 Make _ -> fromKey "make"
299 Nm -> fromKey "nm"
300 Objdump -> fromKey "objdump"
301 Patch -> fromKey "patch"
302 Perl -> fromKey "perl"
303 Python -> fromKey "python"
304 Ranlib -> fromKey "ranlib"
305 RunTest -> fromKey "python"
306 Sphinx _ -> fromKey "sphinx-build"
307 Tar _ -> fromKey "tar"
308 Xelatex -> fromKey "xelatex"
309 _ -> error $ "No entry for " ++ show builder ++ inCfg
310 where
311 inCfg = " in " ++ quote configFile ++ " file."
312 fromKey key = do
313 let unpack = fromMaybe . error $ "Cannot find path to builder "
314 ++ quote key ++ inCfg ++ " Did you skip configure?"
315 path <- unpack <$> lookupValue configFile key
316 if null path
317 then do
318 unless (isOptional builder) . error $ "Non optional builder "
319 ++ quote key ++ " is not specified" ++ inCfg
320 return "" -- TODO: Use a safe interface.
321 else do
322 win <- windowsHost
323 fullPath <- lookupInPath path
324 case (win, hasExtension fullPath) of
325 (False, _ ) -> return fullPath
326 (True , True ) -> fixAbsolutePathOnWindows fullPath
327 (True , False) -> fixAbsolutePathOnWindows fullPath <&> (<.> exe)
328
329 -- | Was the path to a given system 'Builder' specified in configuration files?
330 isSpecified :: Builder -> Action Bool
331 isSpecified = fmap (not . null) . systemBuilderPath
332
333 -- | Apply a patch by executing the 'Patch' builder in a given directory.
334 applyPatch :: FilePath -> FilePath -> Action ()
335 applyPatch dir patch = do
336 let file = dir -/- patch
337 needBuilder Patch
338 path <- builderPath Patch
339 putBuild $ "| Apply patch " ++ file
340 quietly $ cmd [Cwd dir, FileStdin file] [path, "-p0"]