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.addRule(def.Rule) 48 if err != nil { 49 return err 50 } 51 def.RuleDef = ruleDef 52 53 err = l.addNinjaStringListDeps(def.Outputs) 54 if err != nil { 55 return err 56 } 57 58 err = l.addNinjaStringListDeps(def.Inputs) 59 if err != nil { 60 return err 61 } 62 63 err = l.addNinjaStringListDeps(def.Implicits) 64 if err != nil { 65 return err 66 } 67 68 err = l.addNinjaStringListDeps(def.OrderOnly) 69 if err != nil { 70 return err 71 } 72 73 err = l.addNinjaStringListDeps(def.Validations) 74 if err != nil { 75 return err 76 } 77 78 for _, value := range def.Variables { 79 err = l.addNinjaStringDeps(value) 80 if err != nil { 81 return err 82 } 83 } 84 85 for _, value := range def.Args { 86 err = l.addNinjaStringDeps(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 def, ok := l.rules[r] 97 if !ok { 98 def, err = r.def(l.config) 99 if err == errRuleIsBuiltin { 100 // No need to do anything for built-in rules. 101 return nil, nil 102 } 103 if err != nil { 104 return nil, err 105 } 106 107 if def.Pool != nil { 108 err = l.addPool(def.Pool) 109 if err != nil { 110 return nil, err 111 } 112 } 113 114 err = l.addNinjaStringListDeps(def.CommandDeps) 115 if err != nil { 116 return nil, err 117 } 118 119 err = l.addNinjaStringListDeps(def.CommandOrderOnly) 120 if err != nil { 121 return nil, err 122 } 123 124 for _, value := range def.Variables { 125 err = l.addNinjaStringDeps(value) 126 if err != nil { 127 return nil, err 128 } 129 } 130 131 l.rules[r] = def 132 } 133 134 return 135} 136 137func (l *liveTracker) addPool(p Pool) error { 138 _, ok := l.pools[p] 139 if !ok { 140 def, err := p.def(l.config) 141 if err == errPoolIsBuiltin { 142 // No need to do anything for built-in rules. 143 return nil 144 } 145 if err != nil { 146 return err 147 } 148 149 l.pools[p] = def 150 } 151 152 return nil 153} 154 155func (l *liveTracker) addVariable(v Variable) error { 156 _, ok := l.variables[v] 157 if !ok { 158 ctx := &variableFuncContext{l.ctx} 159 160 value, err := v.value(ctx, l.config) 161 if err == errVariableIsArg { 162 // This variable is a placeholder for an argument that can be passed 163 // to a rule. It has no value and thus doesn't reference any other 164 // variables. 165 return nil 166 } 167 if err != nil { 168 return err 169 } 170 171 l.variables[v] = value 172 173 err = l.addNinjaStringDeps(value) 174 if err != nil { 175 return err 176 } 177 } 178 179 return nil 180} 181 182func (l *liveTracker) addNinjaStringListDeps(list []ninjaString) error { 183 for _, str := range list { 184 err := l.addNinjaStringDeps(str) 185 if err != nil { 186 return err 187 } 188 } 189 return nil 190} 191 192func (l *liveTracker) addNinjaStringDeps(str ninjaString) error { 193 for _, v := range str.Variables() { 194 err := l.addVariable(v) 195 if err != nil { 196 return err 197 } 198 } 199 return nil 200} 201 202func (l *liveTracker) RemoveVariableIfLive(v Variable) bool { 203 l.Lock() 204 defer l.Unlock() 205 206 _, isLive := l.variables[v] 207 if isLive { 208 delete(l.variables, v) 209 } 210 return isLive 211} 212 213func (l *liveTracker) RemoveRuleIfLive(r Rule) bool { 214 l.Lock() 215 defer l.Unlock() 216 217 _, isLive := l.rules[r] 218 if isLive { 219 delete(l.rules, r) 220 } 221 return isLive 222} 223