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