1*1fa6dee9SAndroid Build Coastguard Worker// Copyright 2014 Google Inc. All rights reserved. 2*1fa6dee9SAndroid Build Coastguard Worker// 3*1fa6dee9SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*1fa6dee9SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*1fa6dee9SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*1fa6dee9SAndroid Build Coastguard Worker// 7*1fa6dee9SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*1fa6dee9SAndroid Build Coastguard Worker// 9*1fa6dee9SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*1fa6dee9SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*1fa6dee9SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*1fa6dee9SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*1fa6dee9SAndroid Build Coastguard Worker// limitations under the License. 14*1fa6dee9SAndroid Build Coastguard Worker 15*1fa6dee9SAndroid Build Coastguard Workerpackage blueprint 16*1fa6dee9SAndroid Build Coastguard Worker 17*1fa6dee9SAndroid Build Coastguard Workerimport "sync" 18*1fa6dee9SAndroid Build Coastguard Worker 19*1fa6dee9SAndroid Build Coastguard Worker// A liveTracker tracks the values of live variables, rules, and pools. An 20*1fa6dee9SAndroid Build Coastguard Worker// entity is made "live" when it is referenced directly or indirectly by a build 21*1fa6dee9SAndroid Build Coastguard Worker// definition. When an entity is made live its value is computed based on the 22*1fa6dee9SAndroid Build Coastguard Worker// configuration. 23*1fa6dee9SAndroid Build Coastguard Workertype liveTracker struct { 24*1fa6dee9SAndroid Build Coastguard Worker sync.Mutex 25*1fa6dee9SAndroid Build Coastguard Worker config interface{} // Used to evaluate variable, rule, and pool values. 26*1fa6dee9SAndroid Build Coastguard Worker ctx *Context // Used to evaluate globs 27*1fa6dee9SAndroid Build Coastguard Worker 28*1fa6dee9SAndroid Build Coastguard Worker variables map[Variable]*ninjaString 29*1fa6dee9SAndroid Build Coastguard Worker pools map[Pool]*poolDef 30*1fa6dee9SAndroid Build Coastguard Worker rules map[Rule]*ruleDef 31*1fa6dee9SAndroid Build Coastguard Worker} 32*1fa6dee9SAndroid Build Coastguard Worker 33*1fa6dee9SAndroid Build Coastguard Workerfunc newLiveTracker(ctx *Context, config interface{}) *liveTracker { 34*1fa6dee9SAndroid Build Coastguard Worker return &liveTracker{ 35*1fa6dee9SAndroid Build Coastguard Worker ctx: ctx, 36*1fa6dee9SAndroid Build Coastguard Worker config: config, 37*1fa6dee9SAndroid Build Coastguard Worker variables: make(map[Variable]*ninjaString), 38*1fa6dee9SAndroid Build Coastguard Worker pools: make(map[Pool]*poolDef), 39*1fa6dee9SAndroid Build Coastguard Worker rules: make(map[Rule]*ruleDef), 40*1fa6dee9SAndroid Build Coastguard Worker } 41*1fa6dee9SAndroid Build Coastguard Worker} 42*1fa6dee9SAndroid Build Coastguard Worker 43*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) AddBuildDefDeps(def *buildDef) error { 44*1fa6dee9SAndroid Build Coastguard Worker l.Lock() 45*1fa6dee9SAndroid Build Coastguard Worker defer l.Unlock() 46*1fa6dee9SAndroid Build Coastguard Worker 47*1fa6dee9SAndroid Build Coastguard Worker ruleDef, err := l.innerAddRule(def.Rule) 48*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 49*1fa6dee9SAndroid Build Coastguard Worker return err 50*1fa6dee9SAndroid Build Coastguard Worker } 51*1fa6dee9SAndroid Build Coastguard Worker def.RuleDef = ruleDef 52*1fa6dee9SAndroid Build Coastguard Worker 53*1fa6dee9SAndroid Build Coastguard Worker err = l.innerAddNinjaStringListDeps(def.Outputs) 54*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 55*1fa6dee9SAndroid Build Coastguard Worker return err 56*1fa6dee9SAndroid Build Coastguard Worker } 57*1fa6dee9SAndroid Build Coastguard Worker 58*1fa6dee9SAndroid Build Coastguard Worker err = l.innerAddNinjaStringListDeps(def.Inputs) 59*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 60*1fa6dee9SAndroid Build Coastguard Worker return err 61*1fa6dee9SAndroid Build Coastguard Worker } 62*1fa6dee9SAndroid Build Coastguard Worker 63*1fa6dee9SAndroid Build Coastguard Worker err = l.innerAddNinjaStringListDeps(def.Implicits) 64*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 65*1fa6dee9SAndroid Build Coastguard Worker return err 66*1fa6dee9SAndroid Build Coastguard Worker } 67*1fa6dee9SAndroid Build Coastguard Worker 68*1fa6dee9SAndroid Build Coastguard Worker err = l.innerAddNinjaStringListDeps(def.OrderOnly) 69*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 70*1fa6dee9SAndroid Build Coastguard Worker return err 71*1fa6dee9SAndroid Build Coastguard Worker } 72*1fa6dee9SAndroid Build Coastguard Worker 73*1fa6dee9SAndroid Build Coastguard Worker err = l.innerAddNinjaStringListDeps(def.Validations) 74*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 75*1fa6dee9SAndroid Build Coastguard Worker return err 76*1fa6dee9SAndroid Build Coastguard Worker } 77*1fa6dee9SAndroid Build Coastguard Worker 78*1fa6dee9SAndroid Build Coastguard Worker for _, value := range def.Variables { 79*1fa6dee9SAndroid Build Coastguard Worker err = l.innerAddNinjaStringDeps(value) 80*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 81*1fa6dee9SAndroid Build Coastguard Worker return err 82*1fa6dee9SAndroid Build Coastguard Worker } 83*1fa6dee9SAndroid Build Coastguard Worker } 84*1fa6dee9SAndroid Build Coastguard Worker 85*1fa6dee9SAndroid Build Coastguard Worker for _, value := range def.Args { 86*1fa6dee9SAndroid Build Coastguard Worker err = l.innerAddNinjaStringDeps(value) 87*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 88*1fa6dee9SAndroid Build Coastguard Worker return err 89*1fa6dee9SAndroid Build Coastguard Worker } 90*1fa6dee9SAndroid Build Coastguard Worker } 91*1fa6dee9SAndroid Build Coastguard Worker 92*1fa6dee9SAndroid Build Coastguard Worker return nil 93*1fa6dee9SAndroid Build Coastguard Worker} 94*1fa6dee9SAndroid Build Coastguard Worker 95*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) addRule(r Rule) (def *ruleDef, err error) { 96*1fa6dee9SAndroid Build Coastguard Worker l.Lock() 97*1fa6dee9SAndroid Build Coastguard Worker defer l.Unlock() 98*1fa6dee9SAndroid Build Coastguard Worker return l.innerAddRule(r) 99*1fa6dee9SAndroid Build Coastguard Worker} 100*1fa6dee9SAndroid Build Coastguard Worker 101*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) innerAddRule(r Rule) (def *ruleDef, err error) { 102*1fa6dee9SAndroid Build Coastguard Worker def, ok := l.rules[r] 103*1fa6dee9SAndroid Build Coastguard Worker if !ok { 104*1fa6dee9SAndroid Build Coastguard Worker def, err = r.def(l.config) 105*1fa6dee9SAndroid Build Coastguard Worker if err == errRuleIsBuiltin { 106*1fa6dee9SAndroid Build Coastguard Worker // No need to do anything for built-in rules. 107*1fa6dee9SAndroid Build Coastguard Worker return nil, nil 108*1fa6dee9SAndroid Build Coastguard Worker } 109*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 110*1fa6dee9SAndroid Build Coastguard Worker return nil, err 111*1fa6dee9SAndroid Build Coastguard Worker } 112*1fa6dee9SAndroid Build Coastguard Worker 113*1fa6dee9SAndroid Build Coastguard Worker if def.Pool != nil { 114*1fa6dee9SAndroid Build Coastguard Worker err = l.innerAddPool(def.Pool) 115*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 116*1fa6dee9SAndroid Build Coastguard Worker return nil, err 117*1fa6dee9SAndroid Build Coastguard Worker } 118*1fa6dee9SAndroid Build Coastguard Worker } 119*1fa6dee9SAndroid Build Coastguard Worker 120*1fa6dee9SAndroid Build Coastguard Worker err = l.innerAddNinjaStringListDeps(def.CommandDeps) 121*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 122*1fa6dee9SAndroid Build Coastguard Worker return nil, err 123*1fa6dee9SAndroid Build Coastguard Worker } 124*1fa6dee9SAndroid Build Coastguard Worker 125*1fa6dee9SAndroid Build Coastguard Worker err = l.innerAddNinjaStringListDeps(def.CommandOrderOnly) 126*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 127*1fa6dee9SAndroid Build Coastguard Worker return nil, err 128*1fa6dee9SAndroid Build Coastguard Worker } 129*1fa6dee9SAndroid Build Coastguard Worker 130*1fa6dee9SAndroid Build Coastguard Worker for _, value := range def.Variables { 131*1fa6dee9SAndroid Build Coastguard Worker err = l.innerAddNinjaStringDeps(value) 132*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 133*1fa6dee9SAndroid Build Coastguard Worker return nil, err 134*1fa6dee9SAndroid Build Coastguard Worker } 135*1fa6dee9SAndroid Build Coastguard Worker } 136*1fa6dee9SAndroid Build Coastguard Worker 137*1fa6dee9SAndroid Build Coastguard Worker l.rules[r] = def 138*1fa6dee9SAndroid Build Coastguard Worker } 139*1fa6dee9SAndroid Build Coastguard Worker 140*1fa6dee9SAndroid Build Coastguard Worker return 141*1fa6dee9SAndroid Build Coastguard Worker} 142*1fa6dee9SAndroid Build Coastguard Worker 143*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) addPool(p Pool) error { 144*1fa6dee9SAndroid Build Coastguard Worker l.Lock() 145*1fa6dee9SAndroid Build Coastguard Worker defer l.Unlock() 146*1fa6dee9SAndroid Build Coastguard Worker return l.addPool(p) 147*1fa6dee9SAndroid Build Coastguard Worker} 148*1fa6dee9SAndroid Build Coastguard Worker 149*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) innerAddPool(p Pool) error { 150*1fa6dee9SAndroid Build Coastguard Worker _, ok := l.pools[p] 151*1fa6dee9SAndroid Build Coastguard Worker if !ok { 152*1fa6dee9SAndroid Build Coastguard Worker def, err := p.def(l.config) 153*1fa6dee9SAndroid Build Coastguard Worker if err == errPoolIsBuiltin { 154*1fa6dee9SAndroid Build Coastguard Worker // No need to do anything for built-in rules. 155*1fa6dee9SAndroid Build Coastguard Worker return nil 156*1fa6dee9SAndroid Build Coastguard Worker } 157*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 158*1fa6dee9SAndroid Build Coastguard Worker return err 159*1fa6dee9SAndroid Build Coastguard Worker } 160*1fa6dee9SAndroid Build Coastguard Worker 161*1fa6dee9SAndroid Build Coastguard Worker l.pools[p] = def 162*1fa6dee9SAndroid Build Coastguard Worker } 163*1fa6dee9SAndroid Build Coastguard Worker 164*1fa6dee9SAndroid Build Coastguard Worker return nil 165*1fa6dee9SAndroid Build Coastguard Worker} 166*1fa6dee9SAndroid Build Coastguard Worker 167*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) addVariable(v Variable) error { 168*1fa6dee9SAndroid Build Coastguard Worker l.Lock() 169*1fa6dee9SAndroid Build Coastguard Worker defer l.Unlock() 170*1fa6dee9SAndroid Build Coastguard Worker return l.innerAddVariable(v) 171*1fa6dee9SAndroid Build Coastguard Worker} 172*1fa6dee9SAndroid Build Coastguard Worker 173*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) innerAddVariable(v Variable) error { 174*1fa6dee9SAndroid Build Coastguard Worker _, ok := l.variables[v] 175*1fa6dee9SAndroid Build Coastguard Worker if !ok { 176*1fa6dee9SAndroid Build Coastguard Worker ctx := &variableFuncContext{l.ctx} 177*1fa6dee9SAndroid Build Coastguard Worker 178*1fa6dee9SAndroid Build Coastguard Worker value, err := v.value(ctx, l.config) 179*1fa6dee9SAndroid Build Coastguard Worker if err == errVariableIsArg { 180*1fa6dee9SAndroid Build Coastguard Worker // This variable is a placeholder for an argument that can be passed 181*1fa6dee9SAndroid Build Coastguard Worker // to a rule. It has no value and thus doesn't reference any other 182*1fa6dee9SAndroid Build Coastguard Worker // variables. 183*1fa6dee9SAndroid Build Coastguard Worker return nil 184*1fa6dee9SAndroid Build Coastguard Worker } 185*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 186*1fa6dee9SAndroid Build Coastguard Worker return err 187*1fa6dee9SAndroid Build Coastguard Worker } 188*1fa6dee9SAndroid Build Coastguard Worker 189*1fa6dee9SAndroid Build Coastguard Worker l.variables[v] = value 190*1fa6dee9SAndroid Build Coastguard Worker 191*1fa6dee9SAndroid Build Coastguard Worker err = l.innerAddNinjaStringDeps(value) 192*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 193*1fa6dee9SAndroid Build Coastguard Worker return err 194*1fa6dee9SAndroid Build Coastguard Worker } 195*1fa6dee9SAndroid Build Coastguard Worker } 196*1fa6dee9SAndroid Build Coastguard Worker 197*1fa6dee9SAndroid Build Coastguard Worker return nil 198*1fa6dee9SAndroid Build Coastguard Worker} 199*1fa6dee9SAndroid Build Coastguard Worker 200*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) addNinjaStringListDeps(list []*ninjaString) error { 201*1fa6dee9SAndroid Build Coastguard Worker l.Lock() 202*1fa6dee9SAndroid Build Coastguard Worker defer l.Unlock() 203*1fa6dee9SAndroid Build Coastguard Worker return l.innerAddNinjaStringListDeps(list) 204*1fa6dee9SAndroid Build Coastguard Worker} 205*1fa6dee9SAndroid Build Coastguard Worker 206*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) innerAddNinjaStringListDeps(list []*ninjaString) error { 207*1fa6dee9SAndroid Build Coastguard Worker for _, str := range list { 208*1fa6dee9SAndroid Build Coastguard Worker err := l.innerAddNinjaStringDeps(str) 209*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 210*1fa6dee9SAndroid Build Coastguard Worker return err 211*1fa6dee9SAndroid Build Coastguard Worker } 212*1fa6dee9SAndroid Build Coastguard Worker } 213*1fa6dee9SAndroid Build Coastguard Worker return nil 214*1fa6dee9SAndroid Build Coastguard Worker} 215*1fa6dee9SAndroid Build Coastguard Worker 216*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) addNinjaStringDeps(str *ninjaString) error { 217*1fa6dee9SAndroid Build Coastguard Worker l.Lock() 218*1fa6dee9SAndroid Build Coastguard Worker defer l.Unlock() 219*1fa6dee9SAndroid Build Coastguard Worker return l.innerAddNinjaStringDeps(str) 220*1fa6dee9SAndroid Build Coastguard Worker} 221*1fa6dee9SAndroid Build Coastguard Worker 222*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) innerAddNinjaStringDeps(str *ninjaString) error { 223*1fa6dee9SAndroid Build Coastguard Worker for _, v := range str.Variables() { 224*1fa6dee9SAndroid Build Coastguard Worker err := l.innerAddVariable(v) 225*1fa6dee9SAndroid Build Coastguard Worker if err != nil { 226*1fa6dee9SAndroid Build Coastguard Worker return err 227*1fa6dee9SAndroid Build Coastguard Worker } 228*1fa6dee9SAndroid Build Coastguard Worker } 229*1fa6dee9SAndroid Build Coastguard Worker return nil 230*1fa6dee9SAndroid Build Coastguard Worker} 231*1fa6dee9SAndroid Build Coastguard Worker 232*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) Eval(n *ninjaString) (string, error) { 233*1fa6dee9SAndroid Build Coastguard Worker l.Lock() 234*1fa6dee9SAndroid Build Coastguard Worker defer l.Unlock() 235*1fa6dee9SAndroid Build Coastguard Worker return n.Eval(l.variables) 236*1fa6dee9SAndroid Build Coastguard Worker} 237*1fa6dee9SAndroid Build Coastguard Worker 238*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) RemoveVariableIfLive(v Variable) bool { 239*1fa6dee9SAndroid Build Coastguard Worker l.Lock() 240*1fa6dee9SAndroid Build Coastguard Worker defer l.Unlock() 241*1fa6dee9SAndroid Build Coastguard Worker 242*1fa6dee9SAndroid Build Coastguard Worker _, isLive := l.variables[v] 243*1fa6dee9SAndroid Build Coastguard Worker if isLive { 244*1fa6dee9SAndroid Build Coastguard Worker delete(l.variables, v) 245*1fa6dee9SAndroid Build Coastguard Worker } 246*1fa6dee9SAndroid Build Coastguard Worker return isLive 247*1fa6dee9SAndroid Build Coastguard Worker} 248*1fa6dee9SAndroid Build Coastguard Worker 249*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) RemoveRuleIfLive(r Rule) bool { 250*1fa6dee9SAndroid Build Coastguard Worker l.Lock() 251*1fa6dee9SAndroid Build Coastguard Worker defer l.Unlock() 252*1fa6dee9SAndroid Build Coastguard Worker 253*1fa6dee9SAndroid Build Coastguard Worker _, isLive := l.rules[r] 254*1fa6dee9SAndroid Build Coastguard Worker if isLive { 255*1fa6dee9SAndroid Build Coastguard Worker delete(l.rules, r) 256*1fa6dee9SAndroid Build Coastguard Worker } 257*1fa6dee9SAndroid Build Coastguard Worker return isLive 258*1fa6dee9SAndroid Build Coastguard Worker} 259