• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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