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