Encode shape information in `PmOracle`
[ghc.git] / hadrian / src / Rules.hs
1 module Rules (buildRules, oracleRules, packageTargets, topLevelTargets
2 , toolArgsTarget ) where
3
4 import qualified Hadrian.Oracles.ArgsHash
5 import qualified Hadrian.Oracles.Cabal.Rules
6 import qualified Hadrian.Oracles.DirectoryContents
7 import qualified Hadrian.Oracles.Path
8 import qualified Hadrian.Oracles.TextFile
9
10 import Expression
11 import qualified Oracles.ModuleFiles
12 import Packages
13 import qualified Rules.BinaryDist
14 import qualified Rules.Compile
15 import qualified Rules.Configure
16 import qualified Rules.Dependencies
17 import qualified Rules.Documentation
18 import qualified Rules.Generate
19 import qualified Rules.Gmp
20 import qualified Rules.Libffi
21 import qualified Rules.Library
22 import qualified Rules.Program
23 import qualified Rules.Register
24 import qualified Rules.Rts
25 import qualified Rules.SimpleTargets
26 import Settings
27 import Target
28 import UserSettings
29
30
31 -- | @tool-args@ is used by tooling in order to get the arguments necessary
32 -- to set up a GHC API session which can compile modules from GHC. When
33 -- run, the target prints out the arguments that would be passed to @ghc@
34 -- during normal compilation to @stdout@.
35 --
36 -- This target is called by the `ghci.sh` script in order to load all of GHC's
37 -- modules into GHCi.
38 toolArgsTarget :: Rules ()
39 toolArgsTarget = do
40 "tool-args" ~> do
41 -- We can't build DLLs on Windows (yet). Actually we should only
42 -- include the dynamic way when we have a dynamic host GHC, but just
43 -- checking for Windows seems simpler for now.
44 let fake_target = target (Context Stage0 compiler (if windowsHost then vanilla else dynamic))
45 (Ghc ToolArgs Stage0) [] ["ignored"]
46
47 -- need the autogenerated files so that they are precompiled
48 generatedGhcDependencies Stage0 >>= need
49 interpret fake_target Rules.Generate.compilerDependencies >>= need
50
51 root <- buildRoot
52 let dir = buildDir (vanillaContext Stage0 compiler)
53 need [ root -/- dir -/- "Config.hs" ]
54 need [ root -/- dir -/- "Parser.hs" ]
55 need [ root -/- dir -/- "Lexer.hs" ]
56 need [ root -/- dir -/- "CmmParse.hs" ]
57 need [ root -/- dir -/- "CmmLex.hs" ]
58
59 -- Find out the arguments that are needed to load a module into the
60 -- session
61 arg_list <- interpret fake_target getArgs
62 liftIO $ putStrLn (intercalate " " arg_list)
63
64 allStages :: [Stage]
65 allStages = [minBound .. maxBound]
66
67 -- | This rule calls 'need' on all top-level build targets that Hadrian builds
68 -- by default, respecting the 'finalStage' flag.
69 topLevelTargets :: Rules ()
70 topLevelTargets = action $ do
71 verbosity <- getVerbosity
72 forM_ [ Stage1 ..] $ \stage -> do
73 when (verbosity >= Loud) $ do
74 (libraries, programs) <- partition isLibrary <$> stagePackages stage
75 libNames <- mapM (name stage) libraries
76 pgmNames <- mapM (name stage) programs
77 let stageHeader t ps =
78 "| Building " ++ show stage ++ " "
79 ++ t ++ ": " ++ intercalate ", " ps
80 putNormal . unlines $
81 [ stageHeader "libraries" libNames
82 , stageHeader "programs" pgmNames ]
83 let buildStages = [ s | s <- [Stage0 ..], s < finalStage ]
84 targets <- concatForM buildStages $ \stage -> do
85 packages <- stagePackages stage
86 mapM (path stage) packages
87
88 -- Why we need wrappers: https://gitlab.haskell.org/ghc/ghc/issues/16534.
89 root <- buildRoot
90 let wrappers = [ root -/- ("ghc-" ++ stageString s) | s <- [Stage1 ..]
91 , s < finalStage ]
92 need (targets ++ wrappers)
93 where
94 -- either the package database config file for libraries or
95 -- the programPath for programs. However this still does
96 -- not support multiple targets, where a cabal package has
97 -- a library /and/ a program.
98 path :: Stage -> Package -> Action FilePath
99 path stage pkg | isLibrary pkg = pkgConfFile (vanillaContext stage pkg)
100 | otherwise = programPath =<< programContext stage pkg
101 name :: Stage -> Package -> Action String
102 name stage pkg | isLibrary pkg = return (pkgName pkg)
103 | otherwise = programName (vanillaContext stage pkg)
104
105 -- TODO: Get rid of the @includeGhciLib@ hack.
106 -- | Return the list of targets associated with a given 'Stage' and 'Package'.
107 -- By setting the Boolean parameter to False it is possible to exclude the GHCi
108 -- library from the targets, and avoid configuring the package to determine
109 -- whether GHCi library needs to be built for it. We typically want to set
110 -- this parameter to True, however it is important to set it to False when
111 -- computing 'topLevelTargets', as otherwise the whole build gets sequentialised
112 -- because packages are configured in the order respecting their dependencies.
113 packageTargets :: Bool -> Stage -> Package -> Action [FilePath]
114 packageTargets includeGhciLib stage pkg = do
115 let context = vanillaContext stage pkg
116 activePackages <- stagePackages stage
117 if pkg `notElem` activePackages
118 then return [] -- Skip inactive packages.
119 else if isLibrary pkg
120 then do -- Collect all targets of a library package.
121 let pkgWays = if pkg == rts then getRtsWays else getLibraryWays
122 ways <- interpretInContext context pkgWays
123 libs <- mapM (pkgLibraryFile . Context stage pkg) ways
124 more <- Rules.Library.libraryTargets includeGhciLib context
125 setupConfig <- pkgSetupConfigFile context
126 return $ [setupConfig] ++ libs ++ more
127 else do -- The only target of a program package is the executable.
128 prgContext <- programContext stage pkg
129 prgPath <- programPath prgContext
130 return [prgPath]
131
132 packageRules :: Rules ()
133 packageRules = do
134 -- We cannot register multiple GHC packages in parallel. Also we cannot run
135 -- GHC when the package database is being mutated by "ghc-pkg". This is a
136 -- classic concurrent read exclusive write (CREW) conflict.
137 let maxConcurrentReaders = 1000
138 packageDb <- newResource "package-db" maxConcurrentReaders
139 let readPackageDb = [(packageDb, 1)]
140 writePackageDb = [(packageDb, maxConcurrentReaders)]
141
142 Rules.Compile.compilePackage readPackageDb
143 Rules.Dependencies.buildPackageDependencies readPackageDb
144 Rules.Documentation.buildPackageDocumentation
145 Rules.Program.buildProgramRules readPackageDb
146 Rules.Register.configurePackageRules
147
148 forM_ [Stage0 ..] (Rules.Register.registerPackageRules writePackageDb)
149
150 -- TODO: Can we get rid of this enumeration of contexts? Since we iterate
151 -- over it to generate all 4 types of rules below, all the time, we
152 -- might want to see whether the parse-and-extract approach of
153 -- Rules.Compile and Rules.Library could save us some time there.
154 let vanillaContexts = liftM2 vanillaContext allStages knownPackages
155
156 forM_ vanillaContexts Rules.Generate.generatePackageCode
157 Rules.SimpleTargets.simplePackageTargets
158 Rules.SimpleTargets.completionRule
159
160 buildRules :: Rules ()
161 buildRules = do
162 Rules.BinaryDist.bindistRules
163 Rules.Configure.configureRules
164 Rules.Generate.copyRules
165 Rules.Generate.generateRules
166 Rules.Gmp.gmpRules
167 Rules.Libffi.libffiRules
168 Rules.Library.libraryRules
169 Rules.Rts.rtsRules
170 packageRules
171
172 oracleRules :: Rules ()
173 oracleRules = do
174 Hadrian.Oracles.ArgsHash.argsHashOracle trackArgument getArgs
175 Hadrian.Oracles.Cabal.Rules.cabalOracle
176 Hadrian.Oracles.DirectoryContents.directoryContentsOracle
177 Hadrian.Oracles.Path.pathOracle
178 Hadrian.Oracles.TextFile.textFileOracle
179 Oracles.ModuleFiles.moduleFilesOracle