Drop dll-split
[hadrian.git] / src / GHC.hs
1 {-# OPTIONS_GHC -fno-warn-missing-signatures #-}
2 module GHC (
3 -- * GHC packages
4 array, base, binary, bytestring, cabal, checkApiAnnotations, compareSizes,
5 compiler, containers, deepseq, deriveConstants, directory, filepath,
6 genapply, genprimopcode, ghc, ghcBoot, ghcBootTh, ghcCabal, ghcCompact, ghci,
7 ghcPkg, ghcPrim, ghcTags, ghcSplit, haddock, haskeline, hsc2hs, hp2ps,
8 hpc, hpcBin, integerGmp, integerSimple, iservBin, libffi, mtl, parsec,
9 parallel, pretty, primitive, process, rts, runGhc, stm, templateHaskell,
10 terminfo, text, time, touchy, transformers, unlit, unix, win32, xhtml,
11 ghcPackages, isGhcPackage, defaultPackages,
12
13 -- * Package information
14 programName, nonCabalContext, nonHsMainPackage, autogenPath, installStage,
15
16 -- * Miscellaneous
17 programPath, ghcSplitPath, stripCmdPath, buildDll0
18 ) where
19
20 import Base
21 import CommandLine
22 import Context
23 import Oracles.Setting
24
25 -- | These are all GHC packages we know about. Build rules will be generated for
26 -- all of them. However, not all of these packages will be built. For example,
27 -- package 'win32' is built only on Windows. 'defaultPackages' defines default
28 -- conditions for building each package. Users can add their own packages and
29 -- modify build default build conditions in "UserSettings".
30 ghcPackages :: [Package]
31 ghcPackages =
32 [ array, base, binary, bytestring, cabal, checkApiAnnotations, compareSizes
33 , compiler, containers, deepseq, deriveConstants, directory, filepath
34 , genapply, genprimopcode, ghc, ghcBoot, ghcBootTh, ghcCabal, ghcCompact
35 , ghci, ghcPkg, ghcPrim, ghcTags, haddock, haskeline, hsc2hs, hp2ps, hpc
36 , hpcBin, integerGmp, integerSimple, iservBin, libffi, mtl, parsec, parallel
37 , pretty, primitive, process, rts, runGhc, stm, templateHaskell, terminfo
38 , text, time, touchy, transformers, unlit, unix, win32, xhtml ]
39
40 -- TODO: Optimise by switching to sets of packages.
41 isGhcPackage :: Package -> Bool
42 isGhcPackage = (`elem` ghcPackages)
43
44 -- | Package definitions, see 'Package'.
45 array = hsLib "array"
46 base = hsLib "base"
47 binary = hsLib "binary"
48 bytestring = hsLib "bytestring"
49 cabal = hsLib "Cabal" `setPath` "libraries/Cabal/Cabal"
50 checkApiAnnotations = hsUtil "check-api-annotations"
51 compareSizes = hsUtil "compareSizes" `setPath` "utils/compare_sizes"
52 compiler = hsTop "ghc" `setPath` "compiler"
53 containers = hsLib "containers"
54 deepseq = hsLib "deepseq"
55 deriveConstants = hsUtil "deriveConstants"
56 directory = hsLib "directory"
57 filepath = hsLib "filepath"
58 genapply = hsUtil "genapply"
59 genprimopcode = hsUtil "genprimopcode"
60 ghc = hsPrg "ghc-bin" `setPath` "ghc"
61 ghcBoot = hsLib "ghc-boot"
62 ghcBootTh = hsLib "ghc-boot-th"
63 ghcCabal = hsUtil "ghc-cabal"
64 ghcCompact = hsLib "ghc-compact"
65 ghci = hsLib "ghci"
66 ghcPkg = hsUtil "ghc-pkg"
67 ghcPrim = hsLib "ghc-prim"
68 ghcTags = hsUtil "ghctags"
69 ghcSplit = hsUtil "ghc-split"
70 haddock = hsUtil "haddock"
71 haskeline = hsLib "haskeline"
72 hsc2hs = hsUtil "hsc2hs"
73 hp2ps = cUtil "hp2ps"
74 hpc = hsLib "hpc"
75 hpcBin = hsUtil "hpc-bin" `setPath` "utils/hpc"
76 integerGmp = hsLib "integer-gmp"
77 integerSimple = hsLib "integer-simple"
78 iservBin = hsPrg "iserv-bin" `setPath` "iserv"
79 libffi = cTop "libffi"
80 mtl = hsLib "mtl"
81 parsec = hsLib "parsec"
82 parallel = hsLib "parallel"
83 pretty = hsLib "pretty"
84 primitive = hsLib "primitive"
85 process = hsLib "process"
86 rts = cTop "rts"
87 runGhc = hsUtil "runghc"
88 stm = hsLib "stm"
89 templateHaskell = hsLib "template-haskell"
90 terminfo = hsLib "terminfo"
91 text = hsLib "text"
92 time = hsLib "time"
93 touchy = cUtil "touchy"
94 transformers = hsLib "transformers"
95 unlit = cUtil "unlit"
96 unix = hsLib "unix"
97 win32 = hsLib "Win32"
98 xhtml = hsLib "xhtml"
99
100 -- | Construct a Haskell library package, e.g. @array@.
101 hsLib :: PackageName -> Package
102 hsLib name = hsLibrary name ("libraries" -/- name)
103
104 -- | Construct a top-level Haskell library package, e.g. @compiler@.
105 hsTop :: PackageName -> Package
106 hsTop name = hsLibrary name name
107
108 -- | Construct a top-level C library package, e.g. @rts@.
109 cTop :: PackageName -> Package
110 cTop name = cLibrary name name
111
112 -- | Construct a top-level Haskell program package, e.g. @ghc@.
113 hsPrg :: PackageName -> Package
114 hsPrg name = hsProgram name name
115
116 -- | Construct a Haskell utility package, e.g. @haddock@.
117 hsUtil :: PackageName -> Package
118 hsUtil name = hsProgram name ("utils" -/- name)
119
120 -- | Construct a C utility package, e.g. @haddock@.
121 cUtil :: PackageName -> Package
122 cUtil name = cProgram name ("utils" -/- name)
123
124 -- | Amend a package path if it doesn't conform to a typical pattern.
125 setPath :: Package -> FilePath -> Package
126 setPath pkg path = pkg { pkgPath = path }
127
128 -- | Packages that are built by default. You can change this in "UserSettings".
129 defaultPackages :: Stage -> Action [Package]
130 defaultPackages Stage0 = stage0Packages
131 defaultPackages Stage1 = stage1Packages
132 defaultPackages Stage2 = stage2Packages
133 defaultPackages Stage3 = return []
134
135 stage0Packages :: Action [Package]
136 stage0Packages = do
137 win <- windowsHost
138 ios <- iosHost
139 return $ [ binary
140 , cabal
141 , checkApiAnnotations
142 , compareSizes
143 , compiler
144 , deriveConstants
145 , genapply
146 , genprimopcode
147 , ghc
148 , ghcBoot
149 , ghcBootTh
150 , ghcCabal
151 , ghci
152 , ghcPkg
153 , ghcTags
154 , hsc2hs
155 , hp2ps
156 , hpc
157 , mtl
158 , parsec
159 , templateHaskell
160 , text
161 , transformers
162 , unlit ]
163 ++ [ terminfo | not win, not ios ]
164 ++ [ touchy | win ]
165
166 stage1Packages :: Action [Package]
167 stage1Packages = do
168 win <- windowsHost
169 doc <- cmdBuildHaddock
170 intSimple <- cmdIntegerSimple
171 libraries0 <- filter isLibrary <$> stage0Packages
172 return $ libraries0 -- Build all Stage0 libraries in Stage1
173 ++ [ array
174 , base
175 , bytestring
176 , containers
177 , deepseq
178 , directory
179 , filepath
180 , ghc
181 , ghcCabal
182 , ghcCompact
183 , ghcPrim
184 , haskeline
185 , hpcBin
186 , hsc2hs
187 , if intSimple then integerSimple else integerGmp
188 , pretty
189 , process
190 , rts
191 , runGhc
192 , time ]
193 ++ [ iservBin | not win ]
194 ++ [ unix | not win ]
195 ++ [ win32 | win ]
196 ++ [ xhtml | doc ]
197
198 stage2Packages :: Action [Package]
199 stage2Packages = do
200 doc <- cmdBuildHaddock
201 return [ haddock | doc ]
202
203 -- | Given a 'Context', compute the name of the program that is built in it
204 -- assuming that the corresponding package's type is 'Program'. For example, GHC
205 -- built in 'Stage0' is called @ghc-stage1@. If the given package is a
206 -- 'Library', the function simply returns its name.
207 programName :: Context -> String
208 programName Context {..}
209 | package == ghc = "ghc-stage" ++ show (fromEnum stage + 1)
210 | package == hpcBin = "hpc"
211 | package == runGhc = "runhaskell"
212 | package == iservBin = "ghc-iserv"
213 | otherwise = pkgName package
214
215 -- | The build stage whose results are used when installing a package, or
216 -- @Nothing@ if the package is not installed, e.g. because it is a user package.
217 -- The current implementation installs the /latest/ build stage of a package.
218 installStage :: Package -> Action (Maybe Stage)
219 installStage pkg
220 | not (isGhcPackage pkg) = return Nothing -- Only GHC packages are installed
221 | otherwise = do
222 stages <- filterM (fmap (pkg `elem`) . defaultPackages) [Stage0 ..]
223 return $ if null stages then Nothing else Just (maximum stages)
224
225 -- | Is the program corresponding to a given context built 'inplace', i.e. in
226 -- the @inplace/bin@ directory? For most programs, only their /latest/ build
227 -- stages are built 'inplace'. The only exception is the GHC itself, which is
228 -- built 'inplace' in all stages. The function returns @False@ for libraries and
229 -- all user packages.
230 isBuiltInplace :: Context -> Action Bool
231 isBuiltInplace Context {..}
232 | isLibrary package = return False
233 | not (isGhcPackage package) = return False
234 | package == ghc = return True
235 | otherwise = (Just stage ==) <$> installStage package
236
237 -- | The 'FilePath' to a program executable in a given 'Context'.
238 programPath :: Context -> Action FilePath
239 programPath context@Context {..} = do
240 path <- buildPath context
241 inplace <- isBuiltInplace context
242 let contextPath = if inplace then inplacePath else path
243 return $ contextPath -/- programName context <.> exe
244 where
245 inplacePath | package `elem` [touchy, unlit, iservBin] = inplaceLibBinPath
246 | otherwise = inplaceBinPath
247
248 -- | Some contexts are special: their packages do not have @.cabal@ metadata or
249 -- we cannot run @ghc-cabal@ on them, e.g. because the latter hasn't been built
250 -- yet (this is the case with the 'ghcCabal' package in 'Stage0').
251 nonCabalContext :: Context -> Bool
252 nonCabalContext Context {..} = (package `elem` [hp2ps, rts, touchy, unlit])
253 || package == ghcCabal && stage == Stage0
254
255 -- | Some program packages should not be linked with Haskell main function.
256 nonHsMainPackage :: Package -> Bool
257 nonHsMainPackage = (`elem` [ghc, hp2ps, iservBin, touchy, unlit])
258
259 -- | Path to the autogen directory generated by @ghc-cabal@ of a given 'Context'.
260 autogenPath :: Context -> Action FilePath
261 autogenPath context@Context {..}
262 | isLibrary package = autogen "build"
263 | package == ghc = autogen "build/ghc"
264 | package == hpcBin = autogen "build/hpc"
265 | package == iservBin = autogen "build/iserv"
266 | otherwise = autogen $ "build" -/- pkgName package
267 where
268 autogen dir = buildPath context <&> (-/- dir -/- "autogen")
269
270 -- | @ghc-split@ is a Perl script used by GHC with @-split-objs@ flag. It is
271 -- generated in "Rules.Generators.GhcSplit".
272 ghcSplitPath :: FilePath
273 ghcSplitPath = inplaceLibBinPath -/- "ghc-split"
274
275 -- ref: mk/config.mk
276 -- | Command line tool for stripping.
277 stripCmdPath :: Action FilePath
278 stripCmdPath = do
279 targetPlatform <- setting TargetPlatform
280 top <- topDirectory
281 case targetPlatform of
282 "x86_64-unknown-mingw32" ->
283 return (top -/- "inplace/mingw/bin/strip.exe")
284 "arm-unknown-linux" ->
285 return ":" -- HACK: from the make-based system, see the ref above
286 _ -> return "strip"
287
288 buildDll0 :: Context -> Action Bool
289 buildDll0 Context {..} = do
290 windows <- windowsHost
291 return $ windows && stage == Stage1 && package == compiler