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