Make PackageName into a proper newtype
[hadrian.git] / src / Rules / Library.hs
1 module Rules.Library (buildPackageLibrary, cSources, hSources) where
2
3 import Expression hiding (splitPath)
4 import GHC
5 import Oracles
6 import Predicates (splitObjects)
7 import Rules.Actions
8 import Rules.Resources
9 import Settings
10 import qualified System.Directory as IO
11
12 buildPackageLibrary :: Resources -> PartialTarget -> Rules ()
13 buildPackageLibrary _ target @ (PartialTarget stage pkg) = do
14 let path = targetPath stage pkg
15 buildPath = path -/- "build"
16
17 -- TODO: handle dynamic libraries
18 matchBuildResult buildPath "a" ?> \a -> do
19
20 removeFileIfExists a
21 cSrcs <- cSources target
22 hSrcs <- hSources target
23
24 let way = detectWay a -- TODO: eliminate differences below
25 cObjs = [ buildPath -/- src -<.> osuf way | src <- cSrcs ]
26 hObjs = [ buildPath -/- src <.> osuf way | src <- hSrcs ]
27
28 -- This will create split objects if required (we don't track them
29 -- explicitly as this would needlessly bloat the Shake database).
30 need $ cObjs ++ hObjs
31
32 split <- interpretPartial target splitObjects
33 splitObjs <- if not split then return hObjs else -- TODO: make clearer!
34 fmap concat $ forM hSrcs $ \src -> do
35 let splitPath = buildPath -/- src ++ "_" ++ osuf way ++ "_split"
36 contents <- liftIO $ IO.getDirectoryContents splitPath
37 return . map (splitPath -/-)
38 . filter (not . all (== '.')) $ contents
39
40 eObjs <- extraObjects target
41 let objs = cObjs ++ splitObjs ++ eObjs
42
43 asuf <- libsuf way
44 let isLib0 = ("//*-0" <.> asuf) ?== a
45 if isLib0
46 then build $ fullTarget target Ar [] [a] -- TODO: scan for dlls
47 else build $ fullTarget target Ar objs [a]
48
49 synopsis <- interpretPartial target $ getPkgData Synopsis
50 unless isLib0 . putSuccess $ renderBox
51 [ "Successfully built package library '"
52 ++ pkgNameString pkg
53 ++ "' (" ++ show stage ++ ", way "++ show way ++ ")."
54 , "Package synopsis: " ++ dropWhileEnd isPunctuation synopsis ++ "." ]
55
56 -- TODO: this looks fragile as haskell objects can match this rule if their
57 -- names start with "HS" and they are on top of the module hierarchy.
58 -- This happens with hsc2hs, which has top-level file HSCParser.hs.
59 when (pkg /= hsc2hs) $ priority 2 $ (buildPath -/- "HS*.o") %> \obj -> do
60 cSrcs <- cSources target
61 hSrcs <- hSources target
62 let cObjs = [ buildPath -/- src -<.> "o" | src <- cSrcs ]
63 hObjs = [ buildPath -/- src <.> "o" | src <- hSrcs ]
64 need $ cObjs ++ hObjs
65 build $ fullTarget target Ld (cObjs ++ hObjs) [obj]
66
67 cSources :: PartialTarget -> Action [FilePath]
68 cSources target = interpretPartial target $ getPkgDataList CSrcs
69
70 hSources :: PartialTarget -> Action [FilePath]
71 hSources target = do
72 modules <- interpretPartial target $ getPkgDataList Modules
73 -- GHC.Prim is special: we do not build it
74 return . map (replaceEq '.' '/') . filter (/= "GHC.Prim") $ modules
75
76 extraObjects :: PartialTarget -> Action [FilePath]
77 extraObjects (PartialTarget _ pkg)
78 | pkg == integerGmp = getDirectoryFiles "" [pkgPath pkg -/- "gmp/objs/*.o"]
79 | otherwise = return []