xref: /aosp_15_r20/build/blueprint/live_tracker.go (revision 1fa6dee971e1612fa5cc0aa5ca2d35a22e2c34a3)
1*1fa6dee9SAndroid Build Coastguard Worker// Copyright 2014 Google Inc. All rights reserved.
2*1fa6dee9SAndroid Build Coastguard Worker//
3*1fa6dee9SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*1fa6dee9SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*1fa6dee9SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*1fa6dee9SAndroid Build Coastguard Worker//
7*1fa6dee9SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*1fa6dee9SAndroid Build Coastguard Worker//
9*1fa6dee9SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*1fa6dee9SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*1fa6dee9SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*1fa6dee9SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*1fa6dee9SAndroid Build Coastguard Worker// limitations under the License.
14*1fa6dee9SAndroid Build Coastguard Worker
15*1fa6dee9SAndroid Build Coastguard Workerpackage blueprint
16*1fa6dee9SAndroid Build Coastguard Worker
17*1fa6dee9SAndroid Build Coastguard Workerimport "sync"
18*1fa6dee9SAndroid Build Coastguard Worker
19*1fa6dee9SAndroid Build Coastguard Worker// A liveTracker tracks the values of live variables, rules, and pools.  An
20*1fa6dee9SAndroid Build Coastguard Worker// entity is made "live" when it is referenced directly or indirectly by a build
21*1fa6dee9SAndroid Build Coastguard Worker// definition.  When an entity is made live its value is computed based on the
22*1fa6dee9SAndroid Build Coastguard Worker// configuration.
23*1fa6dee9SAndroid Build Coastguard Workertype liveTracker struct {
24*1fa6dee9SAndroid Build Coastguard Worker	sync.Mutex
25*1fa6dee9SAndroid Build Coastguard Worker	config interface{} // Used to evaluate variable, rule, and pool values.
26*1fa6dee9SAndroid Build Coastguard Worker	ctx    *Context    // Used to evaluate globs
27*1fa6dee9SAndroid Build Coastguard Worker
28*1fa6dee9SAndroid Build Coastguard Worker	variables map[Variable]*ninjaString
29*1fa6dee9SAndroid Build Coastguard Worker	pools     map[Pool]*poolDef
30*1fa6dee9SAndroid Build Coastguard Worker	rules     map[Rule]*ruleDef
31*1fa6dee9SAndroid Build Coastguard Worker}
32*1fa6dee9SAndroid Build Coastguard Worker
33*1fa6dee9SAndroid Build Coastguard Workerfunc newLiveTracker(ctx *Context, config interface{}) *liveTracker {
34*1fa6dee9SAndroid Build Coastguard Worker	return &liveTracker{
35*1fa6dee9SAndroid Build Coastguard Worker		ctx:       ctx,
36*1fa6dee9SAndroid Build Coastguard Worker		config:    config,
37*1fa6dee9SAndroid Build Coastguard Worker		variables: make(map[Variable]*ninjaString),
38*1fa6dee9SAndroid Build Coastguard Worker		pools:     make(map[Pool]*poolDef),
39*1fa6dee9SAndroid Build Coastguard Worker		rules:     make(map[Rule]*ruleDef),
40*1fa6dee9SAndroid Build Coastguard Worker	}
41*1fa6dee9SAndroid Build Coastguard Worker}
42*1fa6dee9SAndroid Build Coastguard Worker
43*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) AddBuildDefDeps(def *buildDef) error {
44*1fa6dee9SAndroid Build Coastguard Worker	l.Lock()
45*1fa6dee9SAndroid Build Coastguard Worker	defer l.Unlock()
46*1fa6dee9SAndroid Build Coastguard Worker
47*1fa6dee9SAndroid Build Coastguard Worker	ruleDef, err := l.innerAddRule(def.Rule)
48*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
49*1fa6dee9SAndroid Build Coastguard Worker		return err
50*1fa6dee9SAndroid Build Coastguard Worker	}
51*1fa6dee9SAndroid Build Coastguard Worker	def.RuleDef = ruleDef
52*1fa6dee9SAndroid Build Coastguard Worker
53*1fa6dee9SAndroid Build Coastguard Worker	err = l.innerAddNinjaStringListDeps(def.Outputs)
54*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
55*1fa6dee9SAndroid Build Coastguard Worker		return err
56*1fa6dee9SAndroid Build Coastguard Worker	}
57*1fa6dee9SAndroid Build Coastguard Worker
58*1fa6dee9SAndroid Build Coastguard Worker	err = l.innerAddNinjaStringListDeps(def.Inputs)
59*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
60*1fa6dee9SAndroid Build Coastguard Worker		return err
61*1fa6dee9SAndroid Build Coastguard Worker	}
62*1fa6dee9SAndroid Build Coastguard Worker
63*1fa6dee9SAndroid Build Coastguard Worker	err = l.innerAddNinjaStringListDeps(def.Implicits)
64*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
65*1fa6dee9SAndroid Build Coastguard Worker		return err
66*1fa6dee9SAndroid Build Coastguard Worker	}
67*1fa6dee9SAndroid Build Coastguard Worker
68*1fa6dee9SAndroid Build Coastguard Worker	err = l.innerAddNinjaStringListDeps(def.OrderOnly)
69*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
70*1fa6dee9SAndroid Build Coastguard Worker		return err
71*1fa6dee9SAndroid Build Coastguard Worker	}
72*1fa6dee9SAndroid Build Coastguard Worker
73*1fa6dee9SAndroid Build Coastguard Worker	err = l.innerAddNinjaStringListDeps(def.Validations)
74*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
75*1fa6dee9SAndroid Build Coastguard Worker		return err
76*1fa6dee9SAndroid Build Coastguard Worker	}
77*1fa6dee9SAndroid Build Coastguard Worker
78*1fa6dee9SAndroid Build Coastguard Worker	for _, value := range def.Variables {
79*1fa6dee9SAndroid Build Coastguard Worker		err = l.innerAddNinjaStringDeps(value)
80*1fa6dee9SAndroid Build Coastguard Worker		if err != nil {
81*1fa6dee9SAndroid Build Coastguard Worker			return err
82*1fa6dee9SAndroid Build Coastguard Worker		}
83*1fa6dee9SAndroid Build Coastguard Worker	}
84*1fa6dee9SAndroid Build Coastguard Worker
85*1fa6dee9SAndroid Build Coastguard Worker	for _, value := range def.Args {
86*1fa6dee9SAndroid Build Coastguard Worker		err = l.innerAddNinjaStringDeps(value)
87*1fa6dee9SAndroid Build Coastguard Worker		if err != nil {
88*1fa6dee9SAndroid Build Coastguard Worker			return err
89*1fa6dee9SAndroid Build Coastguard Worker		}
90*1fa6dee9SAndroid Build Coastguard Worker	}
91*1fa6dee9SAndroid Build Coastguard Worker
92*1fa6dee9SAndroid Build Coastguard Worker	return nil
93*1fa6dee9SAndroid Build Coastguard Worker}
94*1fa6dee9SAndroid Build Coastguard Worker
95*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) addRule(r Rule) (def *ruleDef, err error) {
96*1fa6dee9SAndroid Build Coastguard Worker	l.Lock()
97*1fa6dee9SAndroid Build Coastguard Worker	defer l.Unlock()
98*1fa6dee9SAndroid Build Coastguard Worker	return l.innerAddRule(r)
99*1fa6dee9SAndroid Build Coastguard Worker}
100*1fa6dee9SAndroid Build Coastguard Worker
101*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) innerAddRule(r Rule) (def *ruleDef, err error) {
102*1fa6dee9SAndroid Build Coastguard Worker	def, ok := l.rules[r]
103*1fa6dee9SAndroid Build Coastguard Worker	if !ok {
104*1fa6dee9SAndroid Build Coastguard Worker		def, err = r.def(l.config)
105*1fa6dee9SAndroid Build Coastguard Worker		if err == errRuleIsBuiltin {
106*1fa6dee9SAndroid Build Coastguard Worker			// No need to do anything for built-in rules.
107*1fa6dee9SAndroid Build Coastguard Worker			return nil, nil
108*1fa6dee9SAndroid Build Coastguard Worker		}
109*1fa6dee9SAndroid Build Coastguard Worker		if err != nil {
110*1fa6dee9SAndroid Build Coastguard Worker			return nil, err
111*1fa6dee9SAndroid Build Coastguard Worker		}
112*1fa6dee9SAndroid Build Coastguard Worker
113*1fa6dee9SAndroid Build Coastguard Worker		if def.Pool != nil {
114*1fa6dee9SAndroid Build Coastguard Worker			err = l.innerAddPool(def.Pool)
115*1fa6dee9SAndroid Build Coastguard Worker			if err != nil {
116*1fa6dee9SAndroid Build Coastguard Worker				return nil, err
117*1fa6dee9SAndroid Build Coastguard Worker			}
118*1fa6dee9SAndroid Build Coastguard Worker		}
119*1fa6dee9SAndroid Build Coastguard Worker
120*1fa6dee9SAndroid Build Coastguard Worker		err = l.innerAddNinjaStringListDeps(def.CommandDeps)
121*1fa6dee9SAndroid Build Coastguard Worker		if err != nil {
122*1fa6dee9SAndroid Build Coastguard Worker			return nil, err
123*1fa6dee9SAndroid Build Coastguard Worker		}
124*1fa6dee9SAndroid Build Coastguard Worker
125*1fa6dee9SAndroid Build Coastguard Worker		err = l.innerAddNinjaStringListDeps(def.CommandOrderOnly)
126*1fa6dee9SAndroid Build Coastguard Worker		if err != nil {
127*1fa6dee9SAndroid Build Coastguard Worker			return nil, err
128*1fa6dee9SAndroid Build Coastguard Worker		}
129*1fa6dee9SAndroid Build Coastguard Worker
130*1fa6dee9SAndroid Build Coastguard Worker		for _, value := range def.Variables {
131*1fa6dee9SAndroid Build Coastguard Worker			err = l.innerAddNinjaStringDeps(value)
132*1fa6dee9SAndroid Build Coastguard Worker			if err != nil {
133*1fa6dee9SAndroid Build Coastguard Worker				return nil, err
134*1fa6dee9SAndroid Build Coastguard Worker			}
135*1fa6dee9SAndroid Build Coastguard Worker		}
136*1fa6dee9SAndroid Build Coastguard Worker
137*1fa6dee9SAndroid Build Coastguard Worker		l.rules[r] = def
138*1fa6dee9SAndroid Build Coastguard Worker	}
139*1fa6dee9SAndroid Build Coastguard Worker
140*1fa6dee9SAndroid Build Coastguard Worker	return
141*1fa6dee9SAndroid Build Coastguard Worker}
142*1fa6dee9SAndroid Build Coastguard Worker
143*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) addPool(p Pool) error {
144*1fa6dee9SAndroid Build Coastguard Worker	l.Lock()
145*1fa6dee9SAndroid Build Coastguard Worker	defer l.Unlock()
146*1fa6dee9SAndroid Build Coastguard Worker	return l.addPool(p)
147*1fa6dee9SAndroid Build Coastguard Worker}
148*1fa6dee9SAndroid Build Coastguard Worker
149*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) innerAddPool(p Pool) error {
150*1fa6dee9SAndroid Build Coastguard Worker	_, ok := l.pools[p]
151*1fa6dee9SAndroid Build Coastguard Worker	if !ok {
152*1fa6dee9SAndroid Build Coastguard Worker		def, err := p.def(l.config)
153*1fa6dee9SAndroid Build Coastguard Worker		if err == errPoolIsBuiltin {
154*1fa6dee9SAndroid Build Coastguard Worker			// No need to do anything for built-in rules.
155*1fa6dee9SAndroid Build Coastguard Worker			return nil
156*1fa6dee9SAndroid Build Coastguard Worker		}
157*1fa6dee9SAndroid Build Coastguard Worker		if err != nil {
158*1fa6dee9SAndroid Build Coastguard Worker			return err
159*1fa6dee9SAndroid Build Coastguard Worker		}
160*1fa6dee9SAndroid Build Coastguard Worker
161*1fa6dee9SAndroid Build Coastguard Worker		l.pools[p] = def
162*1fa6dee9SAndroid Build Coastguard Worker	}
163*1fa6dee9SAndroid Build Coastguard Worker
164*1fa6dee9SAndroid Build Coastguard Worker	return nil
165*1fa6dee9SAndroid Build Coastguard Worker}
166*1fa6dee9SAndroid Build Coastguard Worker
167*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) addVariable(v Variable) error {
168*1fa6dee9SAndroid Build Coastguard Worker	l.Lock()
169*1fa6dee9SAndroid Build Coastguard Worker	defer l.Unlock()
170*1fa6dee9SAndroid Build Coastguard Worker	return l.innerAddVariable(v)
171*1fa6dee9SAndroid Build Coastguard Worker}
172*1fa6dee9SAndroid Build Coastguard Worker
173*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) innerAddVariable(v Variable) error {
174*1fa6dee9SAndroid Build Coastguard Worker	_, ok := l.variables[v]
175*1fa6dee9SAndroid Build Coastguard Worker	if !ok {
176*1fa6dee9SAndroid Build Coastguard Worker		ctx := &variableFuncContext{l.ctx}
177*1fa6dee9SAndroid Build Coastguard Worker
178*1fa6dee9SAndroid Build Coastguard Worker		value, err := v.value(ctx, l.config)
179*1fa6dee9SAndroid Build Coastguard Worker		if err == errVariableIsArg {
180*1fa6dee9SAndroid Build Coastguard Worker			// This variable is a placeholder for an argument that can be passed
181*1fa6dee9SAndroid Build Coastguard Worker			// to a rule.  It has no value and thus doesn't reference any other
182*1fa6dee9SAndroid Build Coastguard Worker			// variables.
183*1fa6dee9SAndroid Build Coastguard Worker			return nil
184*1fa6dee9SAndroid Build Coastguard Worker		}
185*1fa6dee9SAndroid Build Coastguard Worker		if err != nil {
186*1fa6dee9SAndroid Build Coastguard Worker			return err
187*1fa6dee9SAndroid Build Coastguard Worker		}
188*1fa6dee9SAndroid Build Coastguard Worker
189*1fa6dee9SAndroid Build Coastguard Worker		l.variables[v] = value
190*1fa6dee9SAndroid Build Coastguard Worker
191*1fa6dee9SAndroid Build Coastguard Worker		err = l.innerAddNinjaStringDeps(value)
192*1fa6dee9SAndroid Build Coastguard Worker		if err != nil {
193*1fa6dee9SAndroid Build Coastguard Worker			return err
194*1fa6dee9SAndroid Build Coastguard Worker		}
195*1fa6dee9SAndroid Build Coastguard Worker	}
196*1fa6dee9SAndroid Build Coastguard Worker
197*1fa6dee9SAndroid Build Coastguard Worker	return nil
198*1fa6dee9SAndroid Build Coastguard Worker}
199*1fa6dee9SAndroid Build Coastguard Worker
200*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) addNinjaStringListDeps(list []*ninjaString) error {
201*1fa6dee9SAndroid Build Coastguard Worker	l.Lock()
202*1fa6dee9SAndroid Build Coastguard Worker	defer l.Unlock()
203*1fa6dee9SAndroid Build Coastguard Worker	return l.innerAddNinjaStringListDeps(list)
204*1fa6dee9SAndroid Build Coastguard Worker}
205*1fa6dee9SAndroid Build Coastguard Worker
206*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) innerAddNinjaStringListDeps(list []*ninjaString) error {
207*1fa6dee9SAndroid Build Coastguard Worker	for _, str := range list {
208*1fa6dee9SAndroid Build Coastguard Worker		err := l.innerAddNinjaStringDeps(str)
209*1fa6dee9SAndroid Build Coastguard Worker		if err != nil {
210*1fa6dee9SAndroid Build Coastguard Worker			return err
211*1fa6dee9SAndroid Build Coastguard Worker		}
212*1fa6dee9SAndroid Build Coastguard Worker	}
213*1fa6dee9SAndroid Build Coastguard Worker	return nil
214*1fa6dee9SAndroid Build Coastguard Worker}
215*1fa6dee9SAndroid Build Coastguard Worker
216*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) addNinjaStringDeps(str *ninjaString) error {
217*1fa6dee9SAndroid Build Coastguard Worker	l.Lock()
218*1fa6dee9SAndroid Build Coastguard Worker	defer l.Unlock()
219*1fa6dee9SAndroid Build Coastguard Worker	return l.innerAddNinjaStringDeps(str)
220*1fa6dee9SAndroid Build Coastguard Worker}
221*1fa6dee9SAndroid Build Coastguard Worker
222*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) innerAddNinjaStringDeps(str *ninjaString) error {
223*1fa6dee9SAndroid Build Coastguard Worker	for _, v := range str.Variables() {
224*1fa6dee9SAndroid Build Coastguard Worker		err := l.innerAddVariable(v)
225*1fa6dee9SAndroid Build Coastguard Worker		if err != nil {
226*1fa6dee9SAndroid Build Coastguard Worker			return err
227*1fa6dee9SAndroid Build Coastguard Worker		}
228*1fa6dee9SAndroid Build Coastguard Worker	}
229*1fa6dee9SAndroid Build Coastguard Worker	return nil
230*1fa6dee9SAndroid Build Coastguard Worker}
231*1fa6dee9SAndroid Build Coastguard Worker
232*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) Eval(n *ninjaString) (string, error) {
233*1fa6dee9SAndroid Build Coastguard Worker	l.Lock()
234*1fa6dee9SAndroid Build Coastguard Worker	defer l.Unlock()
235*1fa6dee9SAndroid Build Coastguard Worker	return n.Eval(l.variables)
236*1fa6dee9SAndroid Build Coastguard Worker}
237*1fa6dee9SAndroid Build Coastguard Worker
238*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) RemoveVariableIfLive(v Variable) bool {
239*1fa6dee9SAndroid Build Coastguard Worker	l.Lock()
240*1fa6dee9SAndroid Build Coastguard Worker	defer l.Unlock()
241*1fa6dee9SAndroid Build Coastguard Worker
242*1fa6dee9SAndroid Build Coastguard Worker	_, isLive := l.variables[v]
243*1fa6dee9SAndroid Build Coastguard Worker	if isLive {
244*1fa6dee9SAndroid Build Coastguard Worker		delete(l.variables, v)
245*1fa6dee9SAndroid Build Coastguard Worker	}
246*1fa6dee9SAndroid Build Coastguard Worker	return isLive
247*1fa6dee9SAndroid Build Coastguard Worker}
248*1fa6dee9SAndroid Build Coastguard Worker
249*1fa6dee9SAndroid Build Coastguard Workerfunc (l *liveTracker) RemoveRuleIfLive(r Rule) bool {
250*1fa6dee9SAndroid Build Coastguard Worker	l.Lock()
251*1fa6dee9SAndroid Build Coastguard Worker	defer l.Unlock()
252*1fa6dee9SAndroid Build Coastguard Worker
253*1fa6dee9SAndroid Build Coastguard Worker	_, isLive := l.rules[r]
254*1fa6dee9SAndroid Build Coastguard Worker	if isLive {
255*1fa6dee9SAndroid Build Coastguard Worker		delete(l.rules, r)
256*1fa6dee9SAndroid Build Coastguard Worker	}
257*1fa6dee9SAndroid Build Coastguard Worker	return isLive
258*1fa6dee9SAndroid Build Coastguard Worker}
259