xref: /aosp_15_r20/build/blueprint/module_ctx.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 (
18*1fa6dee9SAndroid Build Coastguard Worker	"errors"
19*1fa6dee9SAndroid Build Coastguard Worker	"fmt"
20*1fa6dee9SAndroid Build Coastguard Worker	"path/filepath"
21*1fa6dee9SAndroid Build Coastguard Worker	"sort"
22*1fa6dee9SAndroid Build Coastguard Worker	"strings"
23*1fa6dee9SAndroid Build Coastguard Worker	"sync"
24*1fa6dee9SAndroid Build Coastguard Worker	"text/scanner"
25*1fa6dee9SAndroid Build Coastguard Worker
26*1fa6dee9SAndroid Build Coastguard Worker	"github.com/google/blueprint/parser"
27*1fa6dee9SAndroid Build Coastguard Worker	"github.com/google/blueprint/pathtools"
28*1fa6dee9SAndroid Build Coastguard Worker	"github.com/google/blueprint/proptools"
29*1fa6dee9SAndroid Build Coastguard Worker)
30*1fa6dee9SAndroid Build Coastguard Worker
31*1fa6dee9SAndroid Build Coastguard Worker// A Module handles generating all of the Ninja build actions needed to build a
32*1fa6dee9SAndroid Build Coastguard Worker// single module based on properties defined in a Blueprints file.  Module
33*1fa6dee9SAndroid Build Coastguard Worker// objects are initially created during the parse phase of a Context using one
34*1fa6dee9SAndroid Build Coastguard Worker// of the registered module types (and the associated ModuleFactory function).
35*1fa6dee9SAndroid Build Coastguard Worker// The Module's properties struct is automatically filled in with the property
36*1fa6dee9SAndroid Build Coastguard Worker// values specified in the Blueprints file (see Context.RegisterModuleType for more
37*1fa6dee9SAndroid Build Coastguard Worker// information on this).
38*1fa6dee9SAndroid Build Coastguard Worker//
39*1fa6dee9SAndroid Build Coastguard Worker// A Module can be split into multiple Modules by a Mutator.  All existing
40*1fa6dee9SAndroid Build Coastguard Worker// properties set on the module will be duplicated to the new Module, and then
41*1fa6dee9SAndroid Build Coastguard Worker// modified as necessary by the Mutator.
42*1fa6dee9SAndroid Build Coastguard Worker//
43*1fa6dee9SAndroid Build Coastguard Worker// The Module implementation can access the build configuration as well as any
44*1fa6dee9SAndroid Build Coastguard Worker// modules on which it depends (as defined by the "deps" property
45*1fa6dee9SAndroid Build Coastguard Worker// specified in the Blueprints file, dynamically added by implementing the
46*1fa6dee9SAndroid Build Coastguard Worker// (deprecated) DynamicDependerModule interface, or dynamically added by a
47*1fa6dee9SAndroid Build Coastguard Worker// BottomUpMutator) using the ModuleContext passed to GenerateBuildActions.
48*1fa6dee9SAndroid Build Coastguard Worker// This ModuleContext is also used to create Ninja build actions and to report
49*1fa6dee9SAndroid Build Coastguard Worker// errors to the user.
50*1fa6dee9SAndroid Build Coastguard Worker//
51*1fa6dee9SAndroid Build Coastguard Worker// In addition to implementing the GenerateBuildActions method, a Module should
52*1fa6dee9SAndroid Build Coastguard Worker// implement methods that provide dependant modules and singletons information
53*1fa6dee9SAndroid Build Coastguard Worker// they need to generate their build actions.  These methods will only be called
54*1fa6dee9SAndroid Build Coastguard Worker// after GenerateBuildActions is called because the Context calls
55*1fa6dee9SAndroid Build Coastguard Worker// GenerateBuildActions in dependency-order (and singletons are invoked after
56*1fa6dee9SAndroid Build Coastguard Worker// all the Modules).  The set of methods a Module supports will determine how
57*1fa6dee9SAndroid Build Coastguard Worker// dependant Modules interact with it.
58*1fa6dee9SAndroid Build Coastguard Worker//
59*1fa6dee9SAndroid Build Coastguard Worker// For example, consider a Module that is responsible for generating a library
60*1fa6dee9SAndroid Build Coastguard Worker// that other modules can link against.  The library Module might implement the
61*1fa6dee9SAndroid Build Coastguard Worker// following interface:
62*1fa6dee9SAndroid Build Coastguard Worker//
63*1fa6dee9SAndroid Build Coastguard Worker//	type LibraryProducer interface {
64*1fa6dee9SAndroid Build Coastguard Worker//	    LibraryFileName() string
65*1fa6dee9SAndroid Build Coastguard Worker//	}
66*1fa6dee9SAndroid Build Coastguard Worker//
67*1fa6dee9SAndroid Build Coastguard Worker//	func IsLibraryProducer(module blueprint.Module) {
68*1fa6dee9SAndroid Build Coastguard Worker//	    _, ok := module.(LibraryProducer)
69*1fa6dee9SAndroid Build Coastguard Worker//	    return ok
70*1fa6dee9SAndroid Build Coastguard Worker//	}
71*1fa6dee9SAndroid Build Coastguard Worker//
72*1fa6dee9SAndroid Build Coastguard Worker// A binary-producing Module that depends on the library Module could then do:
73*1fa6dee9SAndroid Build Coastguard Worker//
74*1fa6dee9SAndroid Build Coastguard Worker//	func (m *myBinaryModule) GenerateBuildActions(ctx blueprint.ModuleContext) {
75*1fa6dee9SAndroid Build Coastguard Worker//	    ...
76*1fa6dee9SAndroid Build Coastguard Worker//	    var libraryFiles []string
77*1fa6dee9SAndroid Build Coastguard Worker//	    ctx.VisitDepsDepthFirstIf(IsLibraryProducer,
78*1fa6dee9SAndroid Build Coastguard Worker//	        func(module blueprint.Module) {
79*1fa6dee9SAndroid Build Coastguard Worker//	            libProducer := module.(LibraryProducer)
80*1fa6dee9SAndroid Build Coastguard Worker//	            libraryFiles = append(libraryFiles, libProducer.LibraryFileName())
81*1fa6dee9SAndroid Build Coastguard Worker//	        })
82*1fa6dee9SAndroid Build Coastguard Worker//	    ...
83*1fa6dee9SAndroid Build Coastguard Worker//	}
84*1fa6dee9SAndroid Build Coastguard Worker//
85*1fa6dee9SAndroid Build Coastguard Worker// to build the list of library file names that should be included in its link
86*1fa6dee9SAndroid Build Coastguard Worker// command.
87*1fa6dee9SAndroid Build Coastguard Worker//
88*1fa6dee9SAndroid Build Coastguard Worker// GenerateBuildActions may be called from multiple threads.  It is guaranteed to
89*1fa6dee9SAndroid Build Coastguard Worker// be called after it has finished being called on all dependencies and on all
90*1fa6dee9SAndroid Build Coastguard Worker// variants of that appear earlier in the ModuleContext.VisitAllModuleVariants list.
91*1fa6dee9SAndroid Build Coastguard Worker// Any accesses to global variables or to Module objects that are not dependencies
92*1fa6dee9SAndroid Build Coastguard Worker// or variants of the current Module must be synchronized by the implementation of
93*1fa6dee9SAndroid Build Coastguard Worker// GenerateBuildActions.
94*1fa6dee9SAndroid Build Coastguard Workertype Module interface {
95*1fa6dee9SAndroid Build Coastguard Worker	// Name returns a string used to uniquely identify each module.  The return
96*1fa6dee9SAndroid Build Coastguard Worker	// value must be unique across all modules.  It is only called once, during
97*1fa6dee9SAndroid Build Coastguard Worker	// initial blueprint parsing.  To change the name later a mutator must call
98*1fa6dee9SAndroid Build Coastguard Worker	// MutatorContext.Rename
99*1fa6dee9SAndroid Build Coastguard Worker	//
100*1fa6dee9SAndroid Build Coastguard Worker	// In most cases, Name should return the contents of a "name:" property from
101*1fa6dee9SAndroid Build Coastguard Worker	// the blueprint file.  An embeddable SimpleName object can be used for this
102*1fa6dee9SAndroid Build Coastguard Worker	// case.
103*1fa6dee9SAndroid Build Coastguard Worker	Name() string
104*1fa6dee9SAndroid Build Coastguard Worker
105*1fa6dee9SAndroid Build Coastguard Worker	// GenerateBuildActions is called by the Context that created the Module
106*1fa6dee9SAndroid Build Coastguard Worker	// during its generate phase.  This call should generate all Ninja build
107*1fa6dee9SAndroid Build Coastguard Worker	// actions (rules, pools, and build statements) needed to build the module.
108*1fa6dee9SAndroid Build Coastguard Worker	GenerateBuildActions(ModuleContext)
109*1fa6dee9SAndroid Build Coastguard Worker}
110*1fa6dee9SAndroid Build Coastguard Worker
111*1fa6dee9SAndroid Build Coastguard Workertype ModuleProxy struct {
112*1fa6dee9SAndroid Build Coastguard Worker	module Module
113*1fa6dee9SAndroid Build Coastguard Worker}
114*1fa6dee9SAndroid Build Coastguard Worker
115*1fa6dee9SAndroid Build Coastguard Workerfunc CreateModuleProxy(module Module) ModuleProxy {
116*1fa6dee9SAndroid Build Coastguard Worker	return ModuleProxy{
117*1fa6dee9SAndroid Build Coastguard Worker		module: module,
118*1fa6dee9SAndroid Build Coastguard Worker	}
119*1fa6dee9SAndroid Build Coastguard Worker}
120*1fa6dee9SAndroid Build Coastguard Worker
121*1fa6dee9SAndroid Build Coastguard Workerfunc (m ModuleProxy) Name() string {
122*1fa6dee9SAndroid Build Coastguard Worker	return m.module.Name()
123*1fa6dee9SAndroid Build Coastguard Worker}
124*1fa6dee9SAndroid Build Coastguard Worker
125*1fa6dee9SAndroid Build Coastguard Workerfunc (m ModuleProxy) GenerateBuildActions(context ModuleContext) {
126*1fa6dee9SAndroid Build Coastguard Worker	m.module.GenerateBuildActions(context)
127*1fa6dee9SAndroid Build Coastguard Worker}
128*1fa6dee9SAndroid Build Coastguard Worker
129*1fa6dee9SAndroid Build Coastguard Worker// A DynamicDependerModule is a Module that may add dependencies that do not
130*1fa6dee9SAndroid Build Coastguard Worker// appear in its "deps" property.  Any Module that implements this interface
131*1fa6dee9SAndroid Build Coastguard Worker// will have its DynamicDependencies method called by the Context that created
132*1fa6dee9SAndroid Build Coastguard Worker// it during generate phase.
133*1fa6dee9SAndroid Build Coastguard Worker//
134*1fa6dee9SAndroid Build Coastguard Worker// Deprecated, use a BottomUpMutator instead
135*1fa6dee9SAndroid Build Coastguard Workertype DynamicDependerModule interface {
136*1fa6dee9SAndroid Build Coastguard Worker	Module
137*1fa6dee9SAndroid Build Coastguard Worker
138*1fa6dee9SAndroid Build Coastguard Worker	// DynamicDependencies is called by the Context that created the
139*1fa6dee9SAndroid Build Coastguard Worker	// DynamicDependerModule during its generate phase.  This call should return
140*1fa6dee9SAndroid Build Coastguard Worker	// the list of module names that the DynamicDependerModule depends on
141*1fa6dee9SAndroid Build Coastguard Worker	// dynamically.  Module names that already appear in the "deps" property may
142*1fa6dee9SAndroid Build Coastguard Worker	// but do not need to be included in the returned list.
143*1fa6dee9SAndroid Build Coastguard Worker	DynamicDependencies(DynamicDependerModuleContext) []string
144*1fa6dee9SAndroid Build Coastguard Worker}
145*1fa6dee9SAndroid Build Coastguard Worker
146*1fa6dee9SAndroid Build Coastguard Workertype EarlyModuleContext interface {
147*1fa6dee9SAndroid Build Coastguard Worker	// Module returns the current module as a Module.  It should rarely be necessary, as the module already has a
148*1fa6dee9SAndroid Build Coastguard Worker	// reference to itself.
149*1fa6dee9SAndroid Build Coastguard Worker	Module() Module
150*1fa6dee9SAndroid Build Coastguard Worker
151*1fa6dee9SAndroid Build Coastguard Worker	// ModuleName returns the name of the module.  This is generally the value that was returned by Module.Name() when
152*1fa6dee9SAndroid Build Coastguard Worker	// the module was created, but may have been modified by calls to BottomUpMutatorContext.Rename.
153*1fa6dee9SAndroid Build Coastguard Worker	ModuleName() string
154*1fa6dee9SAndroid Build Coastguard Worker
155*1fa6dee9SAndroid Build Coastguard Worker	// ModuleDir returns the path to the directory that contains the definition of the module.
156*1fa6dee9SAndroid Build Coastguard Worker	ModuleDir() string
157*1fa6dee9SAndroid Build Coastguard Worker
158*1fa6dee9SAndroid Build Coastguard Worker	// ModuleType returns the name of the module type that was used to create the module, as specified in
159*1fa6dee9SAndroid Build Coastguard Worker	// Context.RegisterModuleType().
160*1fa6dee9SAndroid Build Coastguard Worker	ModuleType() string
161*1fa6dee9SAndroid Build Coastguard Worker
162*1fa6dee9SAndroid Build Coastguard Worker	// ModuleTags returns the tags for this module that should be passed to
163*1fa6dee9SAndroid Build Coastguard Worker	// ninja for analysis. For example:
164*1fa6dee9SAndroid Build Coastguard Worker	// [
165*1fa6dee9SAndroid Build Coastguard Worker	//   "module_name": "libfoo",
166*1fa6dee9SAndroid Build Coastguard Worker	//   "module_type": "cc_library",
167*1fa6dee9SAndroid Build Coastguard Worker	// ]
168*1fa6dee9SAndroid Build Coastguard Worker	ModuleTags() map[string]string
169*1fa6dee9SAndroid Build Coastguard Worker
170*1fa6dee9SAndroid Build Coastguard Worker	// BlueprintsFile returns the name of the blueprint file that contains the definition of this
171*1fa6dee9SAndroid Build Coastguard Worker	// module.
172*1fa6dee9SAndroid Build Coastguard Worker	BlueprintsFile() string
173*1fa6dee9SAndroid Build Coastguard Worker
174*1fa6dee9SAndroid Build Coastguard Worker	// Config returns the config object that was passed to Context.PrepareBuildActions.
175*1fa6dee9SAndroid Build Coastguard Worker	Config() interface{}
176*1fa6dee9SAndroid Build Coastguard Worker
177*1fa6dee9SAndroid Build Coastguard Worker	// ContainsProperty returns true if the specified property name was set in the module definition.
178*1fa6dee9SAndroid Build Coastguard Worker	ContainsProperty(name string) bool
179*1fa6dee9SAndroid Build Coastguard Worker
180*1fa6dee9SAndroid Build Coastguard Worker	// Errorf reports an error at the specified position of the module definition file.
181*1fa6dee9SAndroid Build Coastguard Worker	Errorf(pos scanner.Position, fmt string, args ...interface{})
182*1fa6dee9SAndroid Build Coastguard Worker
183*1fa6dee9SAndroid Build Coastguard Worker	// ModuleErrorf reports an error at the line number of the module type in the module definition.
184*1fa6dee9SAndroid Build Coastguard Worker	ModuleErrorf(fmt string, args ...interface{})
185*1fa6dee9SAndroid Build Coastguard Worker
186*1fa6dee9SAndroid Build Coastguard Worker	// PropertyErrorf reports an error at the line number of a property in the module definition.
187*1fa6dee9SAndroid Build Coastguard Worker	PropertyErrorf(property, fmt string, args ...interface{})
188*1fa6dee9SAndroid Build Coastguard Worker
189*1fa6dee9SAndroid Build Coastguard Worker	// OtherModulePropertyErrorf reports an error at the line number of a property in the given module definition.
190*1fa6dee9SAndroid Build Coastguard Worker	OtherModulePropertyErrorf(logicModule Module, property string, format string, args ...interface{})
191*1fa6dee9SAndroid Build Coastguard Worker
192*1fa6dee9SAndroid Build Coastguard Worker	// Failed returns true if any errors have been reported.  In most cases the module can continue with generating
193*1fa6dee9SAndroid Build Coastguard Worker	// build rules after an error, allowing it to report additional errors in a single run, but in cases where the error
194*1fa6dee9SAndroid Build Coastguard Worker	// has prevented the module from creating necessary data it can return early when Failed returns true.
195*1fa6dee9SAndroid Build Coastguard Worker	Failed() bool
196*1fa6dee9SAndroid Build Coastguard Worker
197*1fa6dee9SAndroid Build Coastguard Worker	// GlobWithDeps returns a list of files and directories that match the
198*1fa6dee9SAndroid Build Coastguard Worker	// specified pattern but do not match any of the patterns in excludes.
199*1fa6dee9SAndroid Build Coastguard Worker	// Any directories will have a '/' suffix.  It also adds efficient
200*1fa6dee9SAndroid Build Coastguard Worker	// dependencies to rerun the primary builder whenever a file matching
201*1fa6dee9SAndroid Build Coastguard Worker	// the pattern as added or removed, without rerunning if a file that
202*1fa6dee9SAndroid Build Coastguard Worker	// does not match the pattern is added to a searched directory.
203*1fa6dee9SAndroid Build Coastguard Worker	GlobWithDeps(pattern string, excludes []string) ([]string, error)
204*1fa6dee9SAndroid Build Coastguard Worker
205*1fa6dee9SAndroid Build Coastguard Worker	// Fs returns a pathtools.Filesystem that can be used to interact with files.  Using the Filesystem interface allows
206*1fa6dee9SAndroid Build Coastguard Worker	// the module to be used in build system tests that run against a mock filesystem.
207*1fa6dee9SAndroid Build Coastguard Worker	Fs() pathtools.FileSystem
208*1fa6dee9SAndroid Build Coastguard Worker
209*1fa6dee9SAndroid Build Coastguard Worker	// AddNinjaFileDeps adds dependencies on the specified files to the rule that creates the ninja manifest.  The
210*1fa6dee9SAndroid Build Coastguard Worker	// primary builder will be rerun whenever the specified files are modified.
211*1fa6dee9SAndroid Build Coastguard Worker	AddNinjaFileDeps(deps ...string)
212*1fa6dee9SAndroid Build Coastguard Worker
213*1fa6dee9SAndroid Build Coastguard Worker	moduleInfo() *moduleInfo
214*1fa6dee9SAndroid Build Coastguard Worker
215*1fa6dee9SAndroid Build Coastguard Worker	error(err error)
216*1fa6dee9SAndroid Build Coastguard Worker
217*1fa6dee9SAndroid Build Coastguard Worker	// Namespace returns the Namespace object provided by the NameInterface set by Context.SetNameInterface, or the
218*1fa6dee9SAndroid Build Coastguard Worker	// default SimpleNameInterface if Context.SetNameInterface was not called.
219*1fa6dee9SAndroid Build Coastguard Worker	Namespace() Namespace
220*1fa6dee9SAndroid Build Coastguard Worker
221*1fa6dee9SAndroid Build Coastguard Worker	// ModuleFactories returns a map of all of the global ModuleFactories by name.
222*1fa6dee9SAndroid Build Coastguard Worker	ModuleFactories() map[string]ModuleFactory
223*1fa6dee9SAndroid Build Coastguard Worker
224*1fa6dee9SAndroid Build Coastguard Worker	// HasMutatorFinished returns true if the given mutator has finished running.
225*1fa6dee9SAndroid Build Coastguard Worker	// It will panic if given an invalid mutator name.
226*1fa6dee9SAndroid Build Coastguard Worker	HasMutatorFinished(mutatorName string) bool
227*1fa6dee9SAndroid Build Coastguard Worker}
228*1fa6dee9SAndroid Build Coastguard Worker
229*1fa6dee9SAndroid Build Coastguard Workertype BaseModuleContext interface {
230*1fa6dee9SAndroid Build Coastguard Worker	EarlyModuleContext
231*1fa6dee9SAndroid Build Coastguard Worker
232*1fa6dee9SAndroid Build Coastguard Worker	// GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
233*1fa6dee9SAndroid Build Coastguard Worker	// none exists.  It panics if the dependency does not have the specified tag.
234*1fa6dee9SAndroid Build Coastguard Worker	GetDirectDepWithTag(name string, tag DependencyTag) Module
235*1fa6dee9SAndroid Build Coastguard Worker
236*1fa6dee9SAndroid Build Coastguard Worker	// GetDirectDep returns the Module and DependencyTag for the  direct dependency with the specified
237*1fa6dee9SAndroid Build Coastguard Worker	// name, or nil if none exists.  If there are multiple dependencies on the same module it returns
238*1fa6dee9SAndroid Build Coastguard Worker	// the first DependencyTag.
239*1fa6dee9SAndroid Build Coastguard Worker	GetDirectDep(name string) (Module, DependencyTag)
240*1fa6dee9SAndroid Build Coastguard Worker
241*1fa6dee9SAndroid Build Coastguard Worker	// VisitDirectDeps calls visit for each direct dependency.  If there are multiple direct dependencies on the same
242*1fa6dee9SAndroid Build Coastguard Worker	// module visit will be called multiple times on that module and OtherModuleDependencyTag will return a different
243*1fa6dee9SAndroid Build Coastguard Worker	// tag for each.
244*1fa6dee9SAndroid Build Coastguard Worker	//
245*1fa6dee9SAndroid Build Coastguard Worker	// The Module passed to the visit function should not be retained outside of the visit function, it may be
246*1fa6dee9SAndroid Build Coastguard Worker	// invalidated by future mutators.
247*1fa6dee9SAndroid Build Coastguard Worker	VisitDirectDeps(visit func(Module))
248*1fa6dee9SAndroid Build Coastguard Worker
249*1fa6dee9SAndroid Build Coastguard Worker	VisitDirectDepsProxy(visit func(proxy ModuleProxy))
250*1fa6dee9SAndroid Build Coastguard Worker
251*1fa6dee9SAndroid Build Coastguard Worker	// VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit.  If there are
252*1fa6dee9SAndroid Build Coastguard Worker	// multiple direct dependencies on the same module pred and visit will be called multiple times on that module and
253*1fa6dee9SAndroid Build Coastguard Worker	// OtherModuleDependencyTag will return a different tag for each.
254*1fa6dee9SAndroid Build Coastguard Worker	//
255*1fa6dee9SAndroid Build Coastguard Worker	// The Module passed to the visit function should not be retained outside of the visit function, it may be
256*1fa6dee9SAndroid Build Coastguard Worker	// invalidated by future mutators.
257*1fa6dee9SAndroid Build Coastguard Worker	VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
258*1fa6dee9SAndroid Build Coastguard Worker
259*1fa6dee9SAndroid Build Coastguard Worker	// VisitDepsDepthFirst calls visit for each transitive dependency, traversing the dependency tree in depth first
260*1fa6dee9SAndroid Build Coastguard Worker	// order. visit will only be called once for any given module, even if there are multiple paths through the
261*1fa6dee9SAndroid Build Coastguard Worker	// dependency tree to the module or multiple direct dependencies with different tags.  OtherModuleDependencyTag will
262*1fa6dee9SAndroid Build Coastguard Worker	// return the tag for the first path found to the module.
263*1fa6dee9SAndroid Build Coastguard Worker	//
264*1fa6dee9SAndroid Build Coastguard Worker	// The Module passed to the visit function should not be retained outside of the visit function, it may be
265*1fa6dee9SAndroid Build Coastguard Worker	// invalidated by future mutators.
266*1fa6dee9SAndroid Build Coastguard Worker	VisitDepsDepthFirst(visit func(Module))
267*1fa6dee9SAndroid Build Coastguard Worker
268*1fa6dee9SAndroid Build Coastguard Worker	// VisitDepsDepthFirstIf calls pred for each transitive dependency, and if pred returns true calls visit, traversing
269*1fa6dee9SAndroid Build Coastguard Worker	// the dependency tree in depth first order.  visit will only be called once for any given module, even if there are
270*1fa6dee9SAndroid Build Coastguard Worker	// multiple paths through the dependency tree to the module or multiple direct dependencies with different tags.
271*1fa6dee9SAndroid Build Coastguard Worker	// OtherModuleDependencyTag will return the tag for the first path found to the module.  The return value of pred
272*1fa6dee9SAndroid Build Coastguard Worker	// does not affect which branches of the tree are traversed.
273*1fa6dee9SAndroid Build Coastguard Worker	//
274*1fa6dee9SAndroid Build Coastguard Worker	// The Module passed to the visit function should not be retained outside of the visit function, it may be
275*1fa6dee9SAndroid Build Coastguard Worker	// invalidated by future mutators.
276*1fa6dee9SAndroid Build Coastguard Worker	VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
277*1fa6dee9SAndroid Build Coastguard Worker
278*1fa6dee9SAndroid Build Coastguard Worker	// WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order.  visit may
279*1fa6dee9SAndroid Build Coastguard Worker	// be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
280*1fa6dee9SAndroid Build Coastguard Worker	// child and parent with different tags.  OtherModuleDependencyTag will return the tag for the currently visited
281*1fa6dee9SAndroid Build Coastguard Worker	// (child, parent) pair.  If visit returns false WalkDeps will not continue recursing down to child.
282*1fa6dee9SAndroid Build Coastguard Worker	//
283*1fa6dee9SAndroid Build Coastguard Worker	// The Modules passed to the visit function should not be retained outside of the visit function, they may be
284*1fa6dee9SAndroid Build Coastguard Worker	// invalidated by future mutators.
285*1fa6dee9SAndroid Build Coastguard Worker	WalkDeps(visit func(Module, Module) bool)
286*1fa6dee9SAndroid Build Coastguard Worker
287*1fa6dee9SAndroid Build Coastguard Worker	WalkDepsProxy(visit func(ModuleProxy, ModuleProxy) bool)
288*1fa6dee9SAndroid Build Coastguard Worker
289*1fa6dee9SAndroid Build Coastguard Worker	// PrimaryModule returns the first variant of the current module.  Variants of a module are always visited in
290*1fa6dee9SAndroid Build Coastguard Worker	// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
291*1fa6dee9SAndroid Build Coastguard Worker	// Module returned by PrimaryModule without data races.  This can be used to perform singleton actions that are
292*1fa6dee9SAndroid Build Coastguard Worker	// only done once for all variants of a module.
293*1fa6dee9SAndroid Build Coastguard Worker	PrimaryModule() Module
294*1fa6dee9SAndroid Build Coastguard Worker
295*1fa6dee9SAndroid Build Coastguard Worker	// FinalModule returns the last variant of the current module.  Variants of a module are always visited in
296*1fa6dee9SAndroid Build Coastguard Worker	// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
297*1fa6dee9SAndroid Build Coastguard Worker	// variants using VisitAllModuleVariants if the current module == FinalModule().  This can be used to perform
298*1fa6dee9SAndroid Build Coastguard Worker	// singleton actions that are only done once for all variants of a module.
299*1fa6dee9SAndroid Build Coastguard Worker	FinalModule() Module
300*1fa6dee9SAndroid Build Coastguard Worker
301*1fa6dee9SAndroid Build Coastguard Worker	// IsFinalModule returns if the current module is the last variant.  Variants of a module are always visited in
302*1fa6dee9SAndroid Build Coastguard Worker	// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
303*1fa6dee9SAndroid Build Coastguard Worker	// variants using VisitAllModuleVariants if the current module is the last one.  This can be used to perform
304*1fa6dee9SAndroid Build Coastguard Worker	// singleton actions that are only done once for all variants of a module.
305*1fa6dee9SAndroid Build Coastguard Worker	IsFinalModule(module Module) bool
306*1fa6dee9SAndroid Build Coastguard Worker
307*1fa6dee9SAndroid Build Coastguard Worker	// VisitAllModuleVariants calls visit for each variant of the current module.  Variants of a module are always
308*1fa6dee9SAndroid Build Coastguard Worker	// visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
309*1fa6dee9SAndroid Build Coastguard Worker	// from all variants if the current module is the last one.  Otherwise, care must be taken to not access any
310*1fa6dee9SAndroid Build Coastguard Worker	// data modified by the current mutator.
311*1fa6dee9SAndroid Build Coastguard Worker	VisitAllModuleVariants(visit func(Module))
312*1fa6dee9SAndroid Build Coastguard Worker
313*1fa6dee9SAndroid Build Coastguard Worker	// VisitAllModuleVariantProxies calls visit for each variant of the current module.  Variants of a module are always
314*1fa6dee9SAndroid Build Coastguard Worker	// visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
315*1fa6dee9SAndroid Build Coastguard Worker	// from all variants if the current module is the last one.  Otherwise, care must be taken to not access any
316*1fa6dee9SAndroid Build Coastguard Worker	// data modified by the current mutator.
317*1fa6dee9SAndroid Build Coastguard Worker	VisitAllModuleVariantProxies(visit func(proxy ModuleProxy))
318*1fa6dee9SAndroid Build Coastguard Worker
319*1fa6dee9SAndroid Build Coastguard Worker	// OtherModuleName returns the name of another Module.  See BaseModuleContext.ModuleName for more information.
320*1fa6dee9SAndroid Build Coastguard Worker	// It is intended for use inside the visit functions of Visit* and WalkDeps.
321*1fa6dee9SAndroid Build Coastguard Worker	OtherModuleName(m Module) string
322*1fa6dee9SAndroid Build Coastguard Worker
323*1fa6dee9SAndroid Build Coastguard Worker	// OtherModuleDir returns the directory of another Module.  See BaseModuleContext.ModuleDir for more information.
324*1fa6dee9SAndroid Build Coastguard Worker	// It is intended for use inside the visit functions of Visit* and WalkDeps.
325*1fa6dee9SAndroid Build Coastguard Worker	OtherModuleDir(m Module) string
326*1fa6dee9SAndroid Build Coastguard Worker
327*1fa6dee9SAndroid Build Coastguard Worker	// OtherModuleType returns the type of another Module.  See BaseModuleContext.ModuleType for more information.
328*1fa6dee9SAndroid Build Coastguard Worker	// It is intended for use inside the visit functions of Visit* and WalkDeps.
329*1fa6dee9SAndroid Build Coastguard Worker	OtherModuleType(m Module) string
330*1fa6dee9SAndroid Build Coastguard Worker
331*1fa6dee9SAndroid Build Coastguard Worker	// OtherModuleErrorf reports an error on another Module.  See BaseModuleContext.ModuleErrorf for more information.
332*1fa6dee9SAndroid Build Coastguard Worker	// It is intended for use inside the visit functions of Visit* and WalkDeps.
333*1fa6dee9SAndroid Build Coastguard Worker	OtherModuleErrorf(m Module, fmt string, args ...interface{})
334*1fa6dee9SAndroid Build Coastguard Worker
335*1fa6dee9SAndroid Build Coastguard Worker	// OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency
336*1fa6dee9SAndroid Build Coastguard Worker	// on the module.  When called inside a Visit* method with current module being visited, and there are multiple
337*1fa6dee9SAndroid Build Coastguard Worker	// dependencies on the module being visited, it returns the dependency tag used for the current dependency.
338*1fa6dee9SAndroid Build Coastguard Worker	OtherModuleDependencyTag(m Module) DependencyTag
339*1fa6dee9SAndroid Build Coastguard Worker
340*1fa6dee9SAndroid Build Coastguard Worker	// OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface
341*1fa6dee9SAndroid Build Coastguard Worker	// passed to Context.SetNameInterface, or SimpleNameInterface if it was not called.
342*1fa6dee9SAndroid Build Coastguard Worker	OtherModuleExists(name string) bool
343*1fa6dee9SAndroid Build Coastguard Worker
344*1fa6dee9SAndroid Build Coastguard Worker	// ModuleFromName returns (module, true) if a module exists by the given name and same context namespace,
345*1fa6dee9SAndroid Build Coastguard Worker	// or (nil, false) if it does not exist. It panics if there is either more than one
346*1fa6dee9SAndroid Build Coastguard Worker	// module of the given name, or if the given name refers to an alias instead of a module.
347*1fa6dee9SAndroid Build Coastguard Worker	// There are no guarantees about which variant of the module will be returned.
348*1fa6dee9SAndroid Build Coastguard Worker	// Prefer retrieving the module using GetDirectDep or a visit function, when possible, as
349*1fa6dee9SAndroid Build Coastguard Worker	// this will guarantee the appropriate module-variant dependency is returned.
350*1fa6dee9SAndroid Build Coastguard Worker	//
351*1fa6dee9SAndroid Build Coastguard Worker	// WARNING: This should _only_ be used within the context of bp2build, where variants and
352*1fa6dee9SAndroid Build Coastguard Worker	// dependencies are not created.
353*1fa6dee9SAndroid Build Coastguard Worker	ModuleFromName(name string) (Module, bool)
354*1fa6dee9SAndroid Build Coastguard Worker
355*1fa6dee9SAndroid Build Coastguard Worker	// OtherModuleDependencyVariantExists returns true if a module with the
356*1fa6dee9SAndroid Build Coastguard Worker	// specified name and variant exists. The variant must match the given
357*1fa6dee9SAndroid Build Coastguard Worker	// variations. It must also match all the non-local variations of the current
358*1fa6dee9SAndroid Build Coastguard Worker	// module. In other words, it checks for the module that AddVariationDependencies
359*1fa6dee9SAndroid Build Coastguard Worker	// would add a dependency on with the same arguments.
360*1fa6dee9SAndroid Build Coastguard Worker	OtherModuleDependencyVariantExists(variations []Variation, name string) bool
361*1fa6dee9SAndroid Build Coastguard Worker
362*1fa6dee9SAndroid Build Coastguard Worker	// OtherModuleFarDependencyVariantExists returns true if a module with the
363*1fa6dee9SAndroid Build Coastguard Worker	// specified name and variant exists. The variant must match the given
364*1fa6dee9SAndroid Build Coastguard Worker	// variations, but not the non-local variations of the current module. In
365*1fa6dee9SAndroid Build Coastguard Worker	// other words, it checks for the module that AddFarVariationDependencies
366*1fa6dee9SAndroid Build Coastguard Worker	// would add a dependency on with the same arguments.
367*1fa6dee9SAndroid Build Coastguard Worker	OtherModuleFarDependencyVariantExists(variations []Variation, name string) bool
368*1fa6dee9SAndroid Build Coastguard Worker
369*1fa6dee9SAndroid Build Coastguard Worker	// OtherModuleReverseDependencyVariantExists returns true if a module with the
370*1fa6dee9SAndroid Build Coastguard Worker	// specified name exists with the same variations as the current module. In
371*1fa6dee9SAndroid Build Coastguard Worker	// other words, it checks for the module that AddReverseDependency would add a
372*1fa6dee9SAndroid Build Coastguard Worker	// dependency on with the same argument.
373*1fa6dee9SAndroid Build Coastguard Worker	OtherModuleReverseDependencyVariantExists(name string) bool
374*1fa6dee9SAndroid Build Coastguard Worker
375*1fa6dee9SAndroid Build Coastguard Worker	// OtherModuleProvider returns the value for a provider for the given module.  If the value is
376*1fa6dee9SAndroid Build Coastguard Worker	// not set it returns nil and false.  The value returned may be a deep copy of the value originally
377*1fa6dee9SAndroid Build Coastguard Worker	// passed to SetProvider.
378*1fa6dee9SAndroid Build Coastguard Worker	//
379*1fa6dee9SAndroid Build Coastguard Worker	// This method shouldn't be used directly, prefer the type-safe android.OtherModuleProvider instead.
380*1fa6dee9SAndroid Build Coastguard Worker	OtherModuleProvider(m Module, provider AnyProviderKey) (any, bool)
381*1fa6dee9SAndroid Build Coastguard Worker
382*1fa6dee9SAndroid Build Coastguard Worker	// OtherModuleIsAutoGenerated returns true if a module has been generated from another module,
383*1fa6dee9SAndroid Build Coastguard Worker	// instead of being defined in Android.bp file
384*1fa6dee9SAndroid Build Coastguard Worker	OtherModuleIsAutoGenerated(m Module) bool
385*1fa6dee9SAndroid Build Coastguard Worker
386*1fa6dee9SAndroid Build Coastguard Worker	// Provider returns the value for a provider for the current module.  If the value is
387*1fa6dee9SAndroid Build Coastguard Worker	// not set it returns nil and false.  It panics if called before the appropriate
388*1fa6dee9SAndroid Build Coastguard Worker	// mutator or GenerateBuildActions pass for the provider.  The value returned may be a deep
389*1fa6dee9SAndroid Build Coastguard Worker	// copy of the value originally passed to SetProvider.
390*1fa6dee9SAndroid Build Coastguard Worker	//
391*1fa6dee9SAndroid Build Coastguard Worker	// This method shouldn't be used directly, prefer the type-safe android.ModuleProvider instead.
392*1fa6dee9SAndroid Build Coastguard Worker	Provider(provider AnyProviderKey) (any, bool)
393*1fa6dee9SAndroid Build Coastguard Worker
394*1fa6dee9SAndroid Build Coastguard Worker	// SetProvider sets the value for a provider for the current module.  It panics if not called
395*1fa6dee9SAndroid Build Coastguard Worker	// during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
396*1fa6dee9SAndroid Build Coastguard Worker	// is not of the appropriate type, or if the value has already been set.  The value should not
397*1fa6dee9SAndroid Build Coastguard Worker	// be modified after being passed to SetProvider.
398*1fa6dee9SAndroid Build Coastguard Worker	//
399*1fa6dee9SAndroid Build Coastguard Worker	// This method shouldn't be used directly, prefer the type-safe android.SetProvider instead.
400*1fa6dee9SAndroid Build Coastguard Worker	SetProvider(provider AnyProviderKey, value any)
401*1fa6dee9SAndroid Build Coastguard Worker
402*1fa6dee9SAndroid Build Coastguard Worker	EarlyGetMissingDependencies() []string
403*1fa6dee9SAndroid Build Coastguard Worker
404*1fa6dee9SAndroid Build Coastguard Worker	EqualModules(m1, m2 Module) bool
405*1fa6dee9SAndroid Build Coastguard Worker
406*1fa6dee9SAndroid Build Coastguard Worker	base() *baseModuleContext
407*1fa6dee9SAndroid Build Coastguard Worker}
408*1fa6dee9SAndroid Build Coastguard Worker
409*1fa6dee9SAndroid Build Coastguard Workertype DynamicDependerModuleContext BottomUpMutatorContext
410*1fa6dee9SAndroid Build Coastguard Worker
411*1fa6dee9SAndroid Build Coastguard Workertype ModuleContext interface {
412*1fa6dee9SAndroid Build Coastguard Worker	BaseModuleContext
413*1fa6dee9SAndroid Build Coastguard Worker
414*1fa6dee9SAndroid Build Coastguard Worker	// ModuleSubDir returns a unique name for the current variant of a module that can be used as part of the path
415*1fa6dee9SAndroid Build Coastguard Worker	// to ensure that each variant of a module gets its own intermediates directory to write to.
416*1fa6dee9SAndroid Build Coastguard Worker	ModuleSubDir() string
417*1fa6dee9SAndroid Build Coastguard Worker
418*1fa6dee9SAndroid Build Coastguard Worker	ModuleCacheKey() string
419*1fa6dee9SAndroid Build Coastguard Worker
420*1fa6dee9SAndroid Build Coastguard Worker	// Variable creates a new ninja variable scoped to the module.  It can be referenced by calls to Rule and Build
421*1fa6dee9SAndroid Build Coastguard Worker	// in the same module.
422*1fa6dee9SAndroid Build Coastguard Worker	Variable(pctx PackageContext, name, value string)
423*1fa6dee9SAndroid Build Coastguard Worker
424*1fa6dee9SAndroid Build Coastguard Worker	// Rule creates a new ninja rule scoped to the module.  It can be referenced by calls to Build in the same module.
425*1fa6dee9SAndroid Build Coastguard Worker	Rule(pctx PackageContext, name string, params RuleParams, argNames ...string) Rule
426*1fa6dee9SAndroid Build Coastguard Worker
427*1fa6dee9SAndroid Build Coastguard Worker	// Build creates a new ninja build statement.
428*1fa6dee9SAndroid Build Coastguard Worker	Build(pctx PackageContext, params BuildParams)
429*1fa6dee9SAndroid Build Coastguard Worker
430*1fa6dee9SAndroid Build Coastguard Worker	// GetMissingDependencies returns the list of dependencies that were passed to AddDependencies or related methods,
431*1fa6dee9SAndroid Build Coastguard Worker	// but do not exist.  It can be used with Context.SetAllowMissingDependencies to allow the primary builder to
432*1fa6dee9SAndroid Build Coastguard Worker	// handle missing dependencies on its own instead of having Blueprint treat them as an error.
433*1fa6dee9SAndroid Build Coastguard Worker	GetMissingDependencies() []string
434*1fa6dee9SAndroid Build Coastguard Worker}
435*1fa6dee9SAndroid Build Coastguard Worker
436*1fa6dee9SAndroid Build Coastguard Workervar _ BaseModuleContext = (*baseModuleContext)(nil)
437*1fa6dee9SAndroid Build Coastguard Worker
438*1fa6dee9SAndroid Build Coastguard Workertype baseModuleContext struct {
439*1fa6dee9SAndroid Build Coastguard Worker	context        *Context
440*1fa6dee9SAndroid Build Coastguard Worker	config         interface{}
441*1fa6dee9SAndroid Build Coastguard Worker	module         *moduleInfo
442*1fa6dee9SAndroid Build Coastguard Worker	errs           []error
443*1fa6dee9SAndroid Build Coastguard Worker	visitingParent *moduleInfo
444*1fa6dee9SAndroid Build Coastguard Worker	visitingDep    depInfo
445*1fa6dee9SAndroid Build Coastguard Worker	ninjaFileDeps  []string
446*1fa6dee9SAndroid Build Coastguard Worker}
447*1fa6dee9SAndroid Build Coastguard Worker
448*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) moduleInfo() *moduleInfo {
449*1fa6dee9SAndroid Build Coastguard Worker	return d.module
450*1fa6dee9SAndroid Build Coastguard Worker}
451*1fa6dee9SAndroid Build Coastguard Worker
452*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) Module() Module {
453*1fa6dee9SAndroid Build Coastguard Worker	return d.module.logicModule
454*1fa6dee9SAndroid Build Coastguard Worker}
455*1fa6dee9SAndroid Build Coastguard Worker
456*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) ModuleName() string {
457*1fa6dee9SAndroid Build Coastguard Worker	return d.module.Name()
458*1fa6dee9SAndroid Build Coastguard Worker}
459*1fa6dee9SAndroid Build Coastguard Worker
460*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) ModuleType() string {
461*1fa6dee9SAndroid Build Coastguard Worker	return d.module.typeName
462*1fa6dee9SAndroid Build Coastguard Worker}
463*1fa6dee9SAndroid Build Coastguard Worker
464*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) ModuleTags() map[string]string {
465*1fa6dee9SAndroid Build Coastguard Worker	return map[string]string{
466*1fa6dee9SAndroid Build Coastguard Worker		"module_name": d.ModuleName(),
467*1fa6dee9SAndroid Build Coastguard Worker		"module_type": d.ModuleType(),
468*1fa6dee9SAndroid Build Coastguard Worker	}
469*1fa6dee9SAndroid Build Coastguard Worker}
470*1fa6dee9SAndroid Build Coastguard Worker
471*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) ContainsProperty(name string) bool {
472*1fa6dee9SAndroid Build Coastguard Worker	_, ok := d.module.propertyPos[name]
473*1fa6dee9SAndroid Build Coastguard Worker	return ok
474*1fa6dee9SAndroid Build Coastguard Worker}
475*1fa6dee9SAndroid Build Coastguard Worker
476*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) ModuleDir() string {
477*1fa6dee9SAndroid Build Coastguard Worker	return filepath.Dir(d.module.relBlueprintsFile)
478*1fa6dee9SAndroid Build Coastguard Worker}
479*1fa6dee9SAndroid Build Coastguard Worker
480*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) BlueprintsFile() string {
481*1fa6dee9SAndroid Build Coastguard Worker	return d.module.relBlueprintsFile
482*1fa6dee9SAndroid Build Coastguard Worker}
483*1fa6dee9SAndroid Build Coastguard Worker
484*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) Config() interface{} {
485*1fa6dee9SAndroid Build Coastguard Worker	return d.config
486*1fa6dee9SAndroid Build Coastguard Worker}
487*1fa6dee9SAndroid Build Coastguard Worker
488*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) error(err error) {
489*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
490*1fa6dee9SAndroid Build Coastguard Worker		d.errs = append(d.errs, err)
491*1fa6dee9SAndroid Build Coastguard Worker	}
492*1fa6dee9SAndroid Build Coastguard Worker}
493*1fa6dee9SAndroid Build Coastguard Worker
494*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) Errorf(pos scanner.Position,
495*1fa6dee9SAndroid Build Coastguard Worker	format string, args ...interface{}) {
496*1fa6dee9SAndroid Build Coastguard Worker
497*1fa6dee9SAndroid Build Coastguard Worker	d.error(&BlueprintError{
498*1fa6dee9SAndroid Build Coastguard Worker		Err: fmt.Errorf(format, args...),
499*1fa6dee9SAndroid Build Coastguard Worker		Pos: pos,
500*1fa6dee9SAndroid Build Coastguard Worker	})
501*1fa6dee9SAndroid Build Coastguard Worker}
502*1fa6dee9SAndroid Build Coastguard Worker
503*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) ModuleErrorf(format string,
504*1fa6dee9SAndroid Build Coastguard Worker	args ...interface{}) {
505*1fa6dee9SAndroid Build Coastguard Worker
506*1fa6dee9SAndroid Build Coastguard Worker	d.error(d.context.moduleErrorf(d.module, format, args...))
507*1fa6dee9SAndroid Build Coastguard Worker}
508*1fa6dee9SAndroid Build Coastguard Worker
509*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) PropertyErrorf(property, format string,
510*1fa6dee9SAndroid Build Coastguard Worker	args ...interface{}) {
511*1fa6dee9SAndroid Build Coastguard Worker
512*1fa6dee9SAndroid Build Coastguard Worker	d.error(d.context.PropertyErrorf(d.module.logicModule, property, format, args...))
513*1fa6dee9SAndroid Build Coastguard Worker}
514*1fa6dee9SAndroid Build Coastguard Worker
515*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) OtherModulePropertyErrorf(logicModule Module, property string, format string,
516*1fa6dee9SAndroid Build Coastguard Worker	args ...interface{}) {
517*1fa6dee9SAndroid Build Coastguard Worker
518*1fa6dee9SAndroid Build Coastguard Worker	d.error(d.context.PropertyErrorf(logicModule, property, format, args...))
519*1fa6dee9SAndroid Build Coastguard Worker}
520*1fa6dee9SAndroid Build Coastguard Worker
521*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) Failed() bool {
522*1fa6dee9SAndroid Build Coastguard Worker	return len(d.errs) > 0
523*1fa6dee9SAndroid Build Coastguard Worker}
524*1fa6dee9SAndroid Build Coastguard Worker
525*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) GlobWithDeps(pattern string,
526*1fa6dee9SAndroid Build Coastguard Worker	excludes []string) ([]string, error) {
527*1fa6dee9SAndroid Build Coastguard Worker	return d.context.glob(pattern, excludes)
528*1fa6dee9SAndroid Build Coastguard Worker}
529*1fa6dee9SAndroid Build Coastguard Worker
530*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) Fs() pathtools.FileSystem {
531*1fa6dee9SAndroid Build Coastguard Worker	return d.context.fs
532*1fa6dee9SAndroid Build Coastguard Worker}
533*1fa6dee9SAndroid Build Coastguard Worker
534*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) Namespace() Namespace {
535*1fa6dee9SAndroid Build Coastguard Worker	return d.context.nameInterface.GetNamespace(newNamespaceContext(d.module))
536*1fa6dee9SAndroid Build Coastguard Worker}
537*1fa6dee9SAndroid Build Coastguard Worker
538*1fa6dee9SAndroid Build Coastguard Workerfunc (d *baseModuleContext) HasMutatorFinished(mutatorName string) bool {
539*1fa6dee9SAndroid Build Coastguard Worker	return d.context.HasMutatorFinished(mutatorName)
540*1fa6dee9SAndroid Build Coastguard Worker}
541*1fa6dee9SAndroid Build Coastguard Worker
542*1fa6dee9SAndroid Build Coastguard Workervar _ ModuleContext = (*moduleContext)(nil)
543*1fa6dee9SAndroid Build Coastguard Worker
544*1fa6dee9SAndroid Build Coastguard Workertype moduleContext struct {
545*1fa6dee9SAndroid Build Coastguard Worker	baseModuleContext
546*1fa6dee9SAndroid Build Coastguard Worker	scope              *localScope
547*1fa6dee9SAndroid Build Coastguard Worker	actionDefs         localBuildActions
548*1fa6dee9SAndroid Build Coastguard Worker	handledMissingDeps bool
549*1fa6dee9SAndroid Build Coastguard Worker}
550*1fa6dee9SAndroid Build Coastguard Worker
551*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) EqualModules(m1, m2 Module) bool {
552*1fa6dee9SAndroid Build Coastguard Worker	return getWrappedModule(m1) == getWrappedModule(m2)
553*1fa6dee9SAndroid Build Coastguard Worker}
554*1fa6dee9SAndroid Build Coastguard Worker
555*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleName(logicModule Module) string {
556*1fa6dee9SAndroid Build Coastguard Worker	module := m.context.moduleInfo[getWrappedModule(logicModule)]
557*1fa6dee9SAndroid Build Coastguard Worker	return module.Name()
558*1fa6dee9SAndroid Build Coastguard Worker}
559*1fa6dee9SAndroid Build Coastguard Worker
560*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleDir(logicModule Module) string {
561*1fa6dee9SAndroid Build Coastguard Worker	module := m.context.moduleInfo[getWrappedModule(logicModule)]
562*1fa6dee9SAndroid Build Coastguard Worker	return filepath.Dir(module.relBlueprintsFile)
563*1fa6dee9SAndroid Build Coastguard Worker}
564*1fa6dee9SAndroid Build Coastguard Worker
565*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleType(logicModule Module) string {
566*1fa6dee9SAndroid Build Coastguard Worker	module := m.context.moduleInfo[getWrappedModule(logicModule)]
567*1fa6dee9SAndroid Build Coastguard Worker	return module.typeName
568*1fa6dee9SAndroid Build Coastguard Worker}
569*1fa6dee9SAndroid Build Coastguard Worker
570*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleErrorf(logicModule Module, format string,
571*1fa6dee9SAndroid Build Coastguard Worker	args ...interface{}) {
572*1fa6dee9SAndroid Build Coastguard Worker
573*1fa6dee9SAndroid Build Coastguard Worker	module := m.context.moduleInfo[getWrappedModule(logicModule)]
574*1fa6dee9SAndroid Build Coastguard Worker	m.errs = append(m.errs, &ModuleError{
575*1fa6dee9SAndroid Build Coastguard Worker		BlueprintError: BlueprintError{
576*1fa6dee9SAndroid Build Coastguard Worker			Err: fmt.Errorf(format, args...),
577*1fa6dee9SAndroid Build Coastguard Worker			Pos: module.pos,
578*1fa6dee9SAndroid Build Coastguard Worker		},
579*1fa6dee9SAndroid Build Coastguard Worker		module: module,
580*1fa6dee9SAndroid Build Coastguard Worker	})
581*1fa6dee9SAndroid Build Coastguard Worker}
582*1fa6dee9SAndroid Build Coastguard Worker
583*1fa6dee9SAndroid Build Coastguard Workerfunc getWrappedModule(module Module) Module {
584*1fa6dee9SAndroid Build Coastguard Worker	if mp, isProxy := module.(ModuleProxy); isProxy {
585*1fa6dee9SAndroid Build Coastguard Worker		return mp.module
586*1fa6dee9SAndroid Build Coastguard Worker	}
587*1fa6dee9SAndroid Build Coastguard Worker	return module
588*1fa6dee9SAndroid Build Coastguard Worker}
589*1fa6dee9SAndroid Build Coastguard Worker
590*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleDependencyTag(logicModule Module) DependencyTag {
591*1fa6dee9SAndroid Build Coastguard Worker	// fast path for calling OtherModuleDependencyTag from inside VisitDirectDeps
592*1fa6dee9SAndroid Build Coastguard Worker	if m.visitingDep.module != nil && getWrappedModule(logicModule) == m.visitingDep.module.logicModule {
593*1fa6dee9SAndroid Build Coastguard Worker		return m.visitingDep.tag
594*1fa6dee9SAndroid Build Coastguard Worker	}
595*1fa6dee9SAndroid Build Coastguard Worker
596*1fa6dee9SAndroid Build Coastguard Worker	if m.visitingParent == nil {
597*1fa6dee9SAndroid Build Coastguard Worker		return nil
598*1fa6dee9SAndroid Build Coastguard Worker	}
599*1fa6dee9SAndroid Build Coastguard Worker
600*1fa6dee9SAndroid Build Coastguard Worker	for _, dep := range m.visitingParent.directDeps {
601*1fa6dee9SAndroid Build Coastguard Worker		if dep.module.logicModule == getWrappedModule(logicModule) {
602*1fa6dee9SAndroid Build Coastguard Worker			return dep.tag
603*1fa6dee9SAndroid Build Coastguard Worker		}
604*1fa6dee9SAndroid Build Coastguard Worker	}
605*1fa6dee9SAndroid Build Coastguard Worker
606*1fa6dee9SAndroid Build Coastguard Worker	return nil
607*1fa6dee9SAndroid Build Coastguard Worker}
608*1fa6dee9SAndroid Build Coastguard Worker
609*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) ModuleFromName(name string) (Module, bool) {
610*1fa6dee9SAndroid Build Coastguard Worker	moduleGroup, exists := m.context.nameInterface.ModuleFromName(name, m.module.namespace())
611*1fa6dee9SAndroid Build Coastguard Worker	if exists {
612*1fa6dee9SAndroid Build Coastguard Worker		if len(moduleGroup.modules) != 1 {
613*1fa6dee9SAndroid Build Coastguard Worker			panic(fmt.Errorf("Expected exactly one module named %q, but got %d", name, len(moduleGroup.modules)))
614*1fa6dee9SAndroid Build Coastguard Worker		}
615*1fa6dee9SAndroid Build Coastguard Worker		moduleInfo := moduleGroup.modules[0]
616*1fa6dee9SAndroid Build Coastguard Worker		if moduleInfo != nil {
617*1fa6dee9SAndroid Build Coastguard Worker			return moduleInfo.logicModule, true
618*1fa6dee9SAndroid Build Coastguard Worker		} else {
619*1fa6dee9SAndroid Build Coastguard Worker			panic(fmt.Errorf(`Expected actual module named %q, but group did not contain a module.
620*1fa6dee9SAndroid Build Coastguard Worker    There may instead be an alias by that name.`, name))
621*1fa6dee9SAndroid Build Coastguard Worker		}
622*1fa6dee9SAndroid Build Coastguard Worker	}
623*1fa6dee9SAndroid Build Coastguard Worker	return nil, exists
624*1fa6dee9SAndroid Build Coastguard Worker}
625*1fa6dee9SAndroid Build Coastguard Worker
626*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleExists(name string) bool {
627*1fa6dee9SAndroid Build Coastguard Worker	_, exists := m.context.nameInterface.ModuleFromName(name, m.module.namespace())
628*1fa6dee9SAndroid Build Coastguard Worker	return exists
629*1fa6dee9SAndroid Build Coastguard Worker}
630*1fa6dee9SAndroid Build Coastguard Worker
631*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleDependencyVariantExists(variations []Variation, name string) bool {
632*1fa6dee9SAndroid Build Coastguard Worker	possibleDeps := m.context.moduleGroupFromName(name, m.module.namespace())
633*1fa6dee9SAndroid Build Coastguard Worker	if possibleDeps == nil {
634*1fa6dee9SAndroid Build Coastguard Worker		return false
635*1fa6dee9SAndroid Build Coastguard Worker	}
636*1fa6dee9SAndroid Build Coastguard Worker	found, _, errs := m.context.findVariant(m.module, m.config, possibleDeps, variations, false, false)
637*1fa6dee9SAndroid Build Coastguard Worker	if errs != nil {
638*1fa6dee9SAndroid Build Coastguard Worker		panic(errors.Join(errs...))
639*1fa6dee9SAndroid Build Coastguard Worker	}
640*1fa6dee9SAndroid Build Coastguard Worker	return found != nil
641*1fa6dee9SAndroid Build Coastguard Worker}
642*1fa6dee9SAndroid Build Coastguard Worker
643*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []Variation, name string) bool {
644*1fa6dee9SAndroid Build Coastguard Worker	possibleDeps := m.context.moduleGroupFromName(name, m.module.namespace())
645*1fa6dee9SAndroid Build Coastguard Worker	if possibleDeps == nil {
646*1fa6dee9SAndroid Build Coastguard Worker		return false
647*1fa6dee9SAndroid Build Coastguard Worker	}
648*1fa6dee9SAndroid Build Coastguard Worker	found, _, errs := m.context.findVariant(m.module, m.config, possibleDeps, variations, true, false)
649*1fa6dee9SAndroid Build Coastguard Worker	if errs != nil {
650*1fa6dee9SAndroid Build Coastguard Worker		panic(errors.Join(errs...))
651*1fa6dee9SAndroid Build Coastguard Worker	}
652*1fa6dee9SAndroid Build Coastguard Worker	return found != nil
653*1fa6dee9SAndroid Build Coastguard Worker}
654*1fa6dee9SAndroid Build Coastguard Worker
655*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool {
656*1fa6dee9SAndroid Build Coastguard Worker	possibleDeps := m.context.moduleGroupFromName(name, m.module.namespace())
657*1fa6dee9SAndroid Build Coastguard Worker	if possibleDeps == nil {
658*1fa6dee9SAndroid Build Coastguard Worker		return false
659*1fa6dee9SAndroid Build Coastguard Worker	}
660*1fa6dee9SAndroid Build Coastguard Worker	found, _, errs := m.context.findVariant(m.module, m.config, possibleDeps, nil, false, true)
661*1fa6dee9SAndroid Build Coastguard Worker	if errs != nil {
662*1fa6dee9SAndroid Build Coastguard Worker		panic(errors.Join(errs...))
663*1fa6dee9SAndroid Build Coastguard Worker	}
664*1fa6dee9SAndroid Build Coastguard Worker	return found != nil
665*1fa6dee9SAndroid Build Coastguard Worker}
666*1fa6dee9SAndroid Build Coastguard Worker
667*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleProvider(logicModule Module, provider AnyProviderKey) (any, bool) {
668*1fa6dee9SAndroid Build Coastguard Worker	module := m.context.moduleInfo[getWrappedModule(logicModule)]
669*1fa6dee9SAndroid Build Coastguard Worker	return m.context.provider(module, provider.provider())
670*1fa6dee9SAndroid Build Coastguard Worker}
671*1fa6dee9SAndroid Build Coastguard Worker
672*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) Provider(provider AnyProviderKey) (any, bool) {
673*1fa6dee9SAndroid Build Coastguard Worker	return m.context.provider(m.module, provider.provider())
674*1fa6dee9SAndroid Build Coastguard Worker}
675*1fa6dee9SAndroid Build Coastguard Worker
676*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) SetProvider(provider AnyProviderKey, value interface{}) {
677*1fa6dee9SAndroid Build Coastguard Worker	m.context.setProvider(m.module, provider.provider(), value)
678*1fa6dee9SAndroid Build Coastguard Worker}
679*1fa6dee9SAndroid Build Coastguard Worker
680*1fa6dee9SAndroid Build Coastguard Workerfunc (m *moduleContext) cacheModuleBuildActions(key *BuildActionCacheKey) {
681*1fa6dee9SAndroid Build Coastguard Worker	var providers []CachedProvider
682*1fa6dee9SAndroid Build Coastguard Worker	for i, p := range m.module.providers {
683*1fa6dee9SAndroid Build Coastguard Worker		if p != nil && providerRegistry[i].mutator == "" {
684*1fa6dee9SAndroid Build Coastguard Worker			providers = append(providers,
685*1fa6dee9SAndroid Build Coastguard Worker				CachedProvider{
686*1fa6dee9SAndroid Build Coastguard Worker					Id:    providerRegistry[i],
687*1fa6dee9SAndroid Build Coastguard Worker					Value: &p,
688*1fa6dee9SAndroid Build Coastguard Worker				})
689*1fa6dee9SAndroid Build Coastguard Worker		}
690*1fa6dee9SAndroid Build Coastguard Worker	}
691*1fa6dee9SAndroid Build Coastguard Worker
692*1fa6dee9SAndroid Build Coastguard Worker	// These show up in the ninja file, so we need to cache these to ensure we
693*1fa6dee9SAndroid Build Coastguard Worker	// re-generate ninja file if they changed.
694*1fa6dee9SAndroid Build Coastguard Worker	relPos := m.module.pos
695*1fa6dee9SAndroid Build Coastguard Worker	relPos.Filename = m.module.relBlueprintsFile
696*1fa6dee9SAndroid Build Coastguard Worker	data := BuildActionCachedData{
697*1fa6dee9SAndroid Build Coastguard Worker		Providers: providers,
698*1fa6dee9SAndroid Build Coastguard Worker		Pos:       &relPos,
699*1fa6dee9SAndroid Build Coastguard Worker	}
700*1fa6dee9SAndroid Build Coastguard Worker
701*1fa6dee9SAndroid Build Coastguard Worker	m.context.updateBuildActionsCache(key, &data)
702*1fa6dee9SAndroid Build Coastguard Worker}
703*1fa6dee9SAndroid Build Coastguard Worker
704*1fa6dee9SAndroid Build Coastguard Workerfunc (m *moduleContext) restoreModuleBuildActions() (bool, *BuildActionCacheKey) {
705*1fa6dee9SAndroid Build Coastguard Worker	// Whether the incremental flag is set and the module type supports
706*1fa6dee9SAndroid Build Coastguard Worker	// incremental, this will decide weather to cache the data for the module.
707*1fa6dee9SAndroid Build Coastguard Worker	incrementalEnabled := false
708*1fa6dee9SAndroid Build Coastguard Worker	// Whether the above conditions are true and we can try to restore from
709*1fa6dee9SAndroid Build Coastguard Worker	// the cache for this module, i.e., no env, product variables and Soong
710*1fa6dee9SAndroid Build Coastguard Worker	// code changes.
711*1fa6dee9SAndroid Build Coastguard Worker	incrementalAnalysis := false
712*1fa6dee9SAndroid Build Coastguard Worker	var cacheKey *BuildActionCacheKey = nil
713*1fa6dee9SAndroid Build Coastguard Worker	if m.context.GetIncrementalEnabled() {
714*1fa6dee9SAndroid Build Coastguard Worker		if im, ok := m.module.logicModule.(Incremental); ok {
715*1fa6dee9SAndroid Build Coastguard Worker			incrementalEnabled = im.IncrementalSupported()
716*1fa6dee9SAndroid Build Coastguard Worker			incrementalAnalysis = m.context.GetIncrementalAnalysis() && incrementalEnabled
717*1fa6dee9SAndroid Build Coastguard Worker		}
718*1fa6dee9SAndroid Build Coastguard Worker	}
719*1fa6dee9SAndroid Build Coastguard Worker	if incrementalEnabled {
720*1fa6dee9SAndroid Build Coastguard Worker		hash, err := proptools.CalculateHash(m.module.properties)
721*1fa6dee9SAndroid Build Coastguard Worker		if err != nil {
722*1fa6dee9SAndroid Build Coastguard Worker			panic(newPanicErrorf(err, "failed to calculate properties hash"))
723*1fa6dee9SAndroid Build Coastguard Worker		}
724*1fa6dee9SAndroid Build Coastguard Worker		cacheInput := new(BuildActionCacheInput)
725*1fa6dee9SAndroid Build Coastguard Worker		cacheInput.PropertiesHash = hash
726*1fa6dee9SAndroid Build Coastguard Worker		m.VisitDirectDeps(func(module Module) {
727*1fa6dee9SAndroid Build Coastguard Worker			cacheInput.ProvidersHash =
728*1fa6dee9SAndroid Build Coastguard Worker				append(cacheInput.ProvidersHash, m.context.moduleInfo[module].providerInitialValueHashes)
729*1fa6dee9SAndroid Build Coastguard Worker		})
730*1fa6dee9SAndroid Build Coastguard Worker		hash, err = proptools.CalculateHash(&cacheInput)
731*1fa6dee9SAndroid Build Coastguard Worker		if err != nil {
732*1fa6dee9SAndroid Build Coastguard Worker			panic(newPanicErrorf(err, "failed to calculate cache input hash"))
733*1fa6dee9SAndroid Build Coastguard Worker		}
734*1fa6dee9SAndroid Build Coastguard Worker		cacheKey = &BuildActionCacheKey{
735*1fa6dee9SAndroid Build Coastguard Worker			Id:        m.ModuleCacheKey(),
736*1fa6dee9SAndroid Build Coastguard Worker			InputHash: hash,
737*1fa6dee9SAndroid Build Coastguard Worker		}
738*1fa6dee9SAndroid Build Coastguard Worker		m.module.buildActionCacheKey = cacheKey
739*1fa6dee9SAndroid Build Coastguard Worker	}
740*1fa6dee9SAndroid Build Coastguard Worker
741*1fa6dee9SAndroid Build Coastguard Worker	restored := false
742*1fa6dee9SAndroid Build Coastguard Worker	if incrementalAnalysis && cacheKey != nil {
743*1fa6dee9SAndroid Build Coastguard Worker		// Try to restore from cache if there is a cache hit
744*1fa6dee9SAndroid Build Coastguard Worker		data := m.context.getBuildActionsFromCache(cacheKey)
745*1fa6dee9SAndroid Build Coastguard Worker		relPos := m.module.pos
746*1fa6dee9SAndroid Build Coastguard Worker		relPos.Filename = m.module.relBlueprintsFile
747*1fa6dee9SAndroid Build Coastguard Worker		if data != nil && data.Pos != nil && relPos == *data.Pos {
748*1fa6dee9SAndroid Build Coastguard Worker			for _, provider := range data.Providers {
749*1fa6dee9SAndroid Build Coastguard Worker				m.context.setProvider(m.module, provider.Id, *provider.Value)
750*1fa6dee9SAndroid Build Coastguard Worker			}
751*1fa6dee9SAndroid Build Coastguard Worker			m.module.incrementalRestored = true
752*1fa6dee9SAndroid Build Coastguard Worker			m.module.orderOnlyStrings = data.OrderOnlyStrings
753*1fa6dee9SAndroid Build Coastguard Worker			restored = true
754*1fa6dee9SAndroid Build Coastguard Worker		}
755*1fa6dee9SAndroid Build Coastguard Worker	}
756*1fa6dee9SAndroid Build Coastguard Worker
757*1fa6dee9SAndroid Build Coastguard Worker	return restored, cacheKey
758*1fa6dee9SAndroid Build Coastguard Worker}
759*1fa6dee9SAndroid Build Coastguard Worker
760*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) GetDirectDep(name string) (Module, DependencyTag) {
761*1fa6dee9SAndroid Build Coastguard Worker	for _, dep := range m.module.directDeps {
762*1fa6dee9SAndroid Build Coastguard Worker		if dep.module.Name() == name {
763*1fa6dee9SAndroid Build Coastguard Worker			return dep.module.logicModule, dep.tag
764*1fa6dee9SAndroid Build Coastguard Worker		}
765*1fa6dee9SAndroid Build Coastguard Worker	}
766*1fa6dee9SAndroid Build Coastguard Worker
767*1fa6dee9SAndroid Build Coastguard Worker	return nil, nil
768*1fa6dee9SAndroid Build Coastguard Worker}
769*1fa6dee9SAndroid Build Coastguard Worker
770*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) GetDirectDepWithTag(name string, tag DependencyTag) Module {
771*1fa6dee9SAndroid Build Coastguard Worker	var deps []depInfo
772*1fa6dee9SAndroid Build Coastguard Worker	for _, dep := range m.module.directDeps {
773*1fa6dee9SAndroid Build Coastguard Worker		if dep.module.Name() == name {
774*1fa6dee9SAndroid Build Coastguard Worker			if dep.tag == tag {
775*1fa6dee9SAndroid Build Coastguard Worker				return dep.module.logicModule
776*1fa6dee9SAndroid Build Coastguard Worker			}
777*1fa6dee9SAndroid Build Coastguard Worker			deps = append(deps, dep)
778*1fa6dee9SAndroid Build Coastguard Worker		}
779*1fa6dee9SAndroid Build Coastguard Worker	}
780*1fa6dee9SAndroid Build Coastguard Worker
781*1fa6dee9SAndroid Build Coastguard Worker	if len(deps) != 0 {
782*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("Unable to find dependency %q with requested tag %#v. Found: %#v", deps[0].module, tag, deps))
783*1fa6dee9SAndroid Build Coastguard Worker	}
784*1fa6dee9SAndroid Build Coastguard Worker
785*1fa6dee9SAndroid Build Coastguard Worker	return nil
786*1fa6dee9SAndroid Build Coastguard Worker}
787*1fa6dee9SAndroid Build Coastguard Worker
788*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) VisitDirectDeps(visit func(Module)) {
789*1fa6dee9SAndroid Build Coastguard Worker	defer func() {
790*1fa6dee9SAndroid Build Coastguard Worker		if r := recover(); r != nil {
791*1fa6dee9SAndroid Build Coastguard Worker			panic(newPanicErrorf(r, "VisitDirectDeps(%s, %s) for dependency %s",
792*1fa6dee9SAndroid Build Coastguard Worker				m.module, funcName(visit), m.visitingDep.module))
793*1fa6dee9SAndroid Build Coastguard Worker		}
794*1fa6dee9SAndroid Build Coastguard Worker	}()
795*1fa6dee9SAndroid Build Coastguard Worker
796*1fa6dee9SAndroid Build Coastguard Worker	m.visitingParent = m.module
797*1fa6dee9SAndroid Build Coastguard Worker
798*1fa6dee9SAndroid Build Coastguard Worker	for _, dep := range m.module.directDeps {
799*1fa6dee9SAndroid Build Coastguard Worker		m.visitingDep = dep
800*1fa6dee9SAndroid Build Coastguard Worker		visit(dep.module.logicModule)
801*1fa6dee9SAndroid Build Coastguard Worker	}
802*1fa6dee9SAndroid Build Coastguard Worker
803*1fa6dee9SAndroid Build Coastguard Worker	m.visitingParent = nil
804*1fa6dee9SAndroid Build Coastguard Worker	m.visitingDep = depInfo{}
805*1fa6dee9SAndroid Build Coastguard Worker}
806*1fa6dee9SAndroid Build Coastguard Worker
807*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) VisitDirectDepsProxy(visit func(proxy ModuleProxy)) {
808*1fa6dee9SAndroid Build Coastguard Worker	defer func() {
809*1fa6dee9SAndroid Build Coastguard Worker		if r := recover(); r != nil {
810*1fa6dee9SAndroid Build Coastguard Worker			panic(newPanicErrorf(r, "VisitDirectDeps(%s, %s) for dependency %s",
811*1fa6dee9SAndroid Build Coastguard Worker				m.module, funcName(visit), m.visitingDep.module))
812*1fa6dee9SAndroid Build Coastguard Worker		}
813*1fa6dee9SAndroid Build Coastguard Worker	}()
814*1fa6dee9SAndroid Build Coastguard Worker
815*1fa6dee9SAndroid Build Coastguard Worker	m.visitingParent = m.module
816*1fa6dee9SAndroid Build Coastguard Worker
817*1fa6dee9SAndroid Build Coastguard Worker	for _, dep := range m.module.directDeps {
818*1fa6dee9SAndroid Build Coastguard Worker		m.visitingDep = dep
819*1fa6dee9SAndroid Build Coastguard Worker		visit(ModuleProxy{dep.module.logicModule})
820*1fa6dee9SAndroid Build Coastguard Worker	}
821*1fa6dee9SAndroid Build Coastguard Worker
822*1fa6dee9SAndroid Build Coastguard Worker	m.visitingParent = nil
823*1fa6dee9SAndroid Build Coastguard Worker	m.visitingDep = depInfo{}
824*1fa6dee9SAndroid Build Coastguard Worker}
825*1fa6dee9SAndroid Build Coastguard Worker
826*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
827*1fa6dee9SAndroid Build Coastguard Worker	defer func() {
828*1fa6dee9SAndroid Build Coastguard Worker		if r := recover(); r != nil {
829*1fa6dee9SAndroid Build Coastguard Worker			panic(newPanicErrorf(r, "VisitDirectDepsIf(%s, %s, %s) for dependency %s",
830*1fa6dee9SAndroid Build Coastguard Worker				m.module, funcName(pred), funcName(visit), m.visitingDep.module))
831*1fa6dee9SAndroid Build Coastguard Worker		}
832*1fa6dee9SAndroid Build Coastguard Worker	}()
833*1fa6dee9SAndroid Build Coastguard Worker
834*1fa6dee9SAndroid Build Coastguard Worker	m.visitingParent = m.module
835*1fa6dee9SAndroid Build Coastguard Worker
836*1fa6dee9SAndroid Build Coastguard Worker	for _, dep := range m.module.directDeps {
837*1fa6dee9SAndroid Build Coastguard Worker		m.visitingDep = dep
838*1fa6dee9SAndroid Build Coastguard Worker		if pred(dep.module.logicModule) {
839*1fa6dee9SAndroid Build Coastguard Worker			visit(dep.module.logicModule)
840*1fa6dee9SAndroid Build Coastguard Worker		}
841*1fa6dee9SAndroid Build Coastguard Worker	}
842*1fa6dee9SAndroid Build Coastguard Worker
843*1fa6dee9SAndroid Build Coastguard Worker	m.visitingParent = nil
844*1fa6dee9SAndroid Build Coastguard Worker	m.visitingDep = depInfo{}
845*1fa6dee9SAndroid Build Coastguard Worker}
846*1fa6dee9SAndroid Build Coastguard Worker
847*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
848*1fa6dee9SAndroid Build Coastguard Worker	defer func() {
849*1fa6dee9SAndroid Build Coastguard Worker		if r := recover(); r != nil {
850*1fa6dee9SAndroid Build Coastguard Worker			panic(newPanicErrorf(r, "VisitDepsDepthFirst(%s, %s) for dependency %s",
851*1fa6dee9SAndroid Build Coastguard Worker				m.module, funcName(visit), m.visitingDep.module))
852*1fa6dee9SAndroid Build Coastguard Worker		}
853*1fa6dee9SAndroid Build Coastguard Worker	}()
854*1fa6dee9SAndroid Build Coastguard Worker
855*1fa6dee9SAndroid Build Coastguard Worker	m.context.walkDeps(m.module, false, nil, func(dep depInfo, parent *moduleInfo) {
856*1fa6dee9SAndroid Build Coastguard Worker		m.visitingParent = parent
857*1fa6dee9SAndroid Build Coastguard Worker		m.visitingDep = dep
858*1fa6dee9SAndroid Build Coastguard Worker		visit(dep.module.logicModule)
859*1fa6dee9SAndroid Build Coastguard Worker	})
860*1fa6dee9SAndroid Build Coastguard Worker
861*1fa6dee9SAndroid Build Coastguard Worker	m.visitingParent = nil
862*1fa6dee9SAndroid Build Coastguard Worker	m.visitingDep = depInfo{}
863*1fa6dee9SAndroid Build Coastguard Worker}
864*1fa6dee9SAndroid Build Coastguard Worker
865*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool,
866*1fa6dee9SAndroid Build Coastguard Worker	visit func(Module)) {
867*1fa6dee9SAndroid Build Coastguard Worker
868*1fa6dee9SAndroid Build Coastguard Worker	defer func() {
869*1fa6dee9SAndroid Build Coastguard Worker		if r := recover(); r != nil {
870*1fa6dee9SAndroid Build Coastguard Worker			panic(newPanicErrorf(r, "VisitDepsDepthFirstIf(%s, %s, %s) for dependency %s",
871*1fa6dee9SAndroid Build Coastguard Worker				m.module, funcName(pred), funcName(visit), m.visitingDep.module))
872*1fa6dee9SAndroid Build Coastguard Worker		}
873*1fa6dee9SAndroid Build Coastguard Worker	}()
874*1fa6dee9SAndroid Build Coastguard Worker
875*1fa6dee9SAndroid Build Coastguard Worker	m.context.walkDeps(m.module, false, nil, func(dep depInfo, parent *moduleInfo) {
876*1fa6dee9SAndroid Build Coastguard Worker		if pred(dep.module.logicModule) {
877*1fa6dee9SAndroid Build Coastguard Worker			m.visitingParent = parent
878*1fa6dee9SAndroid Build Coastguard Worker			m.visitingDep = dep
879*1fa6dee9SAndroid Build Coastguard Worker			visit(dep.module.logicModule)
880*1fa6dee9SAndroid Build Coastguard Worker		}
881*1fa6dee9SAndroid Build Coastguard Worker	})
882*1fa6dee9SAndroid Build Coastguard Worker
883*1fa6dee9SAndroid Build Coastguard Worker	m.visitingParent = nil
884*1fa6dee9SAndroid Build Coastguard Worker	m.visitingDep = depInfo{}
885*1fa6dee9SAndroid Build Coastguard Worker}
886*1fa6dee9SAndroid Build Coastguard Worker
887*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) WalkDeps(visit func(child, parent Module) bool) {
888*1fa6dee9SAndroid Build Coastguard Worker	m.context.walkDeps(m.module, true, func(dep depInfo, parent *moduleInfo) bool {
889*1fa6dee9SAndroid Build Coastguard Worker		m.visitingParent = parent
890*1fa6dee9SAndroid Build Coastguard Worker		m.visitingDep = dep
891*1fa6dee9SAndroid Build Coastguard Worker		return visit(dep.module.logicModule, parent.logicModule)
892*1fa6dee9SAndroid Build Coastguard Worker	}, nil)
893*1fa6dee9SAndroid Build Coastguard Worker
894*1fa6dee9SAndroid Build Coastguard Worker	m.visitingParent = nil
895*1fa6dee9SAndroid Build Coastguard Worker	m.visitingDep = depInfo{}
896*1fa6dee9SAndroid Build Coastguard Worker}
897*1fa6dee9SAndroid Build Coastguard Worker
898*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) WalkDepsProxy(visit func(child, parent ModuleProxy) bool) {
899*1fa6dee9SAndroid Build Coastguard Worker	m.context.walkDeps(m.module, true, func(dep depInfo, parent *moduleInfo) bool {
900*1fa6dee9SAndroid Build Coastguard Worker		m.visitingParent = parent
901*1fa6dee9SAndroid Build Coastguard Worker		m.visitingDep = dep
902*1fa6dee9SAndroid Build Coastguard Worker		return visit(ModuleProxy{dep.module.logicModule}, ModuleProxy{parent.logicModule})
903*1fa6dee9SAndroid Build Coastguard Worker	}, nil)
904*1fa6dee9SAndroid Build Coastguard Worker
905*1fa6dee9SAndroid Build Coastguard Worker	m.visitingParent = nil
906*1fa6dee9SAndroid Build Coastguard Worker	m.visitingDep = depInfo{}
907*1fa6dee9SAndroid Build Coastguard Worker}
908*1fa6dee9SAndroid Build Coastguard Worker
909*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) PrimaryModule() Module {
910*1fa6dee9SAndroid Build Coastguard Worker	return m.module.group.modules.firstModule().logicModule
911*1fa6dee9SAndroid Build Coastguard Worker}
912*1fa6dee9SAndroid Build Coastguard Worker
913*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) FinalModule() Module {
914*1fa6dee9SAndroid Build Coastguard Worker	return m.module.group.modules.lastModule().logicModule
915*1fa6dee9SAndroid Build Coastguard Worker}
916*1fa6dee9SAndroid Build Coastguard Worker
917*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) IsFinalModule(module Module) bool {
918*1fa6dee9SAndroid Build Coastguard Worker	return m.module.group.modules.lastModule().logicModule == module
919*1fa6dee9SAndroid Build Coastguard Worker}
920*1fa6dee9SAndroid Build Coastguard Worker
921*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) VisitAllModuleVariants(visit func(Module)) {
922*1fa6dee9SAndroid Build Coastguard Worker	m.context.visitAllModuleVariants(m.module, visit)
923*1fa6dee9SAndroid Build Coastguard Worker}
924*1fa6dee9SAndroid Build Coastguard Worker
925*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) VisitAllModuleVariantProxies(visit func(proxy ModuleProxy)) {
926*1fa6dee9SAndroid Build Coastguard Worker	m.context.visitAllModuleVariants(m.module, visitProxyAdaptor(visit))
927*1fa6dee9SAndroid Build Coastguard Worker}
928*1fa6dee9SAndroid Build Coastguard Worker
929*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) AddNinjaFileDeps(deps ...string) {
930*1fa6dee9SAndroid Build Coastguard Worker	m.ninjaFileDeps = append(m.ninjaFileDeps, deps...)
931*1fa6dee9SAndroid Build Coastguard Worker}
932*1fa6dee9SAndroid Build Coastguard Worker
933*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) ModuleFactories() map[string]ModuleFactory {
934*1fa6dee9SAndroid Build Coastguard Worker	return m.context.ModuleTypeFactories()
935*1fa6dee9SAndroid Build Coastguard Worker}
936*1fa6dee9SAndroid Build Coastguard Worker
937*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) base() *baseModuleContext {
938*1fa6dee9SAndroid Build Coastguard Worker	return m
939*1fa6dee9SAndroid Build Coastguard Worker}
940*1fa6dee9SAndroid Build Coastguard Worker
941*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) OtherModuleIsAutoGenerated(logicModule Module) bool {
942*1fa6dee9SAndroid Build Coastguard Worker	module := m.context.moduleInfo[getWrappedModule(logicModule)]
943*1fa6dee9SAndroid Build Coastguard Worker	if module == nil {
944*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("Module %s not found in baseModuleContext", logicModule.Name()))
945*1fa6dee9SAndroid Build Coastguard Worker	}
946*1fa6dee9SAndroid Build Coastguard Worker	return module.createdBy != nil
947*1fa6dee9SAndroid Build Coastguard Worker}
948*1fa6dee9SAndroid Build Coastguard Worker
949*1fa6dee9SAndroid Build Coastguard Workerfunc (m *moduleContext) ModuleSubDir() string {
950*1fa6dee9SAndroid Build Coastguard Worker	return m.module.variant.name
951*1fa6dee9SAndroid Build Coastguard Worker}
952*1fa6dee9SAndroid Build Coastguard Worker
953*1fa6dee9SAndroid Build Coastguard Workerfunc (m *moduleContext) ModuleCacheKey() string {
954*1fa6dee9SAndroid Build Coastguard Worker	return m.module.ModuleCacheKey()
955*1fa6dee9SAndroid Build Coastguard Worker}
956*1fa6dee9SAndroid Build Coastguard Worker
957*1fa6dee9SAndroid Build Coastguard Workerfunc (m *moduleContext) Variable(pctx PackageContext, name, value string) {
958*1fa6dee9SAndroid Build Coastguard Worker	m.scope.ReparentTo(pctx)
959*1fa6dee9SAndroid Build Coastguard Worker
960*1fa6dee9SAndroid Build Coastguard Worker	v, err := m.scope.AddLocalVariable(name, value)
961*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
962*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
963*1fa6dee9SAndroid Build Coastguard Worker	}
964*1fa6dee9SAndroid Build Coastguard Worker
965*1fa6dee9SAndroid Build Coastguard Worker	m.actionDefs.variables = append(m.actionDefs.variables, v)
966*1fa6dee9SAndroid Build Coastguard Worker}
967*1fa6dee9SAndroid Build Coastguard Worker
968*1fa6dee9SAndroid Build Coastguard Workerfunc (m *moduleContext) Rule(pctx PackageContext, name string,
969*1fa6dee9SAndroid Build Coastguard Worker	params RuleParams, argNames ...string) Rule {
970*1fa6dee9SAndroid Build Coastguard Worker
971*1fa6dee9SAndroid Build Coastguard Worker	m.scope.ReparentTo(pctx)
972*1fa6dee9SAndroid Build Coastguard Worker
973*1fa6dee9SAndroid Build Coastguard Worker	r, err := m.scope.AddLocalRule(name, &params, argNames...)
974*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
975*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
976*1fa6dee9SAndroid Build Coastguard Worker	}
977*1fa6dee9SAndroid Build Coastguard Worker
978*1fa6dee9SAndroid Build Coastguard Worker	m.actionDefs.rules = append(m.actionDefs.rules, r)
979*1fa6dee9SAndroid Build Coastguard Worker
980*1fa6dee9SAndroid Build Coastguard Worker	return r
981*1fa6dee9SAndroid Build Coastguard Worker}
982*1fa6dee9SAndroid Build Coastguard Worker
983*1fa6dee9SAndroid Build Coastguard Workerfunc (m *moduleContext) Build(pctx PackageContext, params BuildParams) {
984*1fa6dee9SAndroid Build Coastguard Worker	m.scope.ReparentTo(pctx)
985*1fa6dee9SAndroid Build Coastguard Worker
986*1fa6dee9SAndroid Build Coastguard Worker	def, err := parseBuildParams(m.scope, &params, m.ModuleTags())
987*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
988*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
989*1fa6dee9SAndroid Build Coastguard Worker	}
990*1fa6dee9SAndroid Build Coastguard Worker
991*1fa6dee9SAndroid Build Coastguard Worker	m.actionDefs.buildDefs = append(m.actionDefs.buildDefs, def)
992*1fa6dee9SAndroid Build Coastguard Worker}
993*1fa6dee9SAndroid Build Coastguard Worker
994*1fa6dee9SAndroid Build Coastguard Workerfunc (m *moduleContext) GetMissingDependencies() []string {
995*1fa6dee9SAndroid Build Coastguard Worker	m.handledMissingDeps = true
996*1fa6dee9SAndroid Build Coastguard Worker	return m.module.missingDeps
997*1fa6dee9SAndroid Build Coastguard Worker}
998*1fa6dee9SAndroid Build Coastguard Worker
999*1fa6dee9SAndroid Build Coastguard Workerfunc (m *baseModuleContext) EarlyGetMissingDependencies() []string {
1000*1fa6dee9SAndroid Build Coastguard Worker	return m.module.missingDeps
1001*1fa6dee9SAndroid Build Coastguard Worker}
1002*1fa6dee9SAndroid Build Coastguard Worker
1003*1fa6dee9SAndroid Build Coastguard Worker//
1004*1fa6dee9SAndroid Build Coastguard Worker// MutatorContext
1005*1fa6dee9SAndroid Build Coastguard Worker//
1006*1fa6dee9SAndroid Build Coastguard Worker
1007*1fa6dee9SAndroid Build Coastguard Workertype mutatorContext struct {
1008*1fa6dee9SAndroid Build Coastguard Worker	baseModuleContext
1009*1fa6dee9SAndroid Build Coastguard Worker	mutator          *mutatorInfo
1010*1fa6dee9SAndroid Build Coastguard Worker	reverseDeps      []reverseDep
1011*1fa6dee9SAndroid Build Coastguard Worker	rename           []rename
1012*1fa6dee9SAndroid Build Coastguard Worker	replace          []replace
1013*1fa6dee9SAndroid Build Coastguard Worker	newVariations    moduleList    // new variants of existing modules
1014*1fa6dee9SAndroid Build Coastguard Worker	newModules       []*moduleInfo // brand new modules
1015*1fa6dee9SAndroid Build Coastguard Worker	defaultVariation *string
1016*1fa6dee9SAndroid Build Coastguard Worker	pauseCh          chan<- pauseSpec
1017*1fa6dee9SAndroid Build Coastguard Worker}
1018*1fa6dee9SAndroid Build Coastguard Worker
1019*1fa6dee9SAndroid Build Coastguard Workertype TopDownMutatorContext interface {
1020*1fa6dee9SAndroid Build Coastguard Worker	BaseModuleContext
1021*1fa6dee9SAndroid Build Coastguard Worker}
1022*1fa6dee9SAndroid Build Coastguard Worker
1023*1fa6dee9SAndroid Build Coastguard Workertype BottomUpMutatorContext interface {
1024*1fa6dee9SAndroid Build Coastguard Worker	BaseModuleContext
1025*1fa6dee9SAndroid Build Coastguard Worker
1026*1fa6dee9SAndroid Build Coastguard Worker	// AddDependency adds a dependency to the given module.  It returns a slice of modules for each
1027*1fa6dee9SAndroid Build Coastguard Worker	// dependency (some entries may be nil).  Does not affect the ordering of the current mutator
1028*1fa6dee9SAndroid Build Coastguard Worker	// pass, but will be ordered correctly for all future mutator passes.
1029*1fa6dee9SAndroid Build Coastguard Worker	//
1030*1fa6dee9SAndroid Build Coastguard Worker	// This method will pause until the new dependencies have had the current mutator called on them.
1031*1fa6dee9SAndroid Build Coastguard Worker	AddDependency(module Module, tag DependencyTag, name ...string) []Module
1032*1fa6dee9SAndroid Build Coastguard Worker
1033*1fa6dee9SAndroid Build Coastguard Worker	// AddReverseDependency adds a dependency from the destination to the given module.
1034*1fa6dee9SAndroid Build Coastguard Worker	// Does not affect the ordering of the current mutator pass, but will be ordered
1035*1fa6dee9SAndroid Build Coastguard Worker	// correctly for all future mutator passes.  All reverse dependencies for a destination module are
1036*1fa6dee9SAndroid Build Coastguard Worker	// collected until the end of the mutator pass, sorted by name, and then appended to the destination
1037*1fa6dee9SAndroid Build Coastguard Worker	// module's dependency list.  May only  be called by mutators that were marked with
1038*1fa6dee9SAndroid Build Coastguard Worker	// UsesReverseDependencies during registration.
1039*1fa6dee9SAndroid Build Coastguard Worker	AddReverseDependency(module Module, tag DependencyTag, name string)
1040*1fa6dee9SAndroid Build Coastguard Worker
1041*1fa6dee9SAndroid Build Coastguard Worker	// AddVariationDependencies adds deps as dependencies of the current module, but uses the variations
1042*1fa6dee9SAndroid Build Coastguard Worker	// argument to select which variant of the dependency to use.  It returns a slice of modules for
1043*1fa6dee9SAndroid Build Coastguard Worker	// each dependency (some entries may be nil).  A variant of the dependency must exist that matches
1044*1fa6dee9SAndroid Build Coastguard Worker	// the all of the non-local variations of the current module, plus the variations argument.
1045*1fa6dee9SAndroid Build Coastguard Worker	//
1046*1fa6dee9SAndroid Build Coastguard Worker	//
1047*1fa6dee9SAndroid Build Coastguard Worker	// This method will pause until the new dependencies have had the current mutator called on them.
1048*1fa6dee9SAndroid Build Coastguard Worker	AddVariationDependencies([]Variation, DependencyTag, ...string) []Module
1049*1fa6dee9SAndroid Build Coastguard Worker
1050*1fa6dee9SAndroid Build Coastguard Worker	// AddReverseVariationDependency adds a dependency from the named module to the current
1051*1fa6dee9SAndroid Build Coastguard Worker	// module. The given variations will be added to the current module's varations, and then the
1052*1fa6dee9SAndroid Build Coastguard Worker	// result will be used to find the correct variation of the depending module, which must exist.
1053*1fa6dee9SAndroid Build Coastguard Worker	//
1054*1fa6dee9SAndroid Build Coastguard Worker	// Does not affect the ordering of the current mutator pass, but will be ordered
1055*1fa6dee9SAndroid Build Coastguard Worker	// correctly for all future mutator passes.  All reverse dependencies for a destination module are
1056*1fa6dee9SAndroid Build Coastguard Worker	// collected until the end of the mutator pass, sorted by name, and then appended to the destination
1057*1fa6dee9SAndroid Build Coastguard Worker	// module's dependency list.  May only  be called by mutators that were marked with
1058*1fa6dee9SAndroid Build Coastguard Worker	// UsesReverseDependencies during registration.
1059*1fa6dee9SAndroid Build Coastguard Worker	AddReverseVariationDependency([]Variation, DependencyTag, string)
1060*1fa6dee9SAndroid Build Coastguard Worker
1061*1fa6dee9SAndroid Build Coastguard Worker	// AddFarVariationDependencies adds deps as dependencies of the current module, but uses the
1062*1fa6dee9SAndroid Build Coastguard Worker	// variations argument to select which variant of the dependency to use.  It returns a slice of
1063*1fa6dee9SAndroid Build Coastguard Worker	// modules for each dependency (some entries may be nil).  A variant of the dependency must
1064*1fa6dee9SAndroid Build Coastguard Worker	// exist that matches the variations argument, but may also have other variations.
1065*1fa6dee9SAndroid Build Coastguard Worker	// For any unspecified variation the first variant will be used.
1066*1fa6dee9SAndroid Build Coastguard Worker	//
1067*1fa6dee9SAndroid Build Coastguard Worker	// Unlike AddVariationDependencies, the variations of the current module are ignored - the
1068*1fa6dee9SAndroid Build Coastguard Worker	// dependency only needs to match the supplied variations.
1069*1fa6dee9SAndroid Build Coastguard Worker	//
1070*1fa6dee9SAndroid Build Coastguard Worker	//
1071*1fa6dee9SAndroid Build Coastguard Worker	// This method will pause until the new dependencies have had the current mutator called on them.
1072*1fa6dee9SAndroid Build Coastguard Worker	AddFarVariationDependencies([]Variation, DependencyTag, ...string) []Module
1073*1fa6dee9SAndroid Build Coastguard Worker
1074*1fa6dee9SAndroid Build Coastguard Worker	// ReplaceDependencies finds all the variants of the module with the specified name, then
1075*1fa6dee9SAndroid Build Coastguard Worker	// replaces all dependencies onto those variants with the current variant of this module.
1076*1fa6dee9SAndroid Build Coastguard Worker	// Replacements don't take effect until after the mutator pass is finished.  May only
1077*1fa6dee9SAndroid Build Coastguard Worker	// be called by mutators that were marked with UsesReplaceDependencies during registration.
1078*1fa6dee9SAndroid Build Coastguard Worker	ReplaceDependencies(string)
1079*1fa6dee9SAndroid Build Coastguard Worker
1080*1fa6dee9SAndroid Build Coastguard Worker	// ReplaceDependenciesIf finds all the variants of the module with the specified name, then
1081*1fa6dee9SAndroid Build Coastguard Worker	// replaces all dependencies onto those variants with the current variant of this module
1082*1fa6dee9SAndroid Build Coastguard Worker	// as long as the supplied predicate returns true.
1083*1fa6dee9SAndroid Build Coastguard Worker	// Replacements don't take effect until after the mutator pass is finished.  May only
1084*1fa6dee9SAndroid Build Coastguard Worker	// be called by mutators that were marked with UsesReplaceDependencies during registration.
1085*1fa6dee9SAndroid Build Coastguard Worker	ReplaceDependenciesIf(string, ReplaceDependencyPredicate)
1086*1fa6dee9SAndroid Build Coastguard Worker
1087*1fa6dee9SAndroid Build Coastguard Worker	// Rename all variants of a module.  The new name is not visible to calls to ModuleName,
1088*1fa6dee9SAndroid Build Coastguard Worker	// AddDependency or OtherModuleName until after this mutator pass is complete.  May only be called
1089*1fa6dee9SAndroid Build Coastguard Worker	// by mutators that were marked with UsesRename during registration.
1090*1fa6dee9SAndroid Build Coastguard Worker	Rename(name string)
1091*1fa6dee9SAndroid Build Coastguard Worker
1092*1fa6dee9SAndroid Build Coastguard Worker	// CreateModule creates a new module by calling the factory method for the specified moduleType, and applies
1093*1fa6dee9SAndroid Build Coastguard Worker	// the specified property structs to it as if the properties were set in a blueprint file.  May only
1094*1fa6dee9SAndroid Build Coastguard Worker	// be called by mutators that were marked with UsesCreateModule during registration.
1095*1fa6dee9SAndroid Build Coastguard Worker	CreateModule(ModuleFactory, string, ...interface{}) Module
1096*1fa6dee9SAndroid Build Coastguard Worker}
1097*1fa6dee9SAndroid Build Coastguard Worker
1098*1fa6dee9SAndroid Build Coastguard Worker// A Mutator function is called for each Module, and can modify properties on the modules.
1099*1fa6dee9SAndroid Build Coastguard Worker// It is called after parsing all Blueprint files, but before generating any build rules,
1100*1fa6dee9SAndroid Build Coastguard Worker// and is always called on dependencies before being called on the depending module.
1101*1fa6dee9SAndroid Build Coastguard Worker//
1102*1fa6dee9SAndroid Build Coastguard Worker// The Mutator function should only modify members of properties structs, and not
1103*1fa6dee9SAndroid Build Coastguard Worker// members of the module struct itself, to ensure the modified values are copied
1104*1fa6dee9SAndroid Build Coastguard Worker// if a second Mutator chooses to split the module a second time.
1105*1fa6dee9SAndroid Build Coastguard Workertype TopDownMutator func(mctx TopDownMutatorContext)
1106*1fa6dee9SAndroid Build Coastguard Workertype BottomUpMutator func(mctx BottomUpMutatorContext)
1107*1fa6dee9SAndroid Build Coastguard Worker
1108*1fa6dee9SAndroid Build Coastguard Worker// DependencyTag is an interface to an arbitrary object that embeds BaseDependencyTag.  It can be
1109*1fa6dee9SAndroid Build Coastguard Worker// used to transfer information on a dependency between the mutator that called AddDependency
1110*1fa6dee9SAndroid Build Coastguard Worker// and the GenerateBuildActions method.
1111*1fa6dee9SAndroid Build Coastguard Workertype DependencyTag interface {
1112*1fa6dee9SAndroid Build Coastguard Worker	dependencyTag(DependencyTag)
1113*1fa6dee9SAndroid Build Coastguard Worker}
1114*1fa6dee9SAndroid Build Coastguard Worker
1115*1fa6dee9SAndroid Build Coastguard Workertype BaseDependencyTag struct {
1116*1fa6dee9SAndroid Build Coastguard Worker}
1117*1fa6dee9SAndroid Build Coastguard Worker
1118*1fa6dee9SAndroid Build Coastguard Workerfunc (BaseDependencyTag) dependencyTag(DependencyTag) {
1119*1fa6dee9SAndroid Build Coastguard Worker}
1120*1fa6dee9SAndroid Build Coastguard Worker
1121*1fa6dee9SAndroid Build Coastguard Workervar _ DependencyTag = BaseDependencyTag{}
1122*1fa6dee9SAndroid Build Coastguard Worker
1123*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) createVariationsWithTransition(variationNames []string, outgoingTransitions [][]string) []Module {
1124*1fa6dee9SAndroid Build Coastguard Worker	return mctx.createVariations(variationNames, chooseDepByIndexes(mctx.mutator.name, outgoingTransitions))
1125*1fa6dee9SAndroid Build Coastguard Worker}
1126*1fa6dee9SAndroid Build Coastguard Worker
1127*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) createVariations(variationNames []string, depChooser depChooser) []Module {
1128*1fa6dee9SAndroid Build Coastguard Worker	var ret []Module
1129*1fa6dee9SAndroid Build Coastguard Worker	modules, errs := mctx.context.createVariations(mctx.module, mctx.mutator, depChooser, variationNames)
1130*1fa6dee9SAndroid Build Coastguard Worker	if len(errs) > 0 {
1131*1fa6dee9SAndroid Build Coastguard Worker		mctx.errs = append(mctx.errs, errs...)
1132*1fa6dee9SAndroid Build Coastguard Worker	}
1133*1fa6dee9SAndroid Build Coastguard Worker
1134*1fa6dee9SAndroid Build Coastguard Worker	for _, module := range modules {
1135*1fa6dee9SAndroid Build Coastguard Worker		ret = append(ret, module.logicModule)
1136*1fa6dee9SAndroid Build Coastguard Worker	}
1137*1fa6dee9SAndroid Build Coastguard Worker
1138*1fa6dee9SAndroid Build Coastguard Worker	if mctx.newVariations != nil {
1139*1fa6dee9SAndroid Build Coastguard Worker		panic("module already has variations from this mutator")
1140*1fa6dee9SAndroid Build Coastguard Worker	}
1141*1fa6dee9SAndroid Build Coastguard Worker	mctx.newVariations = modules
1142*1fa6dee9SAndroid Build Coastguard Worker
1143*1fa6dee9SAndroid Build Coastguard Worker	if len(ret) != len(variationNames) {
1144*1fa6dee9SAndroid Build Coastguard Worker		panic("oops!")
1145*1fa6dee9SAndroid Build Coastguard Worker	}
1146*1fa6dee9SAndroid Build Coastguard Worker
1147*1fa6dee9SAndroid Build Coastguard Worker	return ret
1148*1fa6dee9SAndroid Build Coastguard Worker}
1149*1fa6dee9SAndroid Build Coastguard Worker
1150*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) Module() Module {
1151*1fa6dee9SAndroid Build Coastguard Worker	return mctx.module.logicModule
1152*1fa6dee9SAndroid Build Coastguard Worker}
1153*1fa6dee9SAndroid Build Coastguard Worker
1154*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) AddDependency(module Module, tag DependencyTag, deps ...string) []Module {
1155*1fa6dee9SAndroid Build Coastguard Worker	depInfos := make([]Module, 0, len(deps))
1156*1fa6dee9SAndroid Build Coastguard Worker	for _, dep := range deps {
1157*1fa6dee9SAndroid Build Coastguard Worker		modInfo := mctx.context.moduleInfo[module]
1158*1fa6dee9SAndroid Build Coastguard Worker		depInfo, errs := mctx.context.addVariationDependency(modInfo, mctx.mutator, mctx.config, nil, tag, dep, false)
1159*1fa6dee9SAndroid Build Coastguard Worker		if len(errs) > 0 {
1160*1fa6dee9SAndroid Build Coastguard Worker			mctx.errs = append(mctx.errs, errs...)
1161*1fa6dee9SAndroid Build Coastguard Worker		}
1162*1fa6dee9SAndroid Build Coastguard Worker		if !mctx.pause(depInfo) {
1163*1fa6dee9SAndroid Build Coastguard Worker			// Pausing not supported by this mutator, new dependencies can't be returned.
1164*1fa6dee9SAndroid Build Coastguard Worker			depInfo = nil
1165*1fa6dee9SAndroid Build Coastguard Worker		}
1166*1fa6dee9SAndroid Build Coastguard Worker		depInfos = append(depInfos, maybeLogicModule(depInfo))
1167*1fa6dee9SAndroid Build Coastguard Worker	}
1168*1fa6dee9SAndroid Build Coastguard Worker	return depInfos
1169*1fa6dee9SAndroid Build Coastguard Worker}
1170*1fa6dee9SAndroid Build Coastguard Worker
1171*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) AddReverseDependency(module Module, tag DependencyTag, destName string) {
1172*1fa6dee9SAndroid Build Coastguard Worker	if !mctx.mutator.usesReverseDependencies {
1173*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("method AddReverseDependency called from mutator that was not marked UsesReverseDependencies"))
1174*1fa6dee9SAndroid Build Coastguard Worker	}
1175*1fa6dee9SAndroid Build Coastguard Worker
1176*1fa6dee9SAndroid Build Coastguard Worker	if _, ok := tag.(BaseDependencyTag); ok {
1177*1fa6dee9SAndroid Build Coastguard Worker		panic("BaseDependencyTag is not allowed to be used directly!")
1178*1fa6dee9SAndroid Build Coastguard Worker	}
1179*1fa6dee9SAndroid Build Coastguard Worker
1180*1fa6dee9SAndroid Build Coastguard Worker	destModule, errs := mctx.context.findReverseDependency(mctx.context.moduleInfo[module], mctx.config, nil, destName)
1181*1fa6dee9SAndroid Build Coastguard Worker	if len(errs) > 0 {
1182*1fa6dee9SAndroid Build Coastguard Worker		mctx.errs = append(mctx.errs, errs...)
1183*1fa6dee9SAndroid Build Coastguard Worker		return
1184*1fa6dee9SAndroid Build Coastguard Worker	}
1185*1fa6dee9SAndroid Build Coastguard Worker
1186*1fa6dee9SAndroid Build Coastguard Worker	if destModule == nil {
1187*1fa6dee9SAndroid Build Coastguard Worker		// allowMissingDependencies is true and the module wasn't found
1188*1fa6dee9SAndroid Build Coastguard Worker		return
1189*1fa6dee9SAndroid Build Coastguard Worker	}
1190*1fa6dee9SAndroid Build Coastguard Worker
1191*1fa6dee9SAndroid Build Coastguard Worker	mctx.reverseDeps = append(mctx.reverseDeps, reverseDep{
1192*1fa6dee9SAndroid Build Coastguard Worker		destModule,
1193*1fa6dee9SAndroid Build Coastguard Worker		depInfo{mctx.context.moduleInfo[module], tag},
1194*1fa6dee9SAndroid Build Coastguard Worker	})
1195*1fa6dee9SAndroid Build Coastguard Worker}
1196*1fa6dee9SAndroid Build Coastguard Worker
1197*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) AddReverseVariationDependency(variations []Variation, tag DependencyTag, destName string) {
1198*1fa6dee9SAndroid Build Coastguard Worker	if !mctx.mutator.usesReverseDependencies {
1199*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("method AddReverseVariationDependency called from mutator that was not marked UsesReverseDependencies"))
1200*1fa6dee9SAndroid Build Coastguard Worker	}
1201*1fa6dee9SAndroid Build Coastguard Worker
1202*1fa6dee9SAndroid Build Coastguard Worker	if _, ok := tag.(BaseDependencyTag); ok {
1203*1fa6dee9SAndroid Build Coastguard Worker		panic("BaseDependencyTag is not allowed to be used directly!")
1204*1fa6dee9SAndroid Build Coastguard Worker	}
1205*1fa6dee9SAndroid Build Coastguard Worker
1206*1fa6dee9SAndroid Build Coastguard Worker	destModule, errs := mctx.context.findReverseDependency(mctx.module, mctx.config, variations, destName)
1207*1fa6dee9SAndroid Build Coastguard Worker	if len(errs) > 0 {
1208*1fa6dee9SAndroid Build Coastguard Worker		mctx.errs = append(mctx.errs, errs...)
1209*1fa6dee9SAndroid Build Coastguard Worker		return
1210*1fa6dee9SAndroid Build Coastguard Worker	}
1211*1fa6dee9SAndroid Build Coastguard Worker
1212*1fa6dee9SAndroid Build Coastguard Worker	if destModule == nil {
1213*1fa6dee9SAndroid Build Coastguard Worker		// allowMissingDependencies is true and the module wasn't found
1214*1fa6dee9SAndroid Build Coastguard Worker		return
1215*1fa6dee9SAndroid Build Coastguard Worker	}
1216*1fa6dee9SAndroid Build Coastguard Worker
1217*1fa6dee9SAndroid Build Coastguard Worker	mctx.reverseDeps = append(mctx.reverseDeps, reverseDep{
1218*1fa6dee9SAndroid Build Coastguard Worker		destModule,
1219*1fa6dee9SAndroid Build Coastguard Worker		depInfo{mctx.module, tag},
1220*1fa6dee9SAndroid Build Coastguard Worker	})
1221*1fa6dee9SAndroid Build Coastguard Worker}
1222*1fa6dee9SAndroid Build Coastguard Worker
1223*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) AddVariationDependencies(variations []Variation, tag DependencyTag,
1224*1fa6dee9SAndroid Build Coastguard Worker	deps ...string) []Module {
1225*1fa6dee9SAndroid Build Coastguard Worker
1226*1fa6dee9SAndroid Build Coastguard Worker	depInfos := make([]Module, 0, len(deps))
1227*1fa6dee9SAndroid Build Coastguard Worker	for _, dep := range deps {
1228*1fa6dee9SAndroid Build Coastguard Worker		depInfo, errs := mctx.context.addVariationDependency(mctx.module, mctx.mutator, mctx.config, variations, tag, dep, false)
1229*1fa6dee9SAndroid Build Coastguard Worker		if len(errs) > 0 {
1230*1fa6dee9SAndroid Build Coastguard Worker			mctx.errs = append(mctx.errs, errs...)
1231*1fa6dee9SAndroid Build Coastguard Worker		}
1232*1fa6dee9SAndroid Build Coastguard Worker		if !mctx.pause(depInfo) {
1233*1fa6dee9SAndroid Build Coastguard Worker			// Pausing not supported by this mutator, new dependencies can't be returned.
1234*1fa6dee9SAndroid Build Coastguard Worker			depInfo = nil
1235*1fa6dee9SAndroid Build Coastguard Worker		}
1236*1fa6dee9SAndroid Build Coastguard Worker		depInfos = append(depInfos, maybeLogicModule(depInfo))
1237*1fa6dee9SAndroid Build Coastguard Worker	}
1238*1fa6dee9SAndroid Build Coastguard Worker	return depInfos
1239*1fa6dee9SAndroid Build Coastguard Worker}
1240*1fa6dee9SAndroid Build Coastguard Worker
1241*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) AddFarVariationDependencies(variations []Variation, tag DependencyTag,
1242*1fa6dee9SAndroid Build Coastguard Worker	deps ...string) []Module {
1243*1fa6dee9SAndroid Build Coastguard Worker
1244*1fa6dee9SAndroid Build Coastguard Worker	depInfos := make([]Module, 0, len(deps))
1245*1fa6dee9SAndroid Build Coastguard Worker	for _, dep := range deps {
1246*1fa6dee9SAndroid Build Coastguard Worker		depInfo, errs := mctx.context.addVariationDependency(mctx.module, mctx.mutator, mctx.config, variations, tag, dep, true)
1247*1fa6dee9SAndroid Build Coastguard Worker		if len(errs) > 0 {
1248*1fa6dee9SAndroid Build Coastguard Worker			mctx.errs = append(mctx.errs, errs...)
1249*1fa6dee9SAndroid Build Coastguard Worker		}
1250*1fa6dee9SAndroid Build Coastguard Worker		if !mctx.pause(depInfo) {
1251*1fa6dee9SAndroid Build Coastguard Worker			// Pausing not supported by this mutator, new dependencies can't be returned.
1252*1fa6dee9SAndroid Build Coastguard Worker			depInfo = nil
1253*1fa6dee9SAndroid Build Coastguard Worker		}
1254*1fa6dee9SAndroid Build Coastguard Worker		depInfos = append(depInfos, maybeLogicModule(depInfo))
1255*1fa6dee9SAndroid Build Coastguard Worker	}
1256*1fa6dee9SAndroid Build Coastguard Worker	return depInfos
1257*1fa6dee9SAndroid Build Coastguard Worker}
1258*1fa6dee9SAndroid Build Coastguard Worker
1259*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) ReplaceDependencies(name string) {
1260*1fa6dee9SAndroid Build Coastguard Worker	mctx.ReplaceDependenciesIf(name, nil)
1261*1fa6dee9SAndroid Build Coastguard Worker}
1262*1fa6dee9SAndroid Build Coastguard Worker
1263*1fa6dee9SAndroid Build Coastguard Workertype ReplaceDependencyPredicate func(from Module, tag DependencyTag, to Module) bool
1264*1fa6dee9SAndroid Build Coastguard Worker
1265*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) ReplaceDependenciesIf(name string, predicate ReplaceDependencyPredicate) {
1266*1fa6dee9SAndroid Build Coastguard Worker	if !mctx.mutator.usesReplaceDependencies {
1267*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("method ReplaceDependenciesIf called from mutator that was not marked UsesReplaceDependencies"))
1268*1fa6dee9SAndroid Build Coastguard Worker	}
1269*1fa6dee9SAndroid Build Coastguard Worker
1270*1fa6dee9SAndroid Build Coastguard Worker	targets := mctx.context.moduleVariantsThatDependOn(name, mctx.module)
1271*1fa6dee9SAndroid Build Coastguard Worker
1272*1fa6dee9SAndroid Build Coastguard Worker	if len(targets) == 0 {
1273*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("ReplaceDependencies could not find identical variant {%s} for module %s\n"+
1274*1fa6dee9SAndroid Build Coastguard Worker			"available variants:\n  %s",
1275*1fa6dee9SAndroid Build Coastguard Worker			mctx.context.prettyPrintVariant(mctx.module.variant.variations),
1276*1fa6dee9SAndroid Build Coastguard Worker			name,
1277*1fa6dee9SAndroid Build Coastguard Worker			mctx.context.prettyPrintGroupVariants(mctx.context.moduleGroupFromName(name, mctx.module.namespace()))))
1278*1fa6dee9SAndroid Build Coastguard Worker	}
1279*1fa6dee9SAndroid Build Coastguard Worker
1280*1fa6dee9SAndroid Build Coastguard Worker	for _, target := range targets {
1281*1fa6dee9SAndroid Build Coastguard Worker		mctx.replace = append(mctx.replace, replace{target, mctx.module, predicate})
1282*1fa6dee9SAndroid Build Coastguard Worker	}
1283*1fa6dee9SAndroid Build Coastguard Worker}
1284*1fa6dee9SAndroid Build Coastguard Worker
1285*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) Rename(name string) {
1286*1fa6dee9SAndroid Build Coastguard Worker	if !mctx.mutator.usesRename {
1287*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("method Rename called from mutator that was not marked UsesRename"))
1288*1fa6dee9SAndroid Build Coastguard Worker	}
1289*1fa6dee9SAndroid Build Coastguard Worker	mctx.rename = append(mctx.rename, rename{mctx.module.group, name})
1290*1fa6dee9SAndroid Build Coastguard Worker}
1291*1fa6dee9SAndroid Build Coastguard Worker
1292*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) CreateModule(factory ModuleFactory, typeName string, props ...interface{}) Module {
1293*1fa6dee9SAndroid Build Coastguard Worker	if !mctx.mutator.usesCreateModule {
1294*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("method CreateModule called from mutator that was not marked UsesCreateModule"))
1295*1fa6dee9SAndroid Build Coastguard Worker	}
1296*1fa6dee9SAndroid Build Coastguard Worker
1297*1fa6dee9SAndroid Build Coastguard Worker	module := newModule(factory)
1298*1fa6dee9SAndroid Build Coastguard Worker
1299*1fa6dee9SAndroid Build Coastguard Worker	module.relBlueprintsFile = mctx.module.relBlueprintsFile
1300*1fa6dee9SAndroid Build Coastguard Worker	module.pos = mctx.module.pos
1301*1fa6dee9SAndroid Build Coastguard Worker	module.propertyPos = mctx.module.propertyPos
1302*1fa6dee9SAndroid Build Coastguard Worker	module.createdBy = mctx.module
1303*1fa6dee9SAndroid Build Coastguard Worker	module.typeName = typeName
1304*1fa6dee9SAndroid Build Coastguard Worker
1305*1fa6dee9SAndroid Build Coastguard Worker	for _, p := range props {
1306*1fa6dee9SAndroid Build Coastguard Worker		err := proptools.AppendMatchingProperties(module.properties, p, nil)
1307*1fa6dee9SAndroid Build Coastguard Worker		if err != nil {
1308*1fa6dee9SAndroid Build Coastguard Worker			panic(err)
1309*1fa6dee9SAndroid Build Coastguard Worker		}
1310*1fa6dee9SAndroid Build Coastguard Worker	}
1311*1fa6dee9SAndroid Build Coastguard Worker
1312*1fa6dee9SAndroid Build Coastguard Worker	mctx.newModules = append(mctx.newModules, module)
1313*1fa6dee9SAndroid Build Coastguard Worker
1314*1fa6dee9SAndroid Build Coastguard Worker	return module.logicModule
1315*1fa6dee9SAndroid Build Coastguard Worker}
1316*1fa6dee9SAndroid Build Coastguard Worker
1317*1fa6dee9SAndroid Build Coastguard Worker// pause waits until the given dependency has been visited by the mutator's parallelVisit call.
1318*1fa6dee9SAndroid Build Coastguard Worker// It returns true if the pause was supported, false if the pause was not supported and did not
1319*1fa6dee9SAndroid Build Coastguard Worker// occur, which will happen when the mutator is not parallelizable.  If the dependency is nil
1320*1fa6dee9SAndroid Build Coastguard Worker// it returns true if pausing is supported or false if it is not.
1321*1fa6dee9SAndroid Build Coastguard Workerfunc (mctx *mutatorContext) pause(dep *moduleInfo) bool {
1322*1fa6dee9SAndroid Build Coastguard Worker	if mctx.pauseCh != nil {
1323*1fa6dee9SAndroid Build Coastguard Worker		if dep != nil {
1324*1fa6dee9SAndroid Build Coastguard Worker			unpause := make(unpause)
1325*1fa6dee9SAndroid Build Coastguard Worker			mctx.pauseCh <- pauseSpec{
1326*1fa6dee9SAndroid Build Coastguard Worker				paused:  mctx.module,
1327*1fa6dee9SAndroid Build Coastguard Worker				until:   dep,
1328*1fa6dee9SAndroid Build Coastguard Worker				unpause: unpause,
1329*1fa6dee9SAndroid Build Coastguard Worker			}
1330*1fa6dee9SAndroid Build Coastguard Worker			<-unpause
1331*1fa6dee9SAndroid Build Coastguard Worker		}
1332*1fa6dee9SAndroid Build Coastguard Worker		return true
1333*1fa6dee9SAndroid Build Coastguard Worker	}
1334*1fa6dee9SAndroid Build Coastguard Worker	return false
1335*1fa6dee9SAndroid Build Coastguard Worker}
1336*1fa6dee9SAndroid Build Coastguard Worker
1337*1fa6dee9SAndroid Build Coastguard Worker// SimpleName is an embeddable object to implement the ModuleContext.Name method using a property
1338*1fa6dee9SAndroid Build Coastguard Worker// called "name".  Modules that embed it must also add SimpleName.Properties to their property
1339*1fa6dee9SAndroid Build Coastguard Worker// structure list.
1340*1fa6dee9SAndroid Build Coastguard Workertype SimpleName struct {
1341*1fa6dee9SAndroid Build Coastguard Worker	Properties struct {
1342*1fa6dee9SAndroid Build Coastguard Worker		Name string
1343*1fa6dee9SAndroid Build Coastguard Worker	}
1344*1fa6dee9SAndroid Build Coastguard Worker}
1345*1fa6dee9SAndroid Build Coastguard Worker
1346*1fa6dee9SAndroid Build Coastguard Workerfunc (s *SimpleName) Name() string {
1347*1fa6dee9SAndroid Build Coastguard Worker	return s.Properties.Name
1348*1fa6dee9SAndroid Build Coastguard Worker}
1349*1fa6dee9SAndroid Build Coastguard Worker
1350*1fa6dee9SAndroid Build Coastguard Worker// Load Hooks
1351*1fa6dee9SAndroid Build Coastguard Worker
1352*1fa6dee9SAndroid Build Coastguard Workertype LoadHookContext interface {
1353*1fa6dee9SAndroid Build Coastguard Worker	EarlyModuleContext
1354*1fa6dee9SAndroid Build Coastguard Worker
1355*1fa6dee9SAndroid Build Coastguard Worker	// CreateModule creates a new module by calling the factory method for the specified moduleType, and applies
1356*1fa6dee9SAndroid Build Coastguard Worker	// the specified property structs to it as if the properties were set in a blueprint file.
1357*1fa6dee9SAndroid Build Coastguard Worker	CreateModule(ModuleFactory, string, ...interface{}) Module
1358*1fa6dee9SAndroid Build Coastguard Worker
1359*1fa6dee9SAndroid Build Coastguard Worker	// CreateModuleInDirectory creates a new module in the specified directory by calling the
1360*1fa6dee9SAndroid Build Coastguard Worker	// factory method for the specified moduleType, and applies the specified property structs
1361*1fa6dee9SAndroid Build Coastguard Worker	// to it as if the properties were set in a blueprint file.
1362*1fa6dee9SAndroid Build Coastguard Worker	CreateModuleInDirectory(ModuleFactory, string, string, ...interface{}) Module
1363*1fa6dee9SAndroid Build Coastguard Worker
1364*1fa6dee9SAndroid Build Coastguard Worker	// RegisterScopedModuleType creates a new module type that is scoped to the current Blueprints
1365*1fa6dee9SAndroid Build Coastguard Worker	// file.
1366*1fa6dee9SAndroid Build Coastguard Worker	RegisterScopedModuleType(name string, factory ModuleFactory)
1367*1fa6dee9SAndroid Build Coastguard Worker}
1368*1fa6dee9SAndroid Build Coastguard Worker
1369*1fa6dee9SAndroid Build Coastguard Workerfunc (l *loadHookContext) createModule(factory ModuleFactory, typeName, moduleDir string, props ...interface{}) Module {
1370*1fa6dee9SAndroid Build Coastguard Worker	module := newModule(factory)
1371*1fa6dee9SAndroid Build Coastguard Worker
1372*1fa6dee9SAndroid Build Coastguard Worker	module.relBlueprintsFile = moduleDir
1373*1fa6dee9SAndroid Build Coastguard Worker	module.pos = l.module.pos
1374*1fa6dee9SAndroid Build Coastguard Worker	module.propertyPos = l.module.propertyPos
1375*1fa6dee9SAndroid Build Coastguard Worker	module.createdBy = l.module
1376*1fa6dee9SAndroid Build Coastguard Worker	module.typeName = typeName
1377*1fa6dee9SAndroid Build Coastguard Worker
1378*1fa6dee9SAndroid Build Coastguard Worker	for _, p := range props {
1379*1fa6dee9SAndroid Build Coastguard Worker		err := proptools.AppendMatchingProperties(module.properties, p, nil)
1380*1fa6dee9SAndroid Build Coastguard Worker		if err != nil {
1381*1fa6dee9SAndroid Build Coastguard Worker			panic(err)
1382*1fa6dee9SAndroid Build Coastguard Worker		}
1383*1fa6dee9SAndroid Build Coastguard Worker	}
1384*1fa6dee9SAndroid Build Coastguard Worker
1385*1fa6dee9SAndroid Build Coastguard Worker	l.newModules = append(l.newModules, module)
1386*1fa6dee9SAndroid Build Coastguard Worker
1387*1fa6dee9SAndroid Build Coastguard Worker	return module.logicModule
1388*1fa6dee9SAndroid Build Coastguard Worker}
1389*1fa6dee9SAndroid Build Coastguard Worker
1390*1fa6dee9SAndroid Build Coastguard Workerfunc (l *loadHookContext) CreateModule(factory ModuleFactory, typeName string, props ...interface{}) Module {
1391*1fa6dee9SAndroid Build Coastguard Worker	return l.createModule(factory, typeName, l.module.relBlueprintsFile, props...)
1392*1fa6dee9SAndroid Build Coastguard Worker}
1393*1fa6dee9SAndroid Build Coastguard Worker
1394*1fa6dee9SAndroid Build Coastguard Workerfunc (l *loadHookContext) CreateModuleInDirectory(factory ModuleFactory, typeName, moduleDir string, props ...interface{}) Module {
1395*1fa6dee9SAndroid Build Coastguard Worker	if moduleDir != filepath.Clean(moduleDir) {
1396*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("Cannot create a module in %s", moduleDir))
1397*1fa6dee9SAndroid Build Coastguard Worker	}
1398*1fa6dee9SAndroid Build Coastguard Worker
1399*1fa6dee9SAndroid Build Coastguard Worker	filePath := filepath.Join(moduleDir, "Android.bp")
1400*1fa6dee9SAndroid Build Coastguard Worker	return l.createModule(factory, typeName, filePath, props...)
1401*1fa6dee9SAndroid Build Coastguard Worker}
1402*1fa6dee9SAndroid Build Coastguard Worker
1403*1fa6dee9SAndroid Build Coastguard Workerfunc (l *loadHookContext) RegisterScopedModuleType(name string, factory ModuleFactory) {
1404*1fa6dee9SAndroid Build Coastguard Worker	if _, exists := l.context.moduleFactories[name]; exists {
1405*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("A global module type named %q already exists", name))
1406*1fa6dee9SAndroid Build Coastguard Worker	}
1407*1fa6dee9SAndroid Build Coastguard Worker
1408*1fa6dee9SAndroid Build Coastguard Worker	if _, exists := (*l.scopedModuleFactories)[name]; exists {
1409*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("A module type named %q already exists in this scope", name))
1410*1fa6dee9SAndroid Build Coastguard Worker	}
1411*1fa6dee9SAndroid Build Coastguard Worker
1412*1fa6dee9SAndroid Build Coastguard Worker	if *l.scopedModuleFactories == nil {
1413*1fa6dee9SAndroid Build Coastguard Worker		*l.scopedModuleFactories = make(map[string]ModuleFactory)
1414*1fa6dee9SAndroid Build Coastguard Worker	}
1415*1fa6dee9SAndroid Build Coastguard Worker
1416*1fa6dee9SAndroid Build Coastguard Worker	(*l.scopedModuleFactories)[name] = factory
1417*1fa6dee9SAndroid Build Coastguard Worker}
1418*1fa6dee9SAndroid Build Coastguard Worker
1419*1fa6dee9SAndroid Build Coastguard Workertype loadHookContext struct {
1420*1fa6dee9SAndroid Build Coastguard Worker	baseModuleContext
1421*1fa6dee9SAndroid Build Coastguard Worker	newModules            []*moduleInfo
1422*1fa6dee9SAndroid Build Coastguard Worker	scopedModuleFactories *map[string]ModuleFactory
1423*1fa6dee9SAndroid Build Coastguard Worker}
1424*1fa6dee9SAndroid Build Coastguard Worker
1425*1fa6dee9SAndroid Build Coastguard Workertype LoadHook func(ctx LoadHookContext)
1426*1fa6dee9SAndroid Build Coastguard Worker
1427*1fa6dee9SAndroid Build Coastguard Worker// LoadHookWithPriority is a wrapper around LoadHook and allows hooks to be sorted by priority.
1428*1fa6dee9SAndroid Build Coastguard Worker// hooks with higher value of `priority` run last.
1429*1fa6dee9SAndroid Build Coastguard Worker// hooks with equal value of `priority` run in the order they were registered.
1430*1fa6dee9SAndroid Build Coastguard Workertype LoadHookWithPriority struct {
1431*1fa6dee9SAndroid Build Coastguard Worker	priority int
1432*1fa6dee9SAndroid Build Coastguard Worker	loadHook LoadHook
1433*1fa6dee9SAndroid Build Coastguard Worker}
1434*1fa6dee9SAndroid Build Coastguard Worker
1435*1fa6dee9SAndroid Build Coastguard Worker// Load hooks need to be added by module factories, which don't have any parameter to get to the
1436*1fa6dee9SAndroid Build Coastguard Worker// Context, and only produce a Module interface with no base implementation, so the load hooks
1437*1fa6dee9SAndroid Build Coastguard Worker// must be stored in a global map.  The key is a pointer allocated by the module factory, so there
1438*1fa6dee9SAndroid Build Coastguard Worker// is no chance of collisions even if tests are running in parallel with multiple contexts.  The
1439*1fa6dee9SAndroid Build Coastguard Worker// contents should be short-lived, they are added during a module factory and removed immediately
1440*1fa6dee9SAndroid Build Coastguard Worker// after the module factory returns.
1441*1fa6dee9SAndroid Build Coastguard Workervar pendingHooks sync.Map
1442*1fa6dee9SAndroid Build Coastguard Worker
1443*1fa6dee9SAndroid Build Coastguard Workerfunc AddLoadHook(module Module, hook LoadHook) {
1444*1fa6dee9SAndroid Build Coastguard Worker	// default priority is 0
1445*1fa6dee9SAndroid Build Coastguard Worker	AddLoadHookWithPriority(module, hook, 0)
1446*1fa6dee9SAndroid Build Coastguard Worker}
1447*1fa6dee9SAndroid Build Coastguard Worker
1448*1fa6dee9SAndroid Build Coastguard Worker// AddLoadhHookWithPriority adds a load hook with a specified priority.
1449*1fa6dee9SAndroid Build Coastguard Worker// Hooks with higher priority run last.
1450*1fa6dee9SAndroid Build Coastguard Worker// Hooks with equal priority run in the order they were registered.
1451*1fa6dee9SAndroid Build Coastguard Workerfunc AddLoadHookWithPriority(module Module, hook LoadHook, priority int) {
1452*1fa6dee9SAndroid Build Coastguard Worker	// Only one goroutine can be processing a given module, so no additional locking is required
1453*1fa6dee9SAndroid Build Coastguard Worker	// for the slice stored in the sync.Map.
1454*1fa6dee9SAndroid Build Coastguard Worker	v, exists := pendingHooks.Load(module)
1455*1fa6dee9SAndroid Build Coastguard Worker	if !exists {
1456*1fa6dee9SAndroid Build Coastguard Worker		v, _ = pendingHooks.LoadOrStore(module, new([]LoadHookWithPriority))
1457*1fa6dee9SAndroid Build Coastguard Worker	}
1458*1fa6dee9SAndroid Build Coastguard Worker	hooks := v.(*[]LoadHookWithPriority)
1459*1fa6dee9SAndroid Build Coastguard Worker	*hooks = append(*hooks, LoadHookWithPriority{priority, hook})
1460*1fa6dee9SAndroid Build Coastguard Worker}
1461*1fa6dee9SAndroid Build Coastguard Worker
1462*1fa6dee9SAndroid Build Coastguard Workerfunc runAndRemoveLoadHooks(ctx *Context, config interface{}, module *moduleInfo,
1463*1fa6dee9SAndroid Build Coastguard Worker	scopedModuleFactories *map[string]ModuleFactory) (newModules []*moduleInfo, deps []string, errs []error) {
1464*1fa6dee9SAndroid Build Coastguard Worker
1465*1fa6dee9SAndroid Build Coastguard Worker	if v, exists := pendingHooks.Load(module.logicModule); exists {
1466*1fa6dee9SAndroid Build Coastguard Worker		hooks := v.(*[]LoadHookWithPriority)
1467*1fa6dee9SAndroid Build Coastguard Worker		// Sort the hooks by priority.
1468*1fa6dee9SAndroid Build Coastguard Worker		// Use SliceStable so that hooks with equal priority run in the order they were registered.
1469*1fa6dee9SAndroid Build Coastguard Worker		sort.SliceStable(*hooks, func(i, j int) bool { return (*hooks)[i].priority < (*hooks)[j].priority })
1470*1fa6dee9SAndroid Build Coastguard Worker
1471*1fa6dee9SAndroid Build Coastguard Worker		for _, hook := range *hooks {
1472*1fa6dee9SAndroid Build Coastguard Worker			mctx := &loadHookContext{
1473*1fa6dee9SAndroid Build Coastguard Worker				baseModuleContext: baseModuleContext{
1474*1fa6dee9SAndroid Build Coastguard Worker					context: ctx,
1475*1fa6dee9SAndroid Build Coastguard Worker					config:  config,
1476*1fa6dee9SAndroid Build Coastguard Worker					module:  module,
1477*1fa6dee9SAndroid Build Coastguard Worker				},
1478*1fa6dee9SAndroid Build Coastguard Worker				scopedModuleFactories: scopedModuleFactories,
1479*1fa6dee9SAndroid Build Coastguard Worker			}
1480*1fa6dee9SAndroid Build Coastguard Worker			hook.loadHook(mctx)
1481*1fa6dee9SAndroid Build Coastguard Worker			newModules = append(newModules, mctx.newModules...)
1482*1fa6dee9SAndroid Build Coastguard Worker			deps = append(deps, mctx.ninjaFileDeps...)
1483*1fa6dee9SAndroid Build Coastguard Worker			errs = append(errs, mctx.errs...)
1484*1fa6dee9SAndroid Build Coastguard Worker		}
1485*1fa6dee9SAndroid Build Coastguard Worker		pendingHooks.Delete(module.logicModule)
1486*1fa6dee9SAndroid Build Coastguard Worker
1487*1fa6dee9SAndroid Build Coastguard Worker		return newModules, deps, errs
1488*1fa6dee9SAndroid Build Coastguard Worker	}
1489*1fa6dee9SAndroid Build Coastguard Worker
1490*1fa6dee9SAndroid Build Coastguard Worker	return nil, nil, nil
1491*1fa6dee9SAndroid Build Coastguard Worker}
1492*1fa6dee9SAndroid Build Coastguard Worker
1493*1fa6dee9SAndroid Build Coastguard Worker// Check the syntax of a generated blueprint file.
1494*1fa6dee9SAndroid Build Coastguard Worker//
1495*1fa6dee9SAndroid Build Coastguard Worker// This is intended to perform a quick syntactic check for generated blueprint
1496*1fa6dee9SAndroid Build Coastguard Worker// code, where syntactically correct means:
1497*1fa6dee9SAndroid Build Coastguard Worker// * No variable definitions.
1498*1fa6dee9SAndroid Build Coastguard Worker// * Valid module types.
1499*1fa6dee9SAndroid Build Coastguard Worker// * Valid property names.
1500*1fa6dee9SAndroid Build Coastguard Worker// * Valid values for the property type.
1501*1fa6dee9SAndroid Build Coastguard Worker//
1502*1fa6dee9SAndroid Build Coastguard Worker// It does not perform any semantic checking of properties, existence of referenced
1503*1fa6dee9SAndroid Build Coastguard Worker// files, or dependencies.
1504*1fa6dee9SAndroid Build Coastguard Worker//
1505*1fa6dee9SAndroid Build Coastguard Worker// At a low level it:
1506*1fa6dee9SAndroid Build Coastguard Worker// * Parses the contents.
1507*1fa6dee9SAndroid Build Coastguard Worker// * Invokes relevant factory to create Module instances.
1508*1fa6dee9SAndroid Build Coastguard Worker// * Unpacks the properties into the Module.
1509*1fa6dee9SAndroid Build Coastguard Worker// * Does not invoke load hooks or any mutators.
1510*1fa6dee9SAndroid Build Coastguard Worker//
1511*1fa6dee9SAndroid Build Coastguard Worker// The filename is only used for reporting errors.
1512*1fa6dee9SAndroid Build Coastguard Workerfunc CheckBlueprintSyntax(moduleFactories map[string]ModuleFactory, filename string, contents string) []error {
1513*1fa6dee9SAndroid Build Coastguard Worker	file, errs := parser.Parse(filename, strings.NewReader(contents))
1514*1fa6dee9SAndroid Build Coastguard Worker	if len(errs) != 0 {
1515*1fa6dee9SAndroid Build Coastguard Worker		return errs
1516*1fa6dee9SAndroid Build Coastguard Worker	}
1517*1fa6dee9SAndroid Build Coastguard Worker
1518*1fa6dee9SAndroid Build Coastguard Worker	for _, def := range file.Defs {
1519*1fa6dee9SAndroid Build Coastguard Worker		switch def := def.(type) {
1520*1fa6dee9SAndroid Build Coastguard Worker		case *parser.Module:
1521*1fa6dee9SAndroid Build Coastguard Worker			_, moduleErrs := processModuleDef(def, filename, moduleFactories, nil, false)
1522*1fa6dee9SAndroid Build Coastguard Worker			errs = append(errs, moduleErrs...)
1523*1fa6dee9SAndroid Build Coastguard Worker
1524*1fa6dee9SAndroid Build Coastguard Worker		default:
1525*1fa6dee9SAndroid Build Coastguard Worker			panic(fmt.Errorf("unknown definition type: %T", def))
1526*1fa6dee9SAndroid Build Coastguard Worker		}
1527*1fa6dee9SAndroid Build Coastguard Worker	}
1528*1fa6dee9SAndroid Build Coastguard Worker
1529*1fa6dee9SAndroid Build Coastguard Worker	return errs
1530*1fa6dee9SAndroid Build Coastguard Worker}
1531*1fa6dee9SAndroid Build Coastguard Worker
1532*1fa6dee9SAndroid Build Coastguard Workerfunc maybeLogicModule(module *moduleInfo) Module {
1533*1fa6dee9SAndroid Build Coastguard Worker	if module != nil {
1534*1fa6dee9SAndroid Build Coastguard Worker		return module.logicModule
1535*1fa6dee9SAndroid Build Coastguard Worker	} else {
1536*1fa6dee9SAndroid Build Coastguard Worker		return nil
1537*1fa6dee9SAndroid Build Coastguard Worker	}
1538*1fa6dee9SAndroid Build Coastguard Worker}
1539