-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathLibDepTree.hs
157 lines (129 loc) · 5.61 KB
/
LibDepTree.hs
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
--------------------------------------------------------------------------
-- Copyright (c) 2007-2019, ETH Zurich.
-- All rights reserved.
--
-- This file is distributed under the terms in the attached LICENSE file.
-- If you do not find this file, copies can be found by writing to:
-- ETH Zurich D-INFK, Universitaetstasse 6, CH-8092 Zurich. Attn: Systems Group.
--
-- Default architecture-specific definitions for Barrelfish
--
--------------------------------------------------------------------------
module LibDepTree where
import HakeTypes
import qualified Data.Set as S
import Data.Array (indices)
import Data.Graph
import Data.Maybe
import Data.List (sortBy)
import qualified Data.Map.Strict as Map
import qualified RuleDefs -- for libraryPath and applicationPath
type DepElMap = Map.Map DepEl [DepEl]
data LibDepTree2 = LibDepTree2Graph {
gGraph :: Graph,
gNodeFromVertex :: Vertex -> (DepEl, DepEl, [DepEl]),
gVertexFromKey :: DepEl -> Maybe Vertex
}
-- Given an [HRule], extract a LibDepTree2
ldtEmToGraph :: DepElMap -> LibDepTree2
ldtEmToGraph tree = LibDepTree2Graph graph nodeFromVertex vertexFromKey
where
(graph, nodeFromVertex, vertexFromKey) = graphFromEdges (wchild ++ wochild)
wchild = [(a,a,reverse b) | (a,b) <- Map.toList tree]
wochild = [(c,c,[]) | c <- concat [cs | (_,cs) <- Map.toList tree],
Map.notMember c tree]
ldtDepElMerge :: DepElMap -> DepElMap -> DepElMap
ldtDepElMerge = Map.unionWith (++)
ldtHRuleToDepElMap :: [String] -> HRule -> DepElMap
ldtHRuleToDepElMap archs hrule = case hrule of
(Rules rules) -> foldr ldtDepElMerge Map.empty $ map (ldtHRuleToDepElMap archs) rules
(HakeTypes.Rule rts) -> foldr ldtDepElMerge Map.empty $ map ext_rt rts
_ -> Map.empty
where
ext_rt :: RuleToken -> DepElMap
ext_rt rt = case rt of
(LDep a b) -> if elem (depElArch a) archs then Map.singleton a [b] else Map.empty
_ -> Map.empty
ldtFromJust :: Maybe a -> String -> a
ldtFromJust Nothing err = errorWithoutStackTrace ("No Graph Node for " ++ err) -- yuck
ldtFromJust (Just x) err = x
ldtDepOf :: LibDepTree2 -> DepEl -> [DepEl]
ldtDepOf gr = sortBy rtCmp . map extractDepEl . mTopSort . mVertexFromKey
where
triFst (a,_,_) = a
extractDepEl = triFst . nodeFromVertex
(graph, nodeFromVertex, vertexFromKey) = (gGraph gr, gNodeFromVertex gr, gVertexFromKey gr)
mVertexFromKey :: DepEl -> Vertex
mVertexFromKey x = ldtFromJust (vertexFromKey x) ("No node " ++ show x)
-- We move the DepMods to the front, so the --whole-archive will be
-- linked first
rtCmp :: DepEl -> DepEl -> Ordering
rtCmp (DepMod _ _) (DepLib _ _) = LT
rtCmp (DepLib _ _) (DepMod _ _) = GT
rtCmp _ _ = EQ
-- The following functions are copied from Data.Graph and extended with
-- an additional "start" vertex
postorder :: Tree a -> [a] -> [a]
postorder (Node a ts) = postorderF ts . (a :)
postorderF :: Forest a -> [a] -> [a]
postorderF ts = foldr (.) id $ map postorder ts
mPostOrd :: Vertex -> [Vertex]
mPostOrd start = postorderF (mDff) []
where
mDff = dfs graph [start]
mTopSort :: Vertex -> [Vertex]
mTopSort start = tail $ reverse $ mPostOrd start
ldtDepDfs :: LibDepTree2 -> DepEl -> Tree DepEl
ldtDepDfs ldt start = fmap extractDepEl $ head (dfs graph [fromJust $ vertexFromKey start])
where
triFst (a,_,_) = a
extractDepEl = triFst . nodeFromVertex
(graph, nodeFromVertex, vertexFromKey) = (gGraph ldt, gNodeFromVertex ldt, gVertexFromKey ldt)
ldtDriverModules :: LibDepTree2 -> [(DepEl,DepEl)]
-- concat $ map depS (indices $ gGraph t)
ldtDriverModules t = depS =<< indices (gGraph t)
where
triFst (a,_,_) = a
toNode :: Vertex -> DepEl
toNode = triFst . gNodeFromVertex t
depS :: Vertex -> [(DepEl,DepEl)]
depS = step . ldtDepDfs t . toNode
step :: Tree DepEl -> [(DepEl,DepEl)]
step (Node (DepApp arch name) cs) = [ ((DepApp arch name),x) | x <- concat $ map nm cs]
where
nm (Node (DepMod arch name) _) = [DepMod arch name]
nm _ = []
step _ = []
ldtPrettyTree :: Tree DepEl -> String
ldtPrettyTree tr = prettyPrintR tr ""
where
prettyPrintR (Node lbl cs) ind = (ind ++ (show lbl)) ++ "\n" ++
(concat $ [prettyPrintR c ("+ " ++ ind) | c <- cs])
-- Replace the Ldt tokens with In rule tokens
ldtRuleExpand :: LibDepTree2 -> HRule -> HRule
ldtRuleExpand ldt x = case x of
Rule tokens -> Rule $ concat [ldtTokenExpand ldt x | x <- tokens]
Phony s b tokens -> Phony s b $ concat [ldtTokenExpand ldt x | x <- tokens]
Rules rules -> Rules [ldtRuleExpand ldt x | x <- rules]
_ -> x -- .. that means we dont support Ldt tokens under an Include
ldtTokenExpand :: LibDepTree2 -> RuleToken -> [RuleToken]
ldtTokenExpand ldt x = case x of
Ldt tree arch app -> concat $ map toRT $ ldtDepOf ldt (DepApp arch app)
where
toRT :: DepEl -> [RuleToken]
-- XXX: I couldnt figure out where we usually prefix the architecture
toRT (DepApp xarch x) = [In tree arch $
("./" ++ arch ++ (RuleDefs.applicationPath (RuleDefs.options arch) x))]
toRT (DepLib xarch x) = [In tree arch $
("./" ++ arch ++ (RuleDefs.libraryPath (RuleDefs.options arch) x))]
toRT (DepMod xarch x) =
[Str "-Wl,--whole-archive"] ++
(toRT (DepLib xarch x)) ++
[Str "-Wl,--no-whole-archive"]
_ -> [x]
ldtDebug :: LibDepTree2 -> DepEl -> IO ()
ldtDebug ldt el = do
putStrLn $ "Deps of " ++ (show el) ++ ":"
putStrLn $ ldtPrettyTree $ ldtDepDfs ldt el
putStrLn $ show $ ldtDepOf ldt el
return ()