blob: 3b41d06f2105f920c3e2b7f62604e53e265dd00d [file] [log] [blame]
Colin Cross8e0c5112015-01-23 14:15:10 -08001// Copyright 2014 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Jamie Gennis1bc967e2014-05-27 16:34:41 -070015package blueprint
16
Colin Cross691a60d2015-01-07 18:08:56 -080017import "sync"
18
Jamie Gennis1bc967e2014-05-27 16:34:41 -070019// A liveTracker tracks the values of live variables, rules, and pools. An
20// entity is made "live" when it is referenced directly or indirectly by a build
21// definition. When an entity is made live its value is computed based on the
22// configuration.
23type liveTracker struct {
Colin Cross691a60d2015-01-07 18:08:56 -080024 sync.Mutex
Jamie Gennis6eb4d242014-06-11 18:31:16 -070025 config interface{} // Used to evaluate variable, rule, and pool values.
Jamie Gennis1bc967e2014-05-27 16:34:41 -070026
27 variables map[Variable]*ninjaString
28 pools map[Pool]*poolDef
29 rules map[Rule]*ruleDef
30}
31
Jamie Gennis6eb4d242014-06-11 18:31:16 -070032func newLiveTracker(config interface{}) *liveTracker {
Jamie Gennis1bc967e2014-05-27 16:34:41 -070033 return &liveTracker{
34 config: config,
35 variables: make(map[Variable]*ninjaString),
36 pools: make(map[Pool]*poolDef),
37 rules: make(map[Rule]*ruleDef),
38 }
39}
40
41func (l *liveTracker) AddBuildDefDeps(def *buildDef) error {
Colin Cross691a60d2015-01-07 18:08:56 -080042 l.Lock()
43 defer l.Unlock()
44
Jamie Gennis1bc967e2014-05-27 16:34:41 -070045 err := l.addRule(def.Rule)
46 if err != nil {
47 return err
48 }
49
50 err = l.addNinjaStringListDeps(def.Outputs)
51 if err != nil {
52 return err
53 }
54
55 err = l.addNinjaStringListDeps(def.Inputs)
56 if err != nil {
57 return err
58 }
59
60 err = l.addNinjaStringListDeps(def.Implicits)
61 if err != nil {
62 return err
63 }
64
65 err = l.addNinjaStringListDeps(def.OrderOnly)
66 if err != nil {
67 return err
68 }
69
70 for _, value := range def.Args {
71 err = l.addNinjaStringDeps(value)
72 if err != nil {
73 return err
74 }
75 }
76
77 return nil
78}
79
80func (l *liveTracker) addRule(r Rule) error {
81 _, ok := l.rules[r]
82 if !ok {
83 def, err := r.def(l.config)
84 if err == errRuleIsBuiltin {
85 // No need to do anything for built-in rules.
86 return nil
87 }
88 if err != nil {
89 return err
90 }
91
92 if def.Pool != nil {
93 err = l.addPool(def.Pool)
94 if err != nil {
95 return err
96 }
97 }
98
99 for _, value := range def.Variables {
100 err = l.addNinjaStringDeps(value)
101 if err != nil {
102 return err
103 }
104 }
105
106 l.rules[r] = def
107 }
108
109 return nil
110}
111
112func (l *liveTracker) addPool(p Pool) error {
113 _, ok := l.pools[p]
114 if !ok {
115 def, err := p.def(l.config)
Ken Oslund4b9a0512015-04-14 16:26:58 -0700116 if err == errPoolIsBuiltin {
117 // No need to do anything for built-in rules.
118 return nil
119 }
Jamie Gennis1bc967e2014-05-27 16:34:41 -0700120 if err != nil {
121 return err
122 }
123
124 l.pools[p] = def
125 }
126
127 return nil
128}
129
130func (l *liveTracker) addVariable(v Variable) error {
131 _, ok := l.variables[v]
132 if !ok {
133 value, err := v.value(l.config)
134 if err == errVariableIsArg {
135 // This variable is a placeholder for an argument that can be passed
136 // to a rule. It has no value and thus doesn't reference any other
137 // variables.
138 return nil
139 }
140 if err != nil {
141 return err
142 }
143
144 l.variables[v] = value
145
146 err = l.addNinjaStringDeps(value)
147 if err != nil {
148 return err
149 }
150 }
151
152 return nil
153}
154
155func (l *liveTracker) addNinjaStringListDeps(list []*ninjaString) error {
156 for _, str := range list {
157 err := l.addNinjaStringDeps(str)
158 if err != nil {
159 return err
160 }
161 }
162 return nil
163}
164
165func (l *liveTracker) addNinjaStringDeps(str *ninjaString) error {
166 for _, v := range str.variables {
167 err := l.addVariable(v)
168 if err != nil {
169 return err
170 }
171 }
172 return nil
173}
Colin Crossab6d7902015-03-11 16:17:52 -0700174
175func (l *liveTracker) RemoveVariableIfLive(v Variable) bool {
176 l.Lock()
177 defer l.Unlock()
178
179 _, isLive := l.variables[v]
180 if isLive {
181 delete(l.variables, v)
182 }
183 return isLive
184}
185
186func (l *liveTracker) RemoveRuleIfLive(r Rule) bool {
187 l.Lock()
188 defer l.Unlock()
189
190 _, isLive := l.rules[r]
191 if isLive {
192 delete(l.rules, r)
193 }
194 return isLive
195}