blob: b7f3bc84470dcc95ed8a6d5b45d19ce3008484d9 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
module Rules.Compile (compilePackage) where
import Hadrian.Oracles.TextFile
import Base
import Context
import Expression
import Rules.Generate
import Target
import Utilities
compilePackage :: [(Resource, Int)] -> Context -> Rules ()
compilePackage rs context@Context {..} = do
let dir = "//" ++ contextDir context
nonHs extension = dir -/- extension <//> "*" <.> osuf way
compile compiler obj2src obj = do
src <- obj2src context obj
need [src]
needDependencies context src $ obj <.> "d"
buildWithResources rs $ target context (compiler stage) [src] [obj]
compileHs = \[obj, _hi] -> do
path <- buildPath context
(src, deps) <- lookupDependencies (path -/- ".dependencies") obj
need $ src : deps
buildWithResources rs $ target context (Ghc CompileHs stage) [src] [obj]
priority 2.0 $ do
nonHs "c" %> compile (Ghc CompileCWithGhc) (obj2src "c" isGeneratedCFile )
nonHs "cmm" %> compile (Ghc CompileHs) (obj2src "cmm" isGeneratedCmmFile)
nonHs "s" %> compile (Ghc CompileHs) (obj2src "S" $ const False )
-- TODO: Add dependencies for #include of .h and .hs-incl files (gcc -MM?).
[ dir <//> "*" <.> suf way | suf <- [ osuf, hisuf] ] &%> compileHs
[ dir <//> "*" <.> suf way | suf <- [obootsuf, hibootsuf] ] &%> compileHs
-- | Discover dependencies of a given source file by iteratively calling @gcc@
-- in the @-MM -MG@ mode and building generated dependencies if they are missing
-- until reaching a fixed point.
needDependencies :: Context -> FilePath -> FilePath -> Action ()
needDependencies context@Context {..} src depFile = discover
where
discover = do
build $ target context (Cc FindCDependencies stage) [src] [depFile]
deps <- parseFile depFile
-- Generated dependencies, if not yet built, will not be found and hence
-- will be referred to simply by their file names.
let notFound = filter (\file -> file == takeFileName file) deps
-- We find the full paths to generated dependencies, so we can request
-- to build them by calling 'need'.
todo <- catMaybes <$> mapM (fullPathIfGenerated context) notFound
if null todo
then need deps -- The list of dependencies is final, need all
else do
need todo -- Build newly discovered generated dependencies
discover -- Continue the discovery process
parseFile :: FilePath -> Action [String]
parseFile file = do
input <- liftIO $ readFile file
case parseMakefile input of
[(_file, deps)] -> return deps
_ -> return []
-- | Find a given 'FilePath' in the list of generated files in the given
-- 'Context' and return its full path.
fullPathIfGenerated :: Context -> FilePath -> Action (Maybe FilePath)
fullPathIfGenerated context file = interpretInContext context $ do
generated <- generatedDependencies
return $ find ((== file) . takeFileName) generated
obj2src :: String -> (FilePath -> Bool) -> Context -> FilePath -> Action FilePath
obj2src extension isGenerated context@Context {..} obj
| isGenerated src = return src
| otherwise = (pkgPath package ++) <$> suffix
where
src = obj -<.> extension
suffix = do
path <- buildPath context
return $ fromMaybe ("Cannot determine source for " ++ obj)
$ stripPrefix (path -/- extension) src
|