1// 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 15package blueprint 16 17import "sync" 18 19// 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 { 24 sync.Mutex 25 config interface{} // Used to evaluate variable, rule, and pool values. 26 ctx *Context // Used to evaluate globs 27 28 variables map[Variable]*ninjaString 29 pools map[Pool]*poolDef 30 rules map[Rule]*ruleDef 31} 32 33func newLiveTracker(ctx *Context, config interface{}) *liveTracker { 34 return &liveTracker{ 35 ctx: ctx, 36 config: config, 37 variables: make(map[Variable]*ninjaString), 38 pools: make(map[Pool]*poolDef), 39 rules: make(map[Rule]*ruleDef), 40 } 41} 42 43func (l *liveTracker) AddBuildDefDeps(def *buildDef) error { 44 l.Lock() 45 defer l.Unlock() 46 47 ruleDef, err := l.innerAddRule(def.Rule) 48 if err != nil { 49 return err 50 } 51 def.RuleDef = ruleDef 52 53 err = l.innerAddNinjaStringListDeps(def.Outputs) 54 if err != nil { 55 return err 56 } 57 58 err = l.innerAddNinjaStringListDeps(def.Inputs) 59 if err != nil { 60 return err 61 } 62 63 err = l.innerAddNinjaStringListDeps(def.Implicits) 64 if err != nil { 65 return err 66 } 67 68 err = l.innerAddNinjaStringListDeps(def.OrderOnly) 69 if err != nil { 70 return err 71 } 72 73 err = l.innerAddNinjaStringListDeps(def.Validations) 74 if err != nil { 75 return err 76 } 77 78 for _, value := range def.Variables { 79 err = l.innerAddNinjaStringDeps(value) 80 if err != nil { 81 return err 82 } 83 } 84 85 for _, value := range def.Args { 86 err = l.innerAddNinjaStringDeps(value) 87 if err != nil { 88 return err 89 } 90 } 91 92 return nil 93} 94 95func (l *liveTracker) addRule(r Rule) (def *ruleDef, err error) { 96 l.Lock() 97 defer l.Unlock() 98 return l.innerAddRule(r) 99} 100 101func (l *liveTracker) innerAddRule(r Rule) (def *ruleDef, err error) { 102 def, ok := l.rules[r] 103 if !ok { 104 def, err = r.def(l.config) 105 if err == errRuleIsBuiltin { 106 // No need to do anything for built-in rules. 107 return nil, nil 108 } 109 if err != nil { 110 return nil, err 111 } 112 113 if def.Pool != nil { 114 err = l.innerAddPool(def.Pool) 115 if err != nil { 116 return nil, err 117 } 118 } 119 120 err = l.innerAddNinjaStringListDeps(def.CommandDeps) 121 if err != nil { 122 return nil, err 123 } 124 125 err = l.innerAddNinjaStringListDeps(def.CommandOrderOnly) 126 if err != nil { 127 return nil, err 128 } 129 130 for _, value := range def.Variables { 131 err = l.innerAddNinjaStringDeps(value) 132 if err != nil { 133 return nil, err 134 } 135 } 136 137 l.rules[r] = def 138 } 139 140 return 141} 142 143func (l *liveTracker) addPool(p Pool) error { 144 l.Lock() 145 defer l.Unlock() 146 return l.addPool(p) 147} 148 149func (l *liveTracker) innerAddPool(p Pool) error { 150 _, ok := l.pools[p] 151 if !ok { 152 def, err := p.def(l.config) 153 if err == errPoolIsBuiltin { 154 // No need to do anything for built-in rules. 155 return nil 156 } 157 if err != nil { 158 return err 159 } 160 161 l.pools[p] = def 162 } 163 164 return nil 165} 166 167func (l *liveTracker) addVariable(v Variable) error { 168 l.Lock() 169 defer l.Unlock() 170 return l.innerAddVariable(v) 171} 172 173func (l *liveTracker) innerAddVariable(v Variable) error { 174 _, ok := l.variables[v] 175 if !ok { 176 ctx := &variableFuncContext{l.ctx} 177 178 value, err := v.value(ctx, l.config) 179 if err == errVariableIsArg { 180 // This variable is a placeholder for an argument that can be passed 181 // to a rule. It has no value and thus doesn't reference any other 182 // variables. 183 return nil 184 } 185 if err != nil { 186 return err 187 } 188 189 l.variables[v] = value 190 191 err = l.innerAddNinjaStringDeps(value) 192 if err != nil { 193 return err 194 } 195 } 196 197 return nil 198} 199 200func (l *liveTracker) addNinjaStringListDeps(list []*ninjaString) error { 201 l.Lock() 202 defer l.Unlock() 203 return l.innerAddNinjaStringListDeps(list) 204} 205 206func (l *liveTracker) innerAddNinjaStringListDeps(list []*ninjaString) error { 207 for _, str := range list { 208 err := l.innerAddNinjaStringDeps(str) 209 if err != nil { 210 return err 211 } 212 } 213 return nil 214} 215 216func (l *liveTracker) addNinjaStringDeps(str *ninjaString) error { 217 l.Lock() 218 defer l.Unlock() 219 return l.innerAddNinjaStringDeps(str) 220} 221 222func (l *liveTracker) innerAddNinjaStringDeps(str *ninjaString) error { 223 for _, v := range str.Variables() { 224 err := l.innerAddVariable(v) 225 if err != nil { 226 return err 227 } 228 } 229 return nil 230} 231 232func (l *liveTracker) Eval(n *ninjaString) (string, error) { 233 l.Lock() 234 defer l.Unlock() 235 return n.Eval(l.variables) 236} 237 238func (l *liveTracker) RemoveVariableIfLive(v Variable) bool { 239 l.Lock() 240 defer l.Unlock() 241 242 _, isLive := l.variables[v] 243 if isLive { 244 delete(l.variables, v) 245 } 246 return isLive 247} 248 249func (l *liveTracker) RemoveRuleIfLive(r Rule) bool { 250 l.Lock() 251 defer l.Unlock() 252 253 _, isLive := l.rules[r] 254 if isLive { 255 delete(l.rules, r) 256 } 257 return isLive 258} 259