09610d79d1e34e92762c7e8064c9a81f8904705a
[hadrian.git] / src / Rules.hs
1 module Rules (buildRules, oracleRules, packageTargets, topLevelTargets) where
2
3 import qualified Hadrian.Oracles.ArgsHash
4 import qualified Hadrian.Oracles.DirectoryContents
5 import qualified Hadrian.Oracles.Path
6 import qualified Hadrian.Oracles.TextFile
7
8 import Expression
9 import Flavour
10 import qualified Oracles.ModuleFiles
11 import qualified Rules.Compile
12 import qualified Rules.Data
13 import qualified Rules.Dependencies
14 import qualified Rules.Documentation
15 import qualified Rules.Generate
16 import qualified Rules.Configure
17 import qualified Rules.Gmp
18 import qualified Rules.Libffi
19 import qualified Rules.Library
20 import qualified Rules.Perl
21 import qualified Rules.Program
22 import qualified Rules.Register
23 import Settings
24 import UserSettings (stage1Only)
25 import Target
26 import Utilities
27
28 allStages :: [Stage]
29 allStages = [minBound ..]
30
31 -- | This rule calls 'need' on all top-level build targets, respecting the
32 -- 'Stage1Only' flag.
33 topLevelTargets :: Rules ()
34 topLevelTargets = action $ do
35 let libraryPackages = filter isLibrary (knownPackages \\ [rts, libffi])
36 need =<< if stage1Only
37 then do
38 libs <- concatForM [Stage0, Stage1] $ \stage ->
39 concatForM libraryPackages $ packageTargets False stage
40 prgs <- concatForM programsStage1Only $ packageTargets False Stage0
41 return $ libs ++ prgs ++ inplaceLibCopyTargets
42 else do
43 targets <- concatForM allStages $ \stage ->
44 concatForM (knownPackages \\ [rts, libffi]) $
45 packageTargets False stage
46 return $ targets ++ inplaceLibCopyTargets
47
48
49 -- TODO: Get rid of the @includeGhciLib@ hack.
50 -- | Return the list of targets associated with a given 'Stage' and 'Package'.
51 -- By setting the Boolean parameter to False it is possible to exclude the GHCi
52 -- library from the targets, and avoid running @ghc-cabal@ to determine wether
53 -- GHCi library needs to be built for this package. We typically want to set
54 -- this parameter to True, however it is important to set it to False when
55 -- computing 'topLevelTargets', as otherwise the whole build gets sequentialised
56 -- because we need to run @ghc-cabal@ in the order respecting package dependencies.
57 packageTargets :: Bool -> Stage -> Package -> Action [FilePath]
58 packageTargets includeGhciLib stage pkg = do
59 let context = vanillaContext stage pkg
60 activePackages <- stagePackages stage
61 if pkg `notElem` activePackages
62 then return [] -- Skip inactive packages.
63 else if isLibrary pkg
64 then do -- Collect all targets of a library package.
65 ways <- interpretInContext context getLibraryWays
66 libs <- mapM (pkgLibraryFile . Context stage pkg) ways
67 docs <- interpretInContext context =<< buildHaddock <$> flavour
68 more <- libraryTargets includeGhciLib context
69 setup <- pkgSetupConfigFile context
70 haddock <- pkgHaddockFile context
71 return $ [ setup | nonCabalContext context ]
72 ++ [ haddock | docs && stage == Stage1 ]
73 ++ libs ++ more
74 else do -- The only target of a program package is the executable.
75 prgContext <- programContext stage pkg
76 prgPath <- programPath prgContext
77 return [prgPath]
78
79 packageRules :: Rules ()
80 packageRules = do
81 -- We cannot register multiple GHC packages in parallel. Also we cannot run
82 -- GHC when the package database is being mutated by "ghc-pkg". This is a
83 -- classic concurrent read exclusive write (CREW) conflict.
84 let maxConcurrentReaders = 1000
85 packageDb <- newResource "package-db" maxConcurrentReaders
86 let readPackageDb = [(packageDb, 1)]
87 writePackageDb = [(packageDb, maxConcurrentReaders)]
88
89 let contexts = liftM3 Context allStages knownPackages allWays
90 vanillaContexts = liftM2 vanillaContext allStages knownPackages
91
92 forM_ contexts $ mconcat
93 [ Rules.Compile.compilePackage readPackageDb
94 , Rules.Library.buildPackageLibrary ]
95
96 let dynamicContexts = liftM3 Context [Stage1 ..] knownPackages [dynamic]
97 forM_ dynamicContexts Rules.Library.buildDynamicLib
98
99 forM_ (filter isProgram knownPackages) $
100 Rules.Program.buildProgram readPackageDb
101
102 forM_ vanillaContexts $ mconcat
103 [ Rules.Data.buildPackageData
104 , Rules.Dependencies.buildPackageDependencies readPackageDb
105 , Rules.Documentation.buildPackageDocumentation
106 , Rules.Library.buildPackageGhciLibrary
107 , Rules.Generate.generatePackageCode
108 , Rules.Register.registerPackage writePackageDb ]
109
110 buildRules :: Rules ()
111 buildRules = do
112 Rules.Configure.configureRules
113 Rules.Generate.copyRules
114 Rules.Generate.generateRules
115 Rules.Gmp.gmpRules
116 Rules.Libffi.libffiRules
117 packageRules
118 Rules.Perl.perlScriptRules
119
120 oracleRules :: Rules ()
121 oracleRules = do
122 Hadrian.Oracles.ArgsHash.argsHashOracle trackArgument getArgs
123 Hadrian.Oracles.DirectoryContents.directoryContentsOracle
124 Hadrian.Oracles.Path.pathOracle
125 Hadrian.Oracles.TextFile.textFileOracle
126 Oracles.ModuleFiles.moduleFilesOracle
127
128 programsStage1Only :: [Package]
129 programsStage1Only = [ deriveConstants, dllSplit, genapply, genprimopcode, ghc
130 , ghcCabal, ghcPkg, hp2ps, hpc, hsc2hs, runGhc ]