Rules.hs 4.63 KB
Newer Older
1
module Rules (buildRules, oracleRules, packageTargets, topLevelTargets) where
Andrey Mokhov's avatar
Andrey Mokhov committed
2 3 4 5 6

import qualified Hadrian.Oracles.ArgsHash
import qualified Hadrian.Oracles.DirectoryContents
import qualified Hadrian.Oracles.KeyValue
import qualified Hadrian.Oracles.Path
7

Andrey Mokhov's avatar
Andrey Mokhov committed
8
import Context
Andrey Mokhov's avatar
Andrey Mokhov committed
9
import Expression
Andrey Mokhov's avatar
Andrey Mokhov committed
10
import Flavour
11
import GHC
Andrey Mokhov's avatar
Andrey Mokhov committed
12
import qualified Oracles.ModuleFiles
13 14 15 16 17 18 19 20 21 22 23 24 25
import qualified Rules.Compile
import qualified Rules.Data
import qualified Rules.Dependencies
import qualified Rules.Documentation
import qualified Rules.Generate
import qualified Rules.Cabal
import qualified Rules.Configure
import qualified Rules.Gmp
import qualified Rules.Libffi
import qualified Rules.Library
import qualified Rules.Perl
import qualified Rules.Program
import qualified Rules.Register
Andrey Mokhov's avatar
Andrey Mokhov committed
26
import Settings
Andrey Mokhov's avatar
Andrey Mokhov committed
27
import Target
28
import Utilities
29

quchen's avatar
quchen committed
30
allStages :: [Stage]
quchen's avatar
quchen committed
31
allStages = [minBound ..]
quchen's avatar
quchen committed
32

Zhen Zhang's avatar
Zhen Zhang committed
33 34
-- | This rule 'need' all top-level build targets
-- or Stage1Only targets
35
topLevelTargets :: Rules ()
Zhen Zhang's avatar
Zhen Zhang committed
36
topLevelTargets = action $ do
37 38 39 40 41 42
    let libraryPackages = filter isLibrary (knownPackages \\ [rts, libffi])
    need =<< if stage1Only
             then do
                 libs <- concatForM [Stage0, Stage1] $ \stage ->
                     concatForM libraryPackages $ packageTargets stage
                 prgs <- concatForM programsStage1Only $ packageTargets Stage0
43 44 45 46 47
                 return $ libs ++ prgs ++ inplaceLibCopyTargets
             else do
                 targets <- concatForM allStages $ \stage ->
                                concatForM (knownPackages \\ [rts, libffi]) $ packageTargets stage
                 return $ targets ++ inplaceLibCopyTargets
48

49 50 51
-- | Return the list of targets associated with a given 'Stage' and 'Package'.
packageTargets :: Stage -> Package -> Action [FilePath]
packageTargets stage pkg = do
Zhen Zhang's avatar
Zhen Zhang committed
52 53
    let context = vanillaContext stage pkg
    activePackages <- interpretInContext context getPackages
54 55 56 57
    if pkg `notElem` activePackages
    then return [] -- Skip inactive packages.
    else if isLibrary pkg
        then do -- Collect all targets of a library package.
58 59 60 61 62 63 64 65
            ways    <- interpretInContext context getLibraryWays
            libs    <- mapM (pkgLibraryFile . Context stage pkg) ways
            docs    <- interpretInContext context =<< buildHaddock <$> flavour
            more    <- libraryTargets context
            setup   <- pkgSetupConfigFile context
            haddock <- pkgHaddockFile     context
            return $ [ setup   | nonCabalContext context ]
                  ++ [ haddock | docs && stage == Stage1 ]
66 67
                  ++ libs ++ more
        else -- The only target of a program package is the executable.
68
            fmap maybeToList . programPath =<< programContext stage pkg
quchen's avatar
quchen committed
69

70
packageRules :: Rules ()
71
packageRules = do
72 73
    -- We cannot register multiple GHC packages in parallel. Also we cannot run
    -- GHC when the package database is being mutated by "ghc-pkg". This is a
74 75 76 77 78 79
    -- classic concurrent read exclusive write (CREW) conflict.
    let maxConcurrentReaders = 1000
    packageDb <- newResource "package-db" maxConcurrentReaders
    let readPackageDb  = [(packageDb, 1)]
        writePackageDb = [(packageDb, maxConcurrentReaders)]

Andrey Mokhov's avatar
Andrey Mokhov committed
80 81
    let contexts        = liftM3 Context        allStages knownPackages allWays
        vanillaContexts = liftM2 vanillaContext allStages knownPackages
82

Andrey Mokhov's avatar
Andrey Mokhov committed
83
    forM_ contexts $ mconcat
84 85
        [ Rules.Compile.compilePackage readPackageDb
        , Rules.Library.buildPackageLibrary ]
86

Zhen Zhang's avatar
Zhen Zhang committed
87 88 89
    let dynamicContexts = liftM3 Context [Stage1 ..] knownPackages [dynamic]
    forM_ dynamicContexts Rules.Library.buildDynamicLib

Andrey Mokhov's avatar
Andrey Mokhov committed
90
    forM_ vanillaContexts $ mconcat
91 92 93 94 95
        [ Rules.Data.buildPackageData
        , Rules.Dependencies.buildPackageDependencies readPackageDb
        , Rules.Documentation.buildPackageDocumentation
        , Rules.Library.buildPackageGhciLibrary
        , Rules.Generate.generatePackageCode
96
        , Rules.Program.buildProgram readPackageDb
97
        , Rules.Register.registerPackage writePackageDb ]
98 99

buildRules :: Rules ()
100
buildRules = do
101 102 103 104 105 106
    Rules.Cabal.cabalRules
    Rules.Configure.configureRules
    Rules.Generate.copyRules
    Rules.Generate.generateRules
    Rules.Gmp.gmpRules
    Rules.Libffi.libffiRules
Andrey Mokhov's avatar
Andrey Mokhov committed
107
    packageRules
108
    Rules.Perl.perlScriptRules
Zhen Zhang's avatar
Zhen Zhang committed
109

Andrey Mokhov's avatar
Andrey Mokhov committed
110 111 112 113 114 115 116 117
oracleRules :: Rules ()
oracleRules = do
    Hadrian.Oracles.ArgsHash.argsHashOracle trackArgument getArgs
    Hadrian.Oracles.DirectoryContents.directoryContentsOracle
    Hadrian.Oracles.KeyValue.keyValueOracle
    Hadrian.Oracles.Path.pathOracle
    Oracles.ModuleFiles.moduleFilesOracle

Zhen Zhang's avatar
Zhen Zhang committed
118 119
programsStage1Only :: [Package]
programsStage1Only =
Andrey Mokhov's avatar
Andrey Mokhov committed
120 121 122
    [ deriveConstants, genprimopcode, hp2ps, runGhc
    , ghcCabal, hpc, dllSplit, ghcPkg, hsc2hs
    , genapply, ghc ]