de4f8c0c4564eda82d7e425ad4865b543d0794d9
[hadrian.git] / src / Rules / Data.hs
1 module Rules.Data (buildPackageData) where
2
3 import Base
4 import Expression
5 import GHC
6 import Oracles
7 import Predicates (registerPackage)
8 import Rules.Actions
9 import Rules.Generate
10 import Rules.Resources
11 import Settings
12 import Settings.Builders.Common
13 import Settings.Packages.Rts
14
15 -- Build package-data.mk by using GhcCabal to process pkgCabal file
16 buildPackageData :: Resources -> PartialTarget -> Rules ()
17 buildPackageData rs target @ (PartialTarget stage pkg) = do
18 let cabalFile = pkgCabalFile pkg
19 configure = pkgPath pkg -/- "configure"
20 dataFile = pkgDataFile stage pkg
21
22 dataFile %> \mk -> do
23 -- The first thing we do with any package is make sure all generated
24 -- dependencies are in place before proceeding.
25 orderOnly $ generatedDependencies stage pkg
26
27 -- GhcCabal may run the configure script, so we depend on it
28 -- We don't know who built the configure script from configure.ac
29 whenM (doesFileExist $ configure <.> "ac") $ need [configure]
30
31 -- We configure packages in the order of their dependencies
32 deps <- packageDeps pkg
33 pkgs <- interpretPartial target getPackages
34 let depPkgs = matchPackageNames (sort pkgs) deps
35 orderOnly $ map (pkgDataFile stage) depPkgs
36
37 need [cabalFile]
38 buildWithResources [(resGhcCabal rs, 1)] $
39 fullTarget target GhcCabal [cabalFile] [mk]
40
41 -- ghc-pkg produces inplace-pkg-config when run on packages with
42 -- library components only
43 when (isLibrary pkg) .
44 whenM (interpretPartial target registerPackage) .
45 buildWithResources [(resGhcPkg rs, 1)] $
46 fullTarget target (GhcPkg stage) [cabalFile] []
47
48 postProcessPackageData dataFile
49
50 -- TODO: PROGNAME was $(CrossCompilePrefix)hp2ps
51 priority 2.0 $ do
52 when (pkg == hp2ps) $ dataFile %> \mk -> do
53 includes <- interpretPartial target $ fromDiffExpr includesArgs
54 let prefix = "utils_hp2ps_" ++ stageString stage ++ "_"
55 cSrcs = [ "AreaBelow.c", "Curves.c", "Error.c", "Main.c"
56 , "Reorder.c", "TopTwenty.c", "AuxFile.c"
57 , "Deviation.c", "HpFile.c", "Marks.c", "Scale.c"
58 , "TraceElement.c", "Axes.c", "Dimensions.c", "Key.c"
59 , "PsFile.c", "Shade.c", "Utilities.c" ]
60 contents = unlines $ map (prefix++)
61 [ "PROGNAME = hp2ps"
62 , "C_SRCS = " ++ unwords cSrcs
63 , "INSTALL = YES"
64 , "INSTALL_INPLACE = YES"
65 , "DEP_EXTRA_LIBS = m"
66 , "CC_OPTS = " ++ unwords includes ]
67 writeFileChanged mk contents
68 putSuccess $ "| Successfully generated '" ++ mk ++ "'."
69
70 when (pkg == touchy) $ dataFile %> \mk -> do
71 let prefix = "utils_touchy_" ++ stageString stage ++ "_"
72 contents = unlines $ map (prefix++)
73 [ "PROGNAME = touchy"
74 , "C_SRCS = touchy.c" ]
75 writeFileChanged mk contents
76 putSuccess $ "| Successfully generated '" ++ mk ++ "'."
77
78 -- Bootstrapping `ghcCabal`: although `ghcCabal` is a proper cabal
79 -- package, we cannot generate the corresponding `package-data.mk` file
80 -- by running by running `ghcCabal`, because it has not yet been built.
81 when (pkg == ghcCabal && stage == Stage0) $ dataFile %> \mk -> do
82 let contents = unlines
83 [ "utils_ghc-cabal_stage0_PROGNAME = ghc-cabal"
84 , "utils_ghc-cabal_stage0_MODULES = Main"
85 , "utils_ghc-cabal_stage0_SYNOPSIS = Bootstrapped ghc-cabal utility."
86 , "utils_ghc-cabal_stage0_HS_SRC_DIRS = ." ]
87 writeFileChanged mk contents
88 putSuccess $ "| Successfully generated '" ++ mk ++ "'."
89
90 when (pkg == rts && stage == Stage1) $ do
91 dataFile %> \mk -> do
92 windows <- windowsHost
93 let prefix = "rts_" ++ stageString stage ++ "_"
94 dirs = [ ".", "hooks", "sm", "eventlog" ]
95 ++ [ "posix" | not windows ]
96 ++ [ "win32" | windows ]
97 -- TODO: rts/dist/build/sm/Evac_thr.c, rts/dist/build/sm/Scav_thr.c
98 -- TODO: adding cmm/S sources to C_SRCS is a hack; rethink after #18
99 cSrcs <- getDirectoryFiles (pkgPath pkg) (map (-/- "*.c") dirs)
100 cmmSrcs <- getDirectoryFiles (pkgPath pkg) ["*.cmm"]
101 buildAdjustor <- anyTargetArch ["i386", "powerpc", "powerpc64"]
102 buildStgCRunAsm <- anyTargetArch ["powerpc64le"]
103 let sSrcs = [ "AdjustorAsm.S" | buildAdjustor ]
104 ++ [ "StgCRunAsm.S" | buildStgCRunAsm ]
105 extraSrcs = [ targetDirectory Stage1 rts -/- "build/AutoApply.cmm" ]
106 includes <- interpretPartial target $ fromDiffExpr includesArgs
107 let contents = unlines $ map (prefix++)
108 [ "C_SRCS = "
109 ++ unwords (cSrcs ++ cmmSrcs ++ sSrcs ++ extraSrcs)
110 , "CC_OPTS = " ++ unwords includes
111 , "COMPONENT_ID = " ++ "rts" ]
112 writeFileChanged mk contents
113 putSuccess $ "| Successfully generated '" ++ mk ++ "'."
114
115 need [rtsConf]
116 buildWithResources [(resGhcPkg rs, 1)] $
117 fullTarget target (GhcPkg stage) [rtsConf] []
118
119 rtsConf %> \_ -> do
120 orderOnly $ generatedDependencies stage pkg
121 need [ rtsConfIn ]
122 build $ fullTarget target HsCpp [rtsConfIn] [rtsConf]
123
124 let fixRtsConf = unlines
125 . map
126 ( replace "\"\"" ""
127 . replace "rts/dist/build" "rts/stage1/build" )
128 . filter (not . null)
129 . lines
130
131 fixFile rtsConf fixRtsConf
132
133 -- Prepare a given 'packaga-data.mk' file for parsing by readConfigFile:
134 -- 1) Drop lines containing '$'
135 -- For example, get rid of
136 -- libraries/Win32_dist-install_CMM_SRCS := $(addprefix cbits/,$(notdir ...
137 -- Reason: we don't need them and we can't parse them.
138 -- 2) Replace '/' and '\' with '_' before '='
139 -- For example libraries/deepseq/dist-install_VERSION = 1.4.0.0
140 -- is replaced by libraries_deepseq_dist-install_VERSION = 1.4.0.0
141 -- Reason: Shake's built-in makefile parser doesn't recognise slashes
142 postProcessPackageData :: FilePath -> Action ()
143 postProcessPackageData file = fixFile file fixPackageData
144 where
145 fixPackageData = unlines . map processLine . filter ('$' `notElem`) . lines
146 processLine line = replaceSeparators '_' prefix ++ suffix
147 where
148 (prefix, suffix) = break (== '=') line