2015-01-23 23:15:10 +01:00
|
|
|
// Copyright 2014 Google Inc. All rights reserved.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2014-05-28 01:34:41 +02:00
|
|
|
package blueprint
|
|
|
|
|
2015-01-08 03:08:56 +01:00
|
|
|
import "sync"
|
|
|
|
|
2014-05-28 01:34:41 +02:00
|
|
|
// A liveTracker tracks the values of live variables, rules, and pools. An
|
|
|
|
// entity is made "live" when it is referenced directly or indirectly by a build
|
|
|
|
// definition. When an entity is made live its value is computed based on the
|
|
|
|
// configuration.
|
|
|
|
type liveTracker struct {
|
2015-01-08 03:08:56 +01:00
|
|
|
sync.Mutex
|
2014-06-12 03:31:16 +02:00
|
|
|
config interface{} // Used to evaluate variable, rule, and pool values.
|
2014-05-28 01:34:41 +02:00
|
|
|
|
|
|
|
variables map[Variable]*ninjaString
|
|
|
|
pools map[Pool]*poolDef
|
|
|
|
rules map[Rule]*ruleDef
|
|
|
|
}
|
|
|
|
|
2014-06-12 03:31:16 +02:00
|
|
|
func newLiveTracker(config interface{}) *liveTracker {
|
2014-05-28 01:34:41 +02:00
|
|
|
return &liveTracker{
|
|
|
|
config: config,
|
|
|
|
variables: make(map[Variable]*ninjaString),
|
|
|
|
pools: make(map[Pool]*poolDef),
|
|
|
|
rules: make(map[Rule]*ruleDef),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *liveTracker) AddBuildDefDeps(def *buildDef) error {
|
2015-01-08 03:08:56 +01:00
|
|
|
l.Lock()
|
|
|
|
defer l.Unlock()
|
|
|
|
|
2015-11-17 23:21:45 +01:00
|
|
|
ruleDef, err := l.addRule(def.Rule)
|
2014-05-28 01:34:41 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2015-11-17 23:21:45 +01:00
|
|
|
def.RuleDef = ruleDef
|
2014-05-28 01:34:41 +02:00
|
|
|
|
|
|
|
err = l.addNinjaStringListDeps(def.Outputs)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
err = l.addNinjaStringListDeps(def.Inputs)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
err = l.addNinjaStringListDeps(def.Implicits)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
err = l.addNinjaStringListDeps(def.OrderOnly)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, value := range def.Args {
|
|
|
|
err = l.addNinjaStringDeps(value)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-11-17 23:21:45 +01:00
|
|
|
func (l *liveTracker) addRule(r Rule) (def *ruleDef, err error) {
|
|
|
|
def, ok := l.rules[r]
|
2014-05-28 01:34:41 +02:00
|
|
|
if !ok {
|
2015-11-17 23:21:45 +01:00
|
|
|
def, err = r.def(l.config)
|
2014-05-28 01:34:41 +02:00
|
|
|
if err == errRuleIsBuiltin {
|
|
|
|
// No need to do anything for built-in rules.
|
2015-11-17 23:21:45 +01:00
|
|
|
return nil, nil
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
if err != nil {
|
2015-11-17 23:21:45 +01:00
|
|
|
return nil, err
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if def.Pool != nil {
|
|
|
|
err = l.addPool(def.Pool)
|
|
|
|
if err != nil {
|
2015-11-17 23:21:45 +01:00
|
|
|
return nil, err
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-17 23:21:45 +01:00
|
|
|
err = l.addNinjaStringListDeps(def.CommandDeps)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2014-05-28 01:34:41 +02:00
|
|
|
for _, value := range def.Variables {
|
|
|
|
err = l.addNinjaStringDeps(value)
|
|
|
|
if err != nil {
|
2015-11-17 23:21:45 +01:00
|
|
|
return nil, err
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
l.rules[r] = def
|
|
|
|
}
|
|
|
|
|
2015-11-17 23:21:45 +01:00
|
|
|
return
|
2014-05-28 01:34:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (l *liveTracker) addPool(p Pool) error {
|
|
|
|
_, ok := l.pools[p]
|
|
|
|
if !ok {
|
|
|
|
def, err := p.def(l.config)
|
2015-04-15 01:26:58 +02:00
|
|
|
if err == errPoolIsBuiltin {
|
|
|
|
// No need to do anything for built-in rules.
|
|
|
|
return nil
|
|
|
|
}
|
2014-05-28 01:34:41 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
l.pools[p] = def
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *liveTracker) addVariable(v Variable) error {
|
|
|
|
_, ok := l.variables[v]
|
|
|
|
if !ok {
|
|
|
|
value, err := v.value(l.config)
|
|
|
|
if err == errVariableIsArg {
|
|
|
|
// This variable is a placeholder for an argument that can be passed
|
|
|
|
// to a rule. It has no value and thus doesn't reference any other
|
|
|
|
// variables.
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
l.variables[v] = value
|
|
|
|
|
|
|
|
err = l.addNinjaStringDeps(value)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *liveTracker) addNinjaStringListDeps(list []*ninjaString) error {
|
|
|
|
for _, str := range list {
|
|
|
|
err := l.addNinjaStringDeps(str)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *liveTracker) addNinjaStringDeps(str *ninjaString) error {
|
|
|
|
for _, v := range str.variables {
|
|
|
|
err := l.addVariable(v)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2015-03-12 00:17:52 +01:00
|
|
|
|
|
|
|
func (l *liveTracker) RemoveVariableIfLive(v Variable) bool {
|
|
|
|
l.Lock()
|
|
|
|
defer l.Unlock()
|
|
|
|
|
|
|
|
_, isLive := l.variables[v]
|
|
|
|
if isLive {
|
|
|
|
delete(l.variables, v)
|
|
|
|
}
|
|
|
|
return isLive
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l *liveTracker) RemoveRuleIfLive(r Rule) bool {
|
|
|
|
l.Lock()
|
|
|
|
defer l.Unlock()
|
|
|
|
|
|
|
|
_, isLive := l.rules[r]
|
|
|
|
if isLive {
|
|
|
|
delete(l.rules, r)
|
|
|
|
}
|
|
|
|
return isLive
|
|
|
|
}
|