xref: /aosp_15_r20/build/blueprint/singleton_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	"fmt"
19*1fa6dee9SAndroid Build Coastguard Worker
20*1fa6dee9SAndroid Build Coastguard Worker	"github.com/google/blueprint/pathtools"
21*1fa6dee9SAndroid Build Coastguard Worker)
22*1fa6dee9SAndroid Build Coastguard Worker
23*1fa6dee9SAndroid Build Coastguard Workertype Singleton interface {
24*1fa6dee9SAndroid Build Coastguard Worker	GenerateBuildActions(SingletonContext)
25*1fa6dee9SAndroid Build Coastguard Worker}
26*1fa6dee9SAndroid Build Coastguard Worker
27*1fa6dee9SAndroid Build Coastguard Workertype SingletonContext interface {
28*1fa6dee9SAndroid Build Coastguard Worker	// Config returns the config object that was passed to Context.PrepareBuildActions.
29*1fa6dee9SAndroid Build Coastguard Worker	Config() interface{}
30*1fa6dee9SAndroid Build Coastguard Worker
31*1fa6dee9SAndroid Build Coastguard Worker	// Name returns the name of the current singleton passed to Context.RegisterSingletonType
32*1fa6dee9SAndroid Build Coastguard Worker	Name() string
33*1fa6dee9SAndroid Build Coastguard Worker
34*1fa6dee9SAndroid Build Coastguard Worker	// ModuleName returns the name of the given Module.  See BaseModuleContext.ModuleName for more information.
35*1fa6dee9SAndroid Build Coastguard Worker	ModuleName(module Module) string
36*1fa6dee9SAndroid Build Coastguard Worker
37*1fa6dee9SAndroid Build Coastguard Worker	// ModuleDir returns the directory of the given Module.  See BaseModuleContext.ModuleDir for more information.
38*1fa6dee9SAndroid Build Coastguard Worker	ModuleDir(module Module) string
39*1fa6dee9SAndroid Build Coastguard Worker
40*1fa6dee9SAndroid Build Coastguard Worker	// ModuleSubDir returns the unique subdirectory name of the given Module.  See ModuleContext.ModuleSubDir for
41*1fa6dee9SAndroid Build Coastguard Worker	// more information.
42*1fa6dee9SAndroid Build Coastguard Worker	ModuleSubDir(module Module) string
43*1fa6dee9SAndroid Build Coastguard Worker
44*1fa6dee9SAndroid Build Coastguard Worker	// ModuleType returns the type of the given Module.  See BaseModuleContext.ModuleType for more information.
45*1fa6dee9SAndroid Build Coastguard Worker	ModuleType(module Module) string
46*1fa6dee9SAndroid Build Coastguard Worker
47*1fa6dee9SAndroid Build Coastguard Worker	// BlueprintFile returns the path of the Blueprint file that defined the given module.
48*1fa6dee9SAndroid Build Coastguard Worker	BlueprintFile(module Module) string
49*1fa6dee9SAndroid Build Coastguard Worker
50*1fa6dee9SAndroid Build Coastguard Worker	// ModuleProvider returns the value, if any, for the provider for a module.  If the value for the
51*1fa6dee9SAndroid Build Coastguard Worker	// provider was not set it returns the zero value of the type of the provider, which means the
52*1fa6dee9SAndroid Build Coastguard Worker	// return value can always be type-asserted to the type of the provider.  The return value should
53*1fa6dee9SAndroid Build Coastguard Worker	// always be considered read-only.  It panics if called before the appropriate mutator or
54*1fa6dee9SAndroid Build Coastguard Worker	// GenerateBuildActions pass for the provider on the module.
55*1fa6dee9SAndroid Build Coastguard Worker	ModuleProvider(module Module, provider AnyProviderKey) (any, bool)
56*1fa6dee9SAndroid Build Coastguard Worker
57*1fa6dee9SAndroid Build Coastguard Worker	// ModuleErrorf reports an error at the line number of the module type in the module definition.
58*1fa6dee9SAndroid Build Coastguard Worker	ModuleErrorf(module Module, format string, args ...interface{})
59*1fa6dee9SAndroid Build Coastguard Worker
60*1fa6dee9SAndroid Build Coastguard Worker	// Errorf reports an error at the specified position of the module definition file.
61*1fa6dee9SAndroid Build Coastguard Worker	Errorf(format string, args ...interface{})
62*1fa6dee9SAndroid Build Coastguard Worker
63*1fa6dee9SAndroid Build Coastguard Worker	// OtherModulePropertyErrorf reports an error on the line number of the given property of the given module
64*1fa6dee9SAndroid Build Coastguard Worker	OtherModulePropertyErrorf(module Module, property string, format string, args ...interface{})
65*1fa6dee9SAndroid Build Coastguard Worker
66*1fa6dee9SAndroid Build Coastguard Worker	// Failed returns true if any errors have been reported.  In most cases the singleton can continue with generating
67*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
68*1fa6dee9SAndroid Build Coastguard Worker	// has prevented the singleton from creating necessary data it can return early when Failed returns true.
69*1fa6dee9SAndroid Build Coastguard Worker	Failed() bool
70*1fa6dee9SAndroid Build Coastguard Worker
71*1fa6dee9SAndroid Build Coastguard Worker	// Variable creates a new ninja variable scoped to the singleton.  It can be referenced by calls to Rule and Build
72*1fa6dee9SAndroid Build Coastguard Worker	// in the same singleton.
73*1fa6dee9SAndroid Build Coastguard Worker	Variable(pctx PackageContext, name, value string)
74*1fa6dee9SAndroid Build Coastguard Worker
75*1fa6dee9SAndroid Build Coastguard Worker	// Rule creates a new ninja rule scoped to the singleton.  It can be referenced by calls to Build in the same
76*1fa6dee9SAndroid Build Coastguard Worker	// singleton.
77*1fa6dee9SAndroid Build Coastguard Worker	Rule(pctx PackageContext, name string, params RuleParams, argNames ...string) Rule
78*1fa6dee9SAndroid Build Coastguard Worker
79*1fa6dee9SAndroid Build Coastguard Worker	// Build creates a new ninja build statement.
80*1fa6dee9SAndroid Build Coastguard Worker	Build(pctx PackageContext, params BuildParams)
81*1fa6dee9SAndroid Build Coastguard Worker
82*1fa6dee9SAndroid Build Coastguard Worker	// RequireNinjaVersion sets the generated ninja manifest to require at least the specified version of ninja.
83*1fa6dee9SAndroid Build Coastguard Worker	RequireNinjaVersion(major, minor, micro int)
84*1fa6dee9SAndroid Build Coastguard Worker
85*1fa6dee9SAndroid Build Coastguard Worker	// SetOutDir sets the value of the top-level "builddir" Ninja variable
86*1fa6dee9SAndroid Build Coastguard Worker	// that controls where Ninja stores its build log files.  This value can be
87*1fa6dee9SAndroid Build Coastguard Worker	// set at most one time for a single build, later calls are ignored.
88*1fa6dee9SAndroid Build Coastguard Worker	SetOutDir(pctx PackageContext, value string)
89*1fa6dee9SAndroid Build Coastguard Worker
90*1fa6dee9SAndroid Build Coastguard Worker	// AddSubninja adds a ninja file to include with subninja. This should likely
91*1fa6dee9SAndroid Build Coastguard Worker	// only ever be used inside bootstrap to handle glob rules.
92*1fa6dee9SAndroid Build Coastguard Worker	AddSubninja(file string)
93*1fa6dee9SAndroid Build Coastguard Worker
94*1fa6dee9SAndroid Build Coastguard Worker	// Eval takes a string with embedded ninja variables, and returns a string
95*1fa6dee9SAndroid Build Coastguard Worker	// with all of the variables recursively expanded. Any variables references
96*1fa6dee9SAndroid Build Coastguard Worker	// are expanded in the scope of the PackageContext.
97*1fa6dee9SAndroid Build Coastguard Worker	Eval(pctx PackageContext, ninjaStr string) (string, error)
98*1fa6dee9SAndroid Build Coastguard Worker
99*1fa6dee9SAndroid Build Coastguard Worker	// VisitAllModules calls visit for each defined variant of each module in an unspecified order.
100*1fa6dee9SAndroid Build Coastguard Worker	VisitAllModules(visit func(Module))
101*1fa6dee9SAndroid Build Coastguard Worker
102*1fa6dee9SAndroid Build Coastguard Worker	// VisitAllModuleProxies calls visit for each defined variant of each module in an unspecified order.
103*1fa6dee9SAndroid Build Coastguard Worker	VisitAllModuleProxies(visit func(proxy ModuleProxy))
104*1fa6dee9SAndroid Build Coastguard Worker
105*1fa6dee9SAndroid Build Coastguard Worker	// VisitAllModules calls pred for each defined variant of each module in an unspecified order, and if pred returns
106*1fa6dee9SAndroid Build Coastguard Worker	// true calls visit.
107*1fa6dee9SAndroid Build Coastguard Worker	VisitAllModulesIf(pred func(Module) bool, visit func(Module))
108*1fa6dee9SAndroid Build Coastguard Worker
109*1fa6dee9SAndroid Build Coastguard Worker	// VisitDirectDeps calls visit for each direct dependency of the Module.  If there are
110*1fa6dee9SAndroid Build Coastguard Worker	// multiple direct dependencies on the same module visit will be called multiple times on
111*1fa6dee9SAndroid Build Coastguard Worker	// that module and OtherModuleDependencyTag will return a different tag for each.
112*1fa6dee9SAndroid Build Coastguard Worker	//
113*1fa6dee9SAndroid Build Coastguard Worker	// The Module passed to the visit function should not be retained outside of the visit
114*1fa6dee9SAndroid Build Coastguard Worker	// function, it may be invalidated by future mutators.
115*1fa6dee9SAndroid Build Coastguard Worker	VisitDirectDeps(module Module, visit func(Module))
116*1fa6dee9SAndroid Build Coastguard Worker
117*1fa6dee9SAndroid Build Coastguard Worker	// VisitDirectDepsIf calls pred for each direct dependency of the Module, and if pred
118*1fa6dee9SAndroid Build Coastguard Worker	// returns true calls visit.  If there are multiple direct dependencies on the same module
119*1fa6dee9SAndroid Build Coastguard Worker	// pred and visit will be called multiple times on that module and OtherModuleDependencyTag
120*1fa6dee9SAndroid Build Coastguard Worker	// will return a different tag for each.
121*1fa6dee9SAndroid Build Coastguard Worker	//
122*1fa6dee9SAndroid Build Coastguard Worker	// The Module passed to the visit function should not be retained outside of the visit
123*1fa6dee9SAndroid Build Coastguard Worker	// function, it may be invalidated by future mutators.
124*1fa6dee9SAndroid Build Coastguard Worker	VisitDirectDepsIf(module Module, pred func(Module) bool, visit func(Module))
125*1fa6dee9SAndroid Build Coastguard Worker
126*1fa6dee9SAndroid Build Coastguard Worker	// VisitDepsDepthFirst calls visit for each transitive dependency, traversing the dependency tree in depth first
127*1fa6dee9SAndroid Build Coastguard Worker	// order. visit will only be called once for any given module, even if there are multiple paths through the
128*1fa6dee9SAndroid Build Coastguard Worker	// dependency tree to the module or multiple direct dependencies with different tags.
129*1fa6dee9SAndroid Build Coastguard Worker	VisitDepsDepthFirst(module Module, visit func(Module))
130*1fa6dee9SAndroid Build Coastguard Worker
131*1fa6dee9SAndroid Build Coastguard Worker	// VisitDepsDepthFirst calls pred for each transitive dependency, and if pred returns true calls visit, traversing
132*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
133*1fa6dee9SAndroid Build Coastguard Worker	// multiple paths through the dependency tree to the module or multiple direct dependencies with different tags.
134*1fa6dee9SAndroid Build Coastguard Worker	VisitDepsDepthFirstIf(module Module, pred func(Module) bool,
135*1fa6dee9SAndroid Build Coastguard Worker		visit func(Module))
136*1fa6dee9SAndroid Build Coastguard Worker
137*1fa6dee9SAndroid Build Coastguard Worker	// VisitAllModuleVariants calls visit for each variant of the given module.
138*1fa6dee9SAndroid Build Coastguard Worker	VisitAllModuleVariants(module Module, visit func(Module))
139*1fa6dee9SAndroid Build Coastguard Worker
140*1fa6dee9SAndroid Build Coastguard Worker	// VisitAllModuleVariantProxies calls visit for each variant of the given module.
141*1fa6dee9SAndroid Build Coastguard Worker	VisitAllModuleVariantProxies(module Module, visit func(proxy ModuleProxy))
142*1fa6dee9SAndroid Build Coastguard Worker
143*1fa6dee9SAndroid Build Coastguard Worker	// PrimaryModule returns the first variant of the given module.  This can be used to perform
144*1fa6dee9SAndroid Build Coastguard Worker	//	// singleton actions that are only done once for all variants of a module.
145*1fa6dee9SAndroid Build Coastguard Worker	PrimaryModule(module Module) Module
146*1fa6dee9SAndroid Build Coastguard Worker
147*1fa6dee9SAndroid Build Coastguard Worker	// IsFinalModule returns if the given module is the last variant. This can be used to perform
148*1fa6dee9SAndroid Build Coastguard Worker	// singleton actions that are only done once for all variants of a module.
149*1fa6dee9SAndroid Build Coastguard Worker	IsFinalModule(module Module) bool
150*1fa6dee9SAndroid Build Coastguard Worker
151*1fa6dee9SAndroid Build Coastguard Worker	// AddNinjaFileDeps adds dependencies on the specified files to the rule that creates the ninja manifest.  The
152*1fa6dee9SAndroid Build Coastguard Worker	// primary builder will be rerun whenever the specified files are modified.
153*1fa6dee9SAndroid Build Coastguard Worker	AddNinjaFileDeps(deps ...string)
154*1fa6dee9SAndroid Build Coastguard Worker
155*1fa6dee9SAndroid Build Coastguard Worker	// GlobWithDeps returns a list of files and directories that match the
156*1fa6dee9SAndroid Build Coastguard Worker	// specified pattern but do not match any of the patterns in excludes.
157*1fa6dee9SAndroid Build Coastguard Worker	// Any directories will have a '/' suffix. It also adds efficient
158*1fa6dee9SAndroid Build Coastguard Worker	// dependencies to rerun the primary builder whenever a file matching
159*1fa6dee9SAndroid Build Coastguard Worker	// the pattern as added or removed, without rerunning if a file that
160*1fa6dee9SAndroid Build Coastguard Worker	// does not match the pattern is added to a searched directory.
161*1fa6dee9SAndroid Build Coastguard Worker	GlobWithDeps(pattern string, excludes []string) ([]string, error)
162*1fa6dee9SAndroid Build Coastguard Worker
163*1fa6dee9SAndroid Build Coastguard Worker	// Fs returns a pathtools.Filesystem that can be used to interact with files.  Using the Filesystem interface allows
164*1fa6dee9SAndroid Build Coastguard Worker	// the singleton to be used in build system tests that run against a mock filesystem.
165*1fa6dee9SAndroid Build Coastguard Worker	Fs() pathtools.FileSystem
166*1fa6dee9SAndroid Build Coastguard Worker
167*1fa6dee9SAndroid Build Coastguard Worker	// ModuleVariantsFromName returns the list of module variants named `name` in the same namespace as `referer`.
168*1fa6dee9SAndroid Build Coastguard Worker	// Allows generating build actions for `referer` based on the metadata for `name` deferred until the singleton context.
169*1fa6dee9SAndroid Build Coastguard Worker	ModuleVariantsFromName(referer Module, name string) []Module
170*1fa6dee9SAndroid Build Coastguard Worker
171*1fa6dee9SAndroid Build Coastguard Worker	// HasMutatorFinished returns true if the given mutator has finished running.
172*1fa6dee9SAndroid Build Coastguard Worker	// It will panic if given an invalid mutator name.
173*1fa6dee9SAndroid Build Coastguard Worker	HasMutatorFinished(mutatorName string) bool
174*1fa6dee9SAndroid Build Coastguard Worker}
175*1fa6dee9SAndroid Build Coastguard Worker
176*1fa6dee9SAndroid Build Coastguard Workervar _ SingletonContext = (*singletonContext)(nil)
177*1fa6dee9SAndroid Build Coastguard Worker
178*1fa6dee9SAndroid Build Coastguard Workertype singletonContext struct {
179*1fa6dee9SAndroid Build Coastguard Worker	name    string
180*1fa6dee9SAndroid Build Coastguard Worker	context *Context
181*1fa6dee9SAndroid Build Coastguard Worker	config  interface{}
182*1fa6dee9SAndroid Build Coastguard Worker	scope   *localScope
183*1fa6dee9SAndroid Build Coastguard Worker	globals *liveTracker
184*1fa6dee9SAndroid Build Coastguard Worker
185*1fa6dee9SAndroid Build Coastguard Worker	ninjaFileDeps []string
186*1fa6dee9SAndroid Build Coastguard Worker	errs          []error
187*1fa6dee9SAndroid Build Coastguard Worker
188*1fa6dee9SAndroid Build Coastguard Worker	actionDefs localBuildActions
189*1fa6dee9SAndroid Build Coastguard Worker}
190*1fa6dee9SAndroid Build Coastguard Worker
191*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) Config() interface{} {
192*1fa6dee9SAndroid Build Coastguard Worker	return s.config
193*1fa6dee9SAndroid Build Coastguard Worker}
194*1fa6dee9SAndroid Build Coastguard Worker
195*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) Name() string {
196*1fa6dee9SAndroid Build Coastguard Worker	return s.name
197*1fa6dee9SAndroid Build Coastguard Worker}
198*1fa6dee9SAndroid Build Coastguard Worker
199*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) ModuleName(logicModule Module) string {
200*1fa6dee9SAndroid Build Coastguard Worker	return s.context.ModuleName(getWrappedModule(logicModule))
201*1fa6dee9SAndroid Build Coastguard Worker}
202*1fa6dee9SAndroid Build Coastguard Worker
203*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) ModuleDir(logicModule Module) string {
204*1fa6dee9SAndroid Build Coastguard Worker	return s.context.ModuleDir(getWrappedModule(logicModule))
205*1fa6dee9SAndroid Build Coastguard Worker}
206*1fa6dee9SAndroid Build Coastguard Worker
207*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) ModuleSubDir(logicModule Module) string {
208*1fa6dee9SAndroid Build Coastguard Worker	return s.context.ModuleSubDir(getWrappedModule(logicModule))
209*1fa6dee9SAndroid Build Coastguard Worker}
210*1fa6dee9SAndroid Build Coastguard Worker
211*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) ModuleType(logicModule Module) string {
212*1fa6dee9SAndroid Build Coastguard Worker	return s.context.ModuleType(getWrappedModule(logicModule))
213*1fa6dee9SAndroid Build Coastguard Worker}
214*1fa6dee9SAndroid Build Coastguard Worker
215*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) ModuleProvider(logicModule Module, provider AnyProviderKey) (any, bool) {
216*1fa6dee9SAndroid Build Coastguard Worker	return s.context.ModuleProvider(getWrappedModule(logicModule), provider)
217*1fa6dee9SAndroid Build Coastguard Worker}
218*1fa6dee9SAndroid Build Coastguard Worker
219*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) BlueprintFile(logicModule Module) string {
220*1fa6dee9SAndroid Build Coastguard Worker	return s.context.BlueprintFile(logicModule)
221*1fa6dee9SAndroid Build Coastguard Worker}
222*1fa6dee9SAndroid Build Coastguard Worker
223*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) error(err error) {
224*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
225*1fa6dee9SAndroid Build Coastguard Worker		s.errs = append(s.errs, err)
226*1fa6dee9SAndroid Build Coastguard Worker	}
227*1fa6dee9SAndroid Build Coastguard Worker}
228*1fa6dee9SAndroid Build Coastguard Worker
229*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) ModuleErrorf(logicModule Module, format string,
230*1fa6dee9SAndroid Build Coastguard Worker	args ...interface{}) {
231*1fa6dee9SAndroid Build Coastguard Worker
232*1fa6dee9SAndroid Build Coastguard Worker	s.error(s.context.ModuleErrorf(logicModule, format, args...))
233*1fa6dee9SAndroid Build Coastguard Worker}
234*1fa6dee9SAndroid Build Coastguard Worker
235*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) Errorf(format string, args ...interface{}) {
236*1fa6dee9SAndroid Build Coastguard Worker	// TODO: Make this not result in the error being printed as "internal error"
237*1fa6dee9SAndroid Build Coastguard Worker	s.error(fmt.Errorf(format, args...))
238*1fa6dee9SAndroid Build Coastguard Worker}
239*1fa6dee9SAndroid Build Coastguard Worker
240*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) OtherModulePropertyErrorf(logicModule Module, property string, format string,
241*1fa6dee9SAndroid Build Coastguard Worker	args ...interface{}) {
242*1fa6dee9SAndroid Build Coastguard Worker
243*1fa6dee9SAndroid Build Coastguard Worker	s.error(s.context.PropertyErrorf(logicModule, property, format, args...))
244*1fa6dee9SAndroid Build Coastguard Worker}
245*1fa6dee9SAndroid Build Coastguard Worker
246*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) Failed() bool {
247*1fa6dee9SAndroid Build Coastguard Worker	return len(s.errs) > 0
248*1fa6dee9SAndroid Build Coastguard Worker}
249*1fa6dee9SAndroid Build Coastguard Worker
250*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) Variable(pctx PackageContext, name, value string) {
251*1fa6dee9SAndroid Build Coastguard Worker	s.scope.ReparentTo(pctx)
252*1fa6dee9SAndroid Build Coastguard Worker
253*1fa6dee9SAndroid Build Coastguard Worker	v, err := s.scope.AddLocalVariable(name, value)
254*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
255*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
256*1fa6dee9SAndroid Build Coastguard Worker	}
257*1fa6dee9SAndroid Build Coastguard Worker
258*1fa6dee9SAndroid Build Coastguard Worker	s.actionDefs.variables = append(s.actionDefs.variables, v)
259*1fa6dee9SAndroid Build Coastguard Worker}
260*1fa6dee9SAndroid Build Coastguard Worker
261*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) Rule(pctx PackageContext, name string,
262*1fa6dee9SAndroid Build Coastguard Worker	params RuleParams, argNames ...string) Rule {
263*1fa6dee9SAndroid Build Coastguard Worker
264*1fa6dee9SAndroid Build Coastguard Worker	s.scope.ReparentTo(pctx)
265*1fa6dee9SAndroid Build Coastguard Worker
266*1fa6dee9SAndroid Build Coastguard Worker	r, err := s.scope.AddLocalRule(name, &params, argNames...)
267*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
268*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
269*1fa6dee9SAndroid Build Coastguard Worker	}
270*1fa6dee9SAndroid Build Coastguard Worker
271*1fa6dee9SAndroid Build Coastguard Worker	s.actionDefs.rules = append(s.actionDefs.rules, r)
272*1fa6dee9SAndroid Build Coastguard Worker
273*1fa6dee9SAndroid Build Coastguard Worker	return r
274*1fa6dee9SAndroid Build Coastguard Worker}
275*1fa6dee9SAndroid Build Coastguard Worker
276*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) Build(pctx PackageContext, params BuildParams) {
277*1fa6dee9SAndroid Build Coastguard Worker	s.scope.ReparentTo(pctx)
278*1fa6dee9SAndroid Build Coastguard Worker
279*1fa6dee9SAndroid Build Coastguard Worker	def, err := parseBuildParams(s.scope, &params, map[string]string{
280*1fa6dee9SAndroid Build Coastguard Worker		"module_name": s.name,
281*1fa6dee9SAndroid Build Coastguard Worker		"module_type": "singleton",
282*1fa6dee9SAndroid Build Coastguard Worker	})
283*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
284*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
285*1fa6dee9SAndroid Build Coastguard Worker	}
286*1fa6dee9SAndroid Build Coastguard Worker
287*1fa6dee9SAndroid Build Coastguard Worker	s.actionDefs.buildDefs = append(s.actionDefs.buildDefs, def)
288*1fa6dee9SAndroid Build Coastguard Worker}
289*1fa6dee9SAndroid Build Coastguard Worker
290*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) Eval(pctx PackageContext, str string) (string, error) {
291*1fa6dee9SAndroid Build Coastguard Worker	s.scope.ReparentTo(pctx)
292*1fa6dee9SAndroid Build Coastguard Worker
293*1fa6dee9SAndroid Build Coastguard Worker	ninjaStr, err := parseNinjaString(s.scope, str)
294*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
295*1fa6dee9SAndroid Build Coastguard Worker		return "", err
296*1fa6dee9SAndroid Build Coastguard Worker	}
297*1fa6dee9SAndroid Build Coastguard Worker
298*1fa6dee9SAndroid Build Coastguard Worker	err = s.globals.addNinjaStringDeps(ninjaStr)
299*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
300*1fa6dee9SAndroid Build Coastguard Worker		return "", err
301*1fa6dee9SAndroid Build Coastguard Worker	}
302*1fa6dee9SAndroid Build Coastguard Worker
303*1fa6dee9SAndroid Build Coastguard Worker	return s.globals.Eval(ninjaStr)
304*1fa6dee9SAndroid Build Coastguard Worker}
305*1fa6dee9SAndroid Build Coastguard Worker
306*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) RequireNinjaVersion(major, minor, micro int) {
307*1fa6dee9SAndroid Build Coastguard Worker	s.context.requireNinjaVersion(major, minor, micro)
308*1fa6dee9SAndroid Build Coastguard Worker}
309*1fa6dee9SAndroid Build Coastguard Worker
310*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) SetOutDir(pctx PackageContext, value string) {
311*1fa6dee9SAndroid Build Coastguard Worker	s.scope.ReparentTo(pctx)
312*1fa6dee9SAndroid Build Coastguard Worker
313*1fa6dee9SAndroid Build Coastguard Worker	ninjaValue, err := parseNinjaString(s.scope, value)
314*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
315*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
316*1fa6dee9SAndroid Build Coastguard Worker	}
317*1fa6dee9SAndroid Build Coastguard Worker
318*1fa6dee9SAndroid Build Coastguard Worker	s.context.setOutDir(ninjaValue)
319*1fa6dee9SAndroid Build Coastguard Worker}
320*1fa6dee9SAndroid Build Coastguard Worker
321*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) AddSubninja(file string) {
322*1fa6dee9SAndroid Build Coastguard Worker	s.context.subninjas = append(s.context.subninjas, file)
323*1fa6dee9SAndroid Build Coastguard Worker}
324*1fa6dee9SAndroid Build Coastguard Worker
325*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) VisitAllModules(visit func(Module)) {
326*1fa6dee9SAndroid Build Coastguard Worker	var visitingModule Module
327*1fa6dee9SAndroid Build Coastguard Worker	defer func() {
328*1fa6dee9SAndroid Build Coastguard Worker		if r := recover(); r != nil {
329*1fa6dee9SAndroid Build Coastguard Worker			panic(newPanicErrorf(r, "VisitAllModules(%s) for module %s",
330*1fa6dee9SAndroid Build Coastguard Worker				funcName(visit), s.context.moduleInfo[visitingModule]))
331*1fa6dee9SAndroid Build Coastguard Worker		}
332*1fa6dee9SAndroid Build Coastguard Worker	}()
333*1fa6dee9SAndroid Build Coastguard Worker
334*1fa6dee9SAndroid Build Coastguard Worker	s.context.VisitAllModules(func(m Module) {
335*1fa6dee9SAndroid Build Coastguard Worker		visitingModule = m
336*1fa6dee9SAndroid Build Coastguard Worker		visit(m)
337*1fa6dee9SAndroid Build Coastguard Worker	})
338*1fa6dee9SAndroid Build Coastguard Worker}
339*1fa6dee9SAndroid Build Coastguard Worker
340*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) VisitAllModuleProxies(visit func(proxy ModuleProxy)) {
341*1fa6dee9SAndroid Build Coastguard Worker	s.VisitAllModules(visitProxyAdaptor(visit))
342*1fa6dee9SAndroid Build Coastguard Worker}
343*1fa6dee9SAndroid Build Coastguard Worker
344*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) VisitAllModulesIf(pred func(Module) bool,
345*1fa6dee9SAndroid Build Coastguard Worker	visit func(Module)) {
346*1fa6dee9SAndroid Build Coastguard Worker
347*1fa6dee9SAndroid Build Coastguard Worker	s.context.VisitAllModulesIf(pred, visit)
348*1fa6dee9SAndroid Build Coastguard Worker}
349*1fa6dee9SAndroid Build Coastguard Worker
350*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) VisitDirectDeps(module Module, visit func(Module)) {
351*1fa6dee9SAndroid Build Coastguard Worker	s.context.VisitDirectDeps(module, visit)
352*1fa6dee9SAndroid Build Coastguard Worker}
353*1fa6dee9SAndroid Build Coastguard Worker
354*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) VisitDirectDepsIf(module Module, pred func(Module) bool, visit func(Module)) {
355*1fa6dee9SAndroid Build Coastguard Worker	s.context.VisitDirectDepsIf(module, pred, visit)
356*1fa6dee9SAndroid Build Coastguard Worker}
357*1fa6dee9SAndroid Build Coastguard Worker
358*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) VisitDepsDepthFirst(module Module,
359*1fa6dee9SAndroid Build Coastguard Worker	visit func(Module)) {
360*1fa6dee9SAndroid Build Coastguard Worker
361*1fa6dee9SAndroid Build Coastguard Worker	s.context.VisitDepsDepthFirst(module, visit)
362*1fa6dee9SAndroid Build Coastguard Worker}
363*1fa6dee9SAndroid Build Coastguard Worker
364*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) VisitDepsDepthFirstIf(module Module,
365*1fa6dee9SAndroid Build Coastguard Worker	pred func(Module) bool, visit func(Module)) {
366*1fa6dee9SAndroid Build Coastguard Worker
367*1fa6dee9SAndroid Build Coastguard Worker	s.context.VisitDepsDepthFirstIf(module, pred, visit)
368*1fa6dee9SAndroid Build Coastguard Worker}
369*1fa6dee9SAndroid Build Coastguard Worker
370*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) PrimaryModule(module Module) Module {
371*1fa6dee9SAndroid Build Coastguard Worker	return s.context.PrimaryModule(module)
372*1fa6dee9SAndroid Build Coastguard Worker}
373*1fa6dee9SAndroid Build Coastguard Worker
374*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) IsFinalModule(module Module) bool {
375*1fa6dee9SAndroid Build Coastguard Worker	return s.context.IsFinalModule(module)
376*1fa6dee9SAndroid Build Coastguard Worker}
377*1fa6dee9SAndroid Build Coastguard Worker
378*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) VisitAllModuleVariants(module Module, visit func(Module)) {
379*1fa6dee9SAndroid Build Coastguard Worker	s.context.VisitAllModuleVariants(module, visit)
380*1fa6dee9SAndroid Build Coastguard Worker}
381*1fa6dee9SAndroid Build Coastguard Worker
382*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) VisitAllModuleVariantProxies(module Module, visit func(proxy ModuleProxy)) {
383*1fa6dee9SAndroid Build Coastguard Worker	s.context.VisitAllModuleVariants(module, visitProxyAdaptor(visit))
384*1fa6dee9SAndroid Build Coastguard Worker}
385*1fa6dee9SAndroid Build Coastguard Worker
386*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) AddNinjaFileDeps(deps ...string) {
387*1fa6dee9SAndroid Build Coastguard Worker	s.ninjaFileDeps = append(s.ninjaFileDeps, deps...)
388*1fa6dee9SAndroid Build Coastguard Worker}
389*1fa6dee9SAndroid Build Coastguard Worker
390*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) GlobWithDeps(pattern string,
391*1fa6dee9SAndroid Build Coastguard Worker	excludes []string) ([]string, error) {
392*1fa6dee9SAndroid Build Coastguard Worker	return s.context.glob(pattern, excludes)
393*1fa6dee9SAndroid Build Coastguard Worker}
394*1fa6dee9SAndroid Build Coastguard Worker
395*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) Fs() pathtools.FileSystem {
396*1fa6dee9SAndroid Build Coastguard Worker	return s.context.fs
397*1fa6dee9SAndroid Build Coastguard Worker}
398*1fa6dee9SAndroid Build Coastguard Worker
399*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) ModuleVariantsFromName(referer Module, name string) []Module {
400*1fa6dee9SAndroid Build Coastguard Worker	c := s.context
401*1fa6dee9SAndroid Build Coastguard Worker
402*1fa6dee9SAndroid Build Coastguard Worker	refererInfo := c.moduleInfo[referer]
403*1fa6dee9SAndroid Build Coastguard Worker	if refererInfo == nil {
404*1fa6dee9SAndroid Build Coastguard Worker		s.ModuleErrorf(referer, "could not find module %q", referer.Name())
405*1fa6dee9SAndroid Build Coastguard Worker		return nil
406*1fa6dee9SAndroid Build Coastguard Worker	}
407*1fa6dee9SAndroid Build Coastguard Worker
408*1fa6dee9SAndroid Build Coastguard Worker	moduleGroup, exists := c.nameInterface.ModuleFromName(name, refererInfo.namespace())
409*1fa6dee9SAndroid Build Coastguard Worker	if !exists {
410*1fa6dee9SAndroid Build Coastguard Worker		return nil
411*1fa6dee9SAndroid Build Coastguard Worker	}
412*1fa6dee9SAndroid Build Coastguard Worker	result := make([]Module, 0, len(moduleGroup.modules))
413*1fa6dee9SAndroid Build Coastguard Worker	for _, moduleInfo := range moduleGroup.modules {
414*1fa6dee9SAndroid Build Coastguard Worker		result = append(result, moduleInfo.logicModule)
415*1fa6dee9SAndroid Build Coastguard Worker	}
416*1fa6dee9SAndroid Build Coastguard Worker	return result
417*1fa6dee9SAndroid Build Coastguard Worker}
418*1fa6dee9SAndroid Build Coastguard Worker
419*1fa6dee9SAndroid Build Coastguard Workerfunc (s *singletonContext) HasMutatorFinished(mutatorName string) bool {
420*1fa6dee9SAndroid Build Coastguard Worker	return s.context.HasMutatorFinished(mutatorName)
421*1fa6dee9SAndroid Build Coastguard Worker}
422*1fa6dee9SAndroid Build Coastguard Worker
423*1fa6dee9SAndroid Build Coastguard Workerfunc visitProxyAdaptor(visit func(proxy ModuleProxy)) func(module Module) {
424*1fa6dee9SAndroid Build Coastguard Worker	return func(module Module) {
425*1fa6dee9SAndroid Build Coastguard Worker		visit(ModuleProxy{
426*1fa6dee9SAndroid Build Coastguard Worker			module: module,
427*1fa6dee9SAndroid Build Coastguard Worker		})
428*1fa6dee9SAndroid Build Coastguard Worker	}
429*1fa6dee9SAndroid Build Coastguard Worker}
430