xref: /aosp_15_r20/build/blueprint/package_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	"reflect"
21*1fa6dee9SAndroid Build Coastguard Worker	"regexp"
22*1fa6dee9SAndroid Build Coastguard Worker	"runtime"
23*1fa6dee9SAndroid Build Coastguard Worker	"strings"
24*1fa6dee9SAndroid Build Coastguard Worker	"sync"
25*1fa6dee9SAndroid Build Coastguard Worker)
26*1fa6dee9SAndroid Build Coastguard Worker
27*1fa6dee9SAndroid Build Coastguard Worker// A PackageContext provides a way to create package-scoped Ninja pools,
28*1fa6dee9SAndroid Build Coastguard Worker// rules, and variables.  A Go package should create a single unexported
29*1fa6dee9SAndroid Build Coastguard Worker// package-scoped PackageContext variable that it uses to create all package-
30*1fa6dee9SAndroid Build Coastguard Worker// scoped Ninja object definitions.  This PackageContext object should then be
31*1fa6dee9SAndroid Build Coastguard Worker// passed to all calls to define module- or singleton-specific Ninja
32*1fa6dee9SAndroid Build Coastguard Worker// definitions.  For example:
33*1fa6dee9SAndroid Build Coastguard Worker//
34*1fa6dee9SAndroid Build Coastguard Worker//	package blah
35*1fa6dee9SAndroid Build Coastguard Worker//
36*1fa6dee9SAndroid Build Coastguard Worker//	import (
37*1fa6dee9SAndroid Build Coastguard Worker//	    "blueprint"
38*1fa6dee9SAndroid Build Coastguard Worker//	)
39*1fa6dee9SAndroid Build Coastguard Worker//
40*1fa6dee9SAndroid Build Coastguard Worker//	var (
41*1fa6dee9SAndroid Build Coastguard Worker//	    pctx = NewPackageContext("path/to/blah")
42*1fa6dee9SAndroid Build Coastguard Worker//
43*1fa6dee9SAndroid Build Coastguard Worker//	    myPrivateVar = pctx.StaticVariable("myPrivateVar", "abcdef")
44*1fa6dee9SAndroid Build Coastguard Worker//	    MyExportedVar = pctx.StaticVariable("MyExportedVar", "$myPrivateVar 123456!")
45*1fa6dee9SAndroid Build Coastguard Worker//
46*1fa6dee9SAndroid Build Coastguard Worker//	    SomeRule = pctx.StaticRule(...)
47*1fa6dee9SAndroid Build Coastguard Worker//	)
48*1fa6dee9SAndroid Build Coastguard Worker//
49*1fa6dee9SAndroid Build Coastguard Worker//	// ...
50*1fa6dee9SAndroid Build Coastguard Worker//
51*1fa6dee9SAndroid Build Coastguard Worker//	func (m *MyModule) GenerateBuildActions(ctx blueprint.Module) {
52*1fa6dee9SAndroid Build Coastguard Worker//	    ctx.Build(pctx, blueprint.BuildParams{
53*1fa6dee9SAndroid Build Coastguard Worker//	        Rule:    SomeRule,
54*1fa6dee9SAndroid Build Coastguard Worker//	        Outputs: []string{"$myPrivateVar"},
55*1fa6dee9SAndroid Build Coastguard Worker//	    })
56*1fa6dee9SAndroid Build Coastguard Worker//	}
57*1fa6dee9SAndroid Build Coastguard Workertype PackageContext interface {
58*1fa6dee9SAndroid Build Coastguard Worker	Import(pkgPath string)
59*1fa6dee9SAndroid Build Coastguard Worker	ImportAs(as, pkgPath string)
60*1fa6dee9SAndroid Build Coastguard Worker
61*1fa6dee9SAndroid Build Coastguard Worker	StaticVariable(name, value string) Variable
62*1fa6dee9SAndroid Build Coastguard Worker	VariableFunc(name string, f func(ctx VariableFuncContext, config interface{}) (string, error)) Variable
63*1fa6dee9SAndroid Build Coastguard Worker	VariableConfigMethod(name string, method interface{}) Variable
64*1fa6dee9SAndroid Build Coastguard Worker
65*1fa6dee9SAndroid Build Coastguard Worker	StaticPool(name string, params PoolParams) Pool
66*1fa6dee9SAndroid Build Coastguard Worker	PoolFunc(name string, f func(interface{}) (PoolParams, error)) Pool
67*1fa6dee9SAndroid Build Coastguard Worker
68*1fa6dee9SAndroid Build Coastguard Worker	StaticRule(name string, params RuleParams, argNames ...string) Rule
69*1fa6dee9SAndroid Build Coastguard Worker	RuleFunc(name string, f func(interface{}) (RuleParams, error), argNames ...string) Rule
70*1fa6dee9SAndroid Build Coastguard Worker
71*1fa6dee9SAndroid Build Coastguard Worker	AddNinjaFileDeps(deps ...string)
72*1fa6dee9SAndroid Build Coastguard Worker
73*1fa6dee9SAndroid Build Coastguard Worker	getScope() *basicScope
74*1fa6dee9SAndroid Build Coastguard Worker}
75*1fa6dee9SAndroid Build Coastguard Worker
76*1fa6dee9SAndroid Build Coastguard Workertype packageContext struct {
77*1fa6dee9SAndroid Build Coastguard Worker	fullName      string
78*1fa6dee9SAndroid Build Coastguard Worker	shortName     string
79*1fa6dee9SAndroid Build Coastguard Worker	pkgPath       string
80*1fa6dee9SAndroid Build Coastguard Worker	scope         *basicScope
81*1fa6dee9SAndroid Build Coastguard Worker	ninjaFileDeps []string
82*1fa6dee9SAndroid Build Coastguard Worker}
83*1fa6dee9SAndroid Build Coastguard Worker
84*1fa6dee9SAndroid Build Coastguard Workervar _ PackageContext = (*packageContext)(nil)
85*1fa6dee9SAndroid Build Coastguard Worker
86*1fa6dee9SAndroid Build Coastguard Workerfunc (p *packageContext) getScope() *basicScope {
87*1fa6dee9SAndroid Build Coastguard Worker	return p.scope
88*1fa6dee9SAndroid Build Coastguard Worker}
89*1fa6dee9SAndroid Build Coastguard Worker
90*1fa6dee9SAndroid Build Coastguard Workervar packageContexts = map[string]*packageContext{}
91*1fa6dee9SAndroid Build Coastguard Worker
92*1fa6dee9SAndroid Build Coastguard Worker// NewPackageContext creates a PackageContext object for a given package.  The
93*1fa6dee9SAndroid Build Coastguard Worker// pkgPath argument should always be set to the full path used to import the
94*1fa6dee9SAndroid Build Coastguard Worker// package.  This function may only be called from a Go package's init()
95*1fa6dee9SAndroid Build Coastguard Worker// function or as part of a package-scoped variable initialization.
96*1fa6dee9SAndroid Build Coastguard Workerfunc NewPackageContext(pkgPath string) PackageContext {
97*1fa6dee9SAndroid Build Coastguard Worker	checkCalledFromInit()
98*1fa6dee9SAndroid Build Coastguard Worker
99*1fa6dee9SAndroid Build Coastguard Worker	if _, present := packageContexts[pkgPath]; present {
100*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("package %q already has a package context", pkgPath))
101*1fa6dee9SAndroid Build Coastguard Worker	}
102*1fa6dee9SAndroid Build Coastguard Worker
103*1fa6dee9SAndroid Build Coastguard Worker	pkgName := pkgPathToName(pkgPath)
104*1fa6dee9SAndroid Build Coastguard Worker	err := validateNinjaName(pkgName)
105*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
106*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
107*1fa6dee9SAndroid Build Coastguard Worker	}
108*1fa6dee9SAndroid Build Coastguard Worker
109*1fa6dee9SAndroid Build Coastguard Worker	i := strings.LastIndex(pkgPath, "/")
110*1fa6dee9SAndroid Build Coastguard Worker	shortName := pkgPath[i+1:]
111*1fa6dee9SAndroid Build Coastguard Worker
112*1fa6dee9SAndroid Build Coastguard Worker	p := &packageContext{
113*1fa6dee9SAndroid Build Coastguard Worker		fullName:  pkgName,
114*1fa6dee9SAndroid Build Coastguard Worker		shortName: shortName,
115*1fa6dee9SAndroid Build Coastguard Worker		pkgPath:   pkgPath,
116*1fa6dee9SAndroid Build Coastguard Worker		scope:     newScope(nil),
117*1fa6dee9SAndroid Build Coastguard Worker	}
118*1fa6dee9SAndroid Build Coastguard Worker
119*1fa6dee9SAndroid Build Coastguard Worker	packageContexts[pkgPath] = p
120*1fa6dee9SAndroid Build Coastguard Worker
121*1fa6dee9SAndroid Build Coastguard Worker	return p
122*1fa6dee9SAndroid Build Coastguard Worker}
123*1fa6dee9SAndroid Build Coastguard Worker
124*1fa6dee9SAndroid Build Coastguard Workervar Phony Rule = NewBuiltinRule("phony")
125*1fa6dee9SAndroid Build Coastguard Worker
126*1fa6dee9SAndroid Build Coastguard Workervar Console Pool = NewBuiltinPool("console")
127*1fa6dee9SAndroid Build Coastguard Worker
128*1fa6dee9SAndroid Build Coastguard Workervar errRuleIsBuiltin = errors.New("the rule is a built-in")
129*1fa6dee9SAndroid Build Coastguard Workervar errPoolIsBuiltin = errors.New("the pool is a built-in")
130*1fa6dee9SAndroid Build Coastguard Workervar errVariableIsArg = errors.New("argument variables have no value")
131*1fa6dee9SAndroid Build Coastguard Worker
132*1fa6dee9SAndroid Build Coastguard Worker// checkCalledFromInit panics if a Go package's init function is not on the
133*1fa6dee9SAndroid Build Coastguard Worker// call stack.
134*1fa6dee9SAndroid Build Coastguard Workerfunc checkCalledFromInit() {
135*1fa6dee9SAndroid Build Coastguard Worker	for skip := 3; ; skip++ {
136*1fa6dee9SAndroid Build Coastguard Worker		_, funcName, ok := callerName(skip)
137*1fa6dee9SAndroid Build Coastguard Worker		if !ok {
138*1fa6dee9SAndroid Build Coastguard Worker			panic("not called from an init func")
139*1fa6dee9SAndroid Build Coastguard Worker		}
140*1fa6dee9SAndroid Build Coastguard Worker
141*1fa6dee9SAndroid Build Coastguard Worker		if funcName == "init" || strings.HasPrefix(funcName, "init·") ||
142*1fa6dee9SAndroid Build Coastguard Worker			funcName == "init.ializers" || strings.HasPrefix(funcName, "init.") {
143*1fa6dee9SAndroid Build Coastguard Worker			return
144*1fa6dee9SAndroid Build Coastguard Worker		}
145*1fa6dee9SAndroid Build Coastguard Worker	}
146*1fa6dee9SAndroid Build Coastguard Worker}
147*1fa6dee9SAndroid Build Coastguard Worker
148*1fa6dee9SAndroid Build Coastguard Worker// A regex to find a package path within a function name. It finds the shortest string that is
149*1fa6dee9SAndroid Build Coastguard Worker// followed by '.' and doesn't have any '/'s left.
150*1fa6dee9SAndroid Build Coastguard Workervar pkgPathRe = regexp.MustCompile(`^(.*?)\.([^/]+)$`)
151*1fa6dee9SAndroid Build Coastguard Worker
152*1fa6dee9SAndroid Build Coastguard Worker// callerName returns the package path and function name of the calling
153*1fa6dee9SAndroid Build Coastguard Worker// function.  The skip argument has the same meaning as the skip argument of
154*1fa6dee9SAndroid Build Coastguard Worker// runtime.Callers.
155*1fa6dee9SAndroid Build Coastguard Workerfunc callerName(skip int) (pkgPath, funcName string, ok bool) {
156*1fa6dee9SAndroid Build Coastguard Worker	var pc [1]uintptr
157*1fa6dee9SAndroid Build Coastguard Worker	n := runtime.Callers(skip+1, pc[:])
158*1fa6dee9SAndroid Build Coastguard Worker	if n != 1 {
159*1fa6dee9SAndroid Build Coastguard Worker		return "", "", false
160*1fa6dee9SAndroid Build Coastguard Worker	}
161*1fa6dee9SAndroid Build Coastguard Worker	frames := runtime.CallersFrames(pc[:])
162*1fa6dee9SAndroid Build Coastguard Worker	frame, _ := frames.Next()
163*1fa6dee9SAndroid Build Coastguard Worker	f := frame.Function
164*1fa6dee9SAndroid Build Coastguard Worker	s := pkgPathRe.FindStringSubmatch(f)
165*1fa6dee9SAndroid Build Coastguard Worker	if len(s) < 3 {
166*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("failed to extract package path and function name from %q", f))
167*1fa6dee9SAndroid Build Coastguard Worker	}
168*1fa6dee9SAndroid Build Coastguard Worker
169*1fa6dee9SAndroid Build Coastguard Worker	return s[1], s[2], true
170*1fa6dee9SAndroid Build Coastguard Worker}
171*1fa6dee9SAndroid Build Coastguard Worker
172*1fa6dee9SAndroid Build Coastguard Worker// pkgPathToName makes a Ninja-friendly name out of a Go package name by
173*1fa6dee9SAndroid Build Coastguard Worker// replaceing all the '/' characters with '.'.  We assume the results are
174*1fa6dee9SAndroid Build Coastguard Worker// unique, though this is not 100% guaranteed for Go package names that
175*1fa6dee9SAndroid Build Coastguard Worker// already contain '.' characters. Disallowing package names with '.' isn't
176*1fa6dee9SAndroid Build Coastguard Worker// reasonable since many package names contain the name of the hosting site
177*1fa6dee9SAndroid Build Coastguard Worker// (e.g. "code.google.com").  In practice this probably isn't really a
178*1fa6dee9SAndroid Build Coastguard Worker// problem.
179*1fa6dee9SAndroid Build Coastguard Workerfunc pkgPathToName(pkgPath string) string {
180*1fa6dee9SAndroid Build Coastguard Worker	return strings.Replace(pkgPath, "/", ".", -1)
181*1fa6dee9SAndroid Build Coastguard Worker}
182*1fa6dee9SAndroid Build Coastguard Worker
183*1fa6dee9SAndroid Build Coastguard Worker// Import enables access to the exported Ninja pools, rules, and variables
184*1fa6dee9SAndroid Build Coastguard Worker// that are defined at the package scope of another Go package.  Go's
185*1fa6dee9SAndroid Build Coastguard Worker// visibility rules apply to these references - capitalized names indicate
186*1fa6dee9SAndroid Build Coastguard Worker// that something is exported.  It may only be called from a Go package's
187*1fa6dee9SAndroid Build Coastguard Worker// init() function.  The Go package path passed to Import must have already
188*1fa6dee9SAndroid Build Coastguard Worker// been imported into the Go package using a Go import statement.  The
189*1fa6dee9SAndroid Build Coastguard Worker// imported variables may then be accessed from Ninja strings as
190*1fa6dee9SAndroid Build Coastguard Worker// "${pkg.Variable}", while the imported rules can simply be accessed as
191*1fa6dee9SAndroid Build Coastguard Worker// exported Go variables from the package.  For example:
192*1fa6dee9SAndroid Build Coastguard Worker//
193*1fa6dee9SAndroid Build Coastguard Worker//	import (
194*1fa6dee9SAndroid Build Coastguard Worker//	    "blueprint"
195*1fa6dee9SAndroid Build Coastguard Worker//	    "foo/bar"
196*1fa6dee9SAndroid Build Coastguard Worker//	)
197*1fa6dee9SAndroid Build Coastguard Worker//
198*1fa6dee9SAndroid Build Coastguard Worker//	var pctx = NewPackagePath("blah")
199*1fa6dee9SAndroid Build Coastguard Worker//
200*1fa6dee9SAndroid Build Coastguard Worker//	func init() {
201*1fa6dee9SAndroid Build Coastguard Worker//	    pctx.Import("foo/bar")
202*1fa6dee9SAndroid Build Coastguard Worker//	}
203*1fa6dee9SAndroid Build Coastguard Worker//
204*1fa6dee9SAndroid Build Coastguard Worker//	...
205*1fa6dee9SAndroid Build Coastguard Worker//
206*1fa6dee9SAndroid Build Coastguard Worker//	func (m *MyModule) GenerateBuildActions(ctx blueprint.Module) {
207*1fa6dee9SAndroid Build Coastguard Worker//	    ctx.Build(pctx, blueprint.BuildParams{
208*1fa6dee9SAndroid Build Coastguard Worker//	        Rule:    bar.SomeRule,
209*1fa6dee9SAndroid Build Coastguard Worker//	        Outputs: []string{"${bar.SomeVariable}"},
210*1fa6dee9SAndroid Build Coastguard Worker//	    })
211*1fa6dee9SAndroid Build Coastguard Worker//	}
212*1fa6dee9SAndroid Build Coastguard Worker//
213*1fa6dee9SAndroid Build Coastguard Worker// Note that the local name used to refer to the package in Ninja variable names
214*1fa6dee9SAndroid Build Coastguard Worker// is derived from pkgPath by extracting the last path component.  This differs
215*1fa6dee9SAndroid Build Coastguard Worker// from Go's import declaration, which derives the local name from the package
216*1fa6dee9SAndroid Build Coastguard Worker// clause in the imported package.  By convention these names are made to match,
217*1fa6dee9SAndroid Build Coastguard Worker// but this is not required.
218*1fa6dee9SAndroid Build Coastguard Workerfunc (p *packageContext) Import(pkgPath string) {
219*1fa6dee9SAndroid Build Coastguard Worker	checkCalledFromInit()
220*1fa6dee9SAndroid Build Coastguard Worker	importPkg, ok := packageContexts[pkgPath]
221*1fa6dee9SAndroid Build Coastguard Worker	if !ok {
222*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("package %q has no context", pkgPath))
223*1fa6dee9SAndroid Build Coastguard Worker	}
224*1fa6dee9SAndroid Build Coastguard Worker
225*1fa6dee9SAndroid Build Coastguard Worker	err := p.scope.AddImport(importPkg.shortName, importPkg.scope)
226*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
227*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
228*1fa6dee9SAndroid Build Coastguard Worker	}
229*1fa6dee9SAndroid Build Coastguard Worker}
230*1fa6dee9SAndroid Build Coastguard Worker
231*1fa6dee9SAndroid Build Coastguard Worker// ImportAs provides the same functionality as Import, but it allows the local
232*1fa6dee9SAndroid Build Coastguard Worker// name that will be used to refer to the package to be specified explicitly.
233*1fa6dee9SAndroid Build Coastguard Worker// It may only be called from a Go package's init() function.
234*1fa6dee9SAndroid Build Coastguard Workerfunc (p *packageContext) ImportAs(as, pkgPath string) {
235*1fa6dee9SAndroid Build Coastguard Worker	checkCalledFromInit()
236*1fa6dee9SAndroid Build Coastguard Worker	importPkg, ok := packageContexts[pkgPath]
237*1fa6dee9SAndroid Build Coastguard Worker	if !ok {
238*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("package %q has no context", pkgPath))
239*1fa6dee9SAndroid Build Coastguard Worker	}
240*1fa6dee9SAndroid Build Coastguard Worker
241*1fa6dee9SAndroid Build Coastguard Worker	err := validateNinjaName(as)
242*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
243*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
244*1fa6dee9SAndroid Build Coastguard Worker	}
245*1fa6dee9SAndroid Build Coastguard Worker
246*1fa6dee9SAndroid Build Coastguard Worker	err = p.scope.AddImport(as, importPkg.scope)
247*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
248*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
249*1fa6dee9SAndroid Build Coastguard Worker	}
250*1fa6dee9SAndroid Build Coastguard Worker}
251*1fa6dee9SAndroid Build Coastguard Worker
252*1fa6dee9SAndroid Build Coastguard Workertype staticVariable struct {
253*1fa6dee9SAndroid Build Coastguard Worker	pctx   *packageContext
254*1fa6dee9SAndroid Build Coastguard Worker	name_  string
255*1fa6dee9SAndroid Build Coastguard Worker	value_ string
256*1fa6dee9SAndroid Build Coastguard Worker}
257*1fa6dee9SAndroid Build Coastguard Worker
258*1fa6dee9SAndroid Build Coastguard Worker// StaticVariable returns a Variable whose value does not depend on any
259*1fa6dee9SAndroid Build Coastguard Worker// configuration information.  It may only be called during a Go package's
260*1fa6dee9SAndroid Build Coastguard Worker// initialization - either from the init() function or as part of a package-
261*1fa6dee9SAndroid Build Coastguard Worker// scoped variable's initialization.
262*1fa6dee9SAndroid Build Coastguard Worker//
263*1fa6dee9SAndroid Build Coastguard Worker// This function is usually used to initialize a package-scoped Go variable that
264*1fa6dee9SAndroid Build Coastguard Worker// represents a Ninja variable that will be output.  The name argument should
265*1fa6dee9SAndroid Build Coastguard Worker// exactly match the Go variable name, and the value string may reference other
266*1fa6dee9SAndroid Build Coastguard Worker// Ninja variables that are visible within the calling Go package.
267*1fa6dee9SAndroid Build Coastguard Workerfunc (p *packageContext) StaticVariable(name, value string) Variable {
268*1fa6dee9SAndroid Build Coastguard Worker	checkCalledFromInit()
269*1fa6dee9SAndroid Build Coastguard Worker	err := validateNinjaName(name)
270*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
271*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
272*1fa6dee9SAndroid Build Coastguard Worker	}
273*1fa6dee9SAndroid Build Coastguard Worker
274*1fa6dee9SAndroid Build Coastguard Worker	v := &staticVariable{
275*1fa6dee9SAndroid Build Coastguard Worker		pctx:   p,
276*1fa6dee9SAndroid Build Coastguard Worker		name_:  name,
277*1fa6dee9SAndroid Build Coastguard Worker		value_: value,
278*1fa6dee9SAndroid Build Coastguard Worker	}
279*1fa6dee9SAndroid Build Coastguard Worker	err = p.scope.AddVariable(v)
280*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
281*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
282*1fa6dee9SAndroid Build Coastguard Worker	}
283*1fa6dee9SAndroid Build Coastguard Worker
284*1fa6dee9SAndroid Build Coastguard Worker	return v
285*1fa6dee9SAndroid Build Coastguard Worker}
286*1fa6dee9SAndroid Build Coastguard Worker
287*1fa6dee9SAndroid Build Coastguard Workerfunc (v *staticVariable) packageContext() *packageContext {
288*1fa6dee9SAndroid Build Coastguard Worker	return v.pctx
289*1fa6dee9SAndroid Build Coastguard Worker}
290*1fa6dee9SAndroid Build Coastguard Worker
291*1fa6dee9SAndroid Build Coastguard Workerfunc (v *staticVariable) name() string {
292*1fa6dee9SAndroid Build Coastguard Worker	return v.name_
293*1fa6dee9SAndroid Build Coastguard Worker}
294*1fa6dee9SAndroid Build Coastguard Worker
295*1fa6dee9SAndroid Build Coastguard Workerfunc (v *staticVariable) fullName(pkgNames map[*packageContext]string) string {
296*1fa6dee9SAndroid Build Coastguard Worker	return packageNamespacePrefix(pkgNames[v.pctx]) + v.name_
297*1fa6dee9SAndroid Build Coastguard Worker}
298*1fa6dee9SAndroid Build Coastguard Worker
299*1fa6dee9SAndroid Build Coastguard Workerfunc (v *staticVariable) value(VariableFuncContext, interface{}) (*ninjaString, error) {
300*1fa6dee9SAndroid Build Coastguard Worker	ninjaStr, err := parseNinjaString(v.pctx.scope, v.value_)
301*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
302*1fa6dee9SAndroid Build Coastguard Worker		err = fmt.Errorf("error parsing variable %s value: %s", v, err)
303*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
304*1fa6dee9SAndroid Build Coastguard Worker	}
305*1fa6dee9SAndroid Build Coastguard Worker	return ninjaStr, nil
306*1fa6dee9SAndroid Build Coastguard Worker}
307*1fa6dee9SAndroid Build Coastguard Worker
308*1fa6dee9SAndroid Build Coastguard Workerfunc (v *staticVariable) String() string {
309*1fa6dee9SAndroid Build Coastguard Worker	return v.pctx.pkgPath + "." + v.name_
310*1fa6dee9SAndroid Build Coastguard Worker}
311*1fa6dee9SAndroid Build Coastguard Worker
312*1fa6dee9SAndroid Build Coastguard Workertype variableFunc struct {
313*1fa6dee9SAndroid Build Coastguard Worker	pctx   *packageContext
314*1fa6dee9SAndroid Build Coastguard Worker	name_  string
315*1fa6dee9SAndroid Build Coastguard Worker	value_ func(VariableFuncContext, interface{}) (string, error)
316*1fa6dee9SAndroid Build Coastguard Worker}
317*1fa6dee9SAndroid Build Coastguard Worker
318*1fa6dee9SAndroid Build Coastguard Worker// VariableFuncContext is passed to VariableFunc functions.
319*1fa6dee9SAndroid Build Coastguard Workertype VariableFuncContext interface {
320*1fa6dee9SAndroid Build Coastguard Worker	// GlobWithDeps returns a list of files and directories that match the
321*1fa6dee9SAndroid Build Coastguard Worker	// specified pattern but do not match any of the patterns in excludes.
322*1fa6dee9SAndroid Build Coastguard Worker	// Any directories will have a '/' suffix.  It also adds efficient
323*1fa6dee9SAndroid Build Coastguard Worker	// dependencies to rerun the primary builder whenever a file matching
324*1fa6dee9SAndroid Build Coastguard Worker	// the pattern as added or removed, without rerunning if a file that
325*1fa6dee9SAndroid Build Coastguard Worker	// does not match the pattern is added to a searched directory.
326*1fa6dee9SAndroid Build Coastguard Worker	GlobWithDeps(globPattern string, excludes []string) ([]string, error)
327*1fa6dee9SAndroid Build Coastguard Worker}
328*1fa6dee9SAndroid Build Coastguard Worker
329*1fa6dee9SAndroid Build Coastguard Workertype variableFuncContext struct {
330*1fa6dee9SAndroid Build Coastguard Worker	context *Context
331*1fa6dee9SAndroid Build Coastguard Worker}
332*1fa6dee9SAndroid Build Coastguard Worker
333*1fa6dee9SAndroid Build Coastguard Workerfunc (v *variableFuncContext) GlobWithDeps(pattern string,
334*1fa6dee9SAndroid Build Coastguard Worker	excludes []string) ([]string, error) {
335*1fa6dee9SAndroid Build Coastguard Worker	return v.context.glob(pattern, excludes)
336*1fa6dee9SAndroid Build Coastguard Worker}
337*1fa6dee9SAndroid Build Coastguard Worker
338*1fa6dee9SAndroid Build Coastguard Worker// VariableFunc returns a Variable whose value is determined by a function that
339*1fa6dee9SAndroid Build Coastguard Worker// takes a config object as input and returns either the variable value or an
340*1fa6dee9SAndroid Build Coastguard Worker// error.  It may only be called during a Go package's initialization - either
341*1fa6dee9SAndroid Build Coastguard Worker// from the init() function or as part of a package-scoped variable's
342*1fa6dee9SAndroid Build Coastguard Worker// initialization.
343*1fa6dee9SAndroid Build Coastguard Worker//
344*1fa6dee9SAndroid Build Coastguard Worker// This function is usually used to initialize a package-scoped Go variable that
345*1fa6dee9SAndroid Build Coastguard Worker// represents a Ninja variable that will be output.  The name argument should
346*1fa6dee9SAndroid Build Coastguard Worker// exactly match the Go variable name, and the value string returned by f may
347*1fa6dee9SAndroid Build Coastguard Worker// reference other Ninja variables that are visible within the calling Go
348*1fa6dee9SAndroid Build Coastguard Worker// package.
349*1fa6dee9SAndroid Build Coastguard Workerfunc (p *packageContext) VariableFunc(name string,
350*1fa6dee9SAndroid Build Coastguard Worker	f func(ctx VariableFuncContext, config interface{}) (string, error)) Variable {
351*1fa6dee9SAndroid Build Coastguard Worker
352*1fa6dee9SAndroid Build Coastguard Worker	checkCalledFromInit()
353*1fa6dee9SAndroid Build Coastguard Worker
354*1fa6dee9SAndroid Build Coastguard Worker	err := validateNinjaName(name)
355*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
356*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
357*1fa6dee9SAndroid Build Coastguard Worker	}
358*1fa6dee9SAndroid Build Coastguard Worker
359*1fa6dee9SAndroid Build Coastguard Worker	v := &variableFunc{
360*1fa6dee9SAndroid Build Coastguard Worker		pctx:   p,
361*1fa6dee9SAndroid Build Coastguard Worker		name_:  name,
362*1fa6dee9SAndroid Build Coastguard Worker		value_: f,
363*1fa6dee9SAndroid Build Coastguard Worker	}
364*1fa6dee9SAndroid Build Coastguard Worker	err = p.scope.AddVariable(v)
365*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
366*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
367*1fa6dee9SAndroid Build Coastguard Worker	}
368*1fa6dee9SAndroid Build Coastguard Worker
369*1fa6dee9SAndroid Build Coastguard Worker	return v
370*1fa6dee9SAndroid Build Coastguard Worker}
371*1fa6dee9SAndroid Build Coastguard Worker
372*1fa6dee9SAndroid Build Coastguard Worker// VariableConfigMethod returns a Variable whose value is determined by calling
373*1fa6dee9SAndroid Build Coastguard Worker// a method on the config object.  The method must take no arguments and return
374*1fa6dee9SAndroid Build Coastguard Worker// a single string that will be the variable's value.  It may only be called
375*1fa6dee9SAndroid Build Coastguard Worker// during a Go package's initialization - either from the init() function or as
376*1fa6dee9SAndroid Build Coastguard Worker// part of a package-scoped variable's initialization.
377*1fa6dee9SAndroid Build Coastguard Worker//
378*1fa6dee9SAndroid Build Coastguard Worker// This function is usually used to initialize a package-scoped Go variable that
379*1fa6dee9SAndroid Build Coastguard Worker// represents a Ninja variable that will be output.  The name argument should
380*1fa6dee9SAndroid Build Coastguard Worker// exactly match the Go variable name, and the value string returned by method
381*1fa6dee9SAndroid Build Coastguard Worker// may reference other Ninja variables that are visible within the calling Go
382*1fa6dee9SAndroid Build Coastguard Worker// package.
383*1fa6dee9SAndroid Build Coastguard Workerfunc (p *packageContext) VariableConfigMethod(name string,
384*1fa6dee9SAndroid Build Coastguard Worker	method interface{}) Variable {
385*1fa6dee9SAndroid Build Coastguard Worker
386*1fa6dee9SAndroid Build Coastguard Worker	checkCalledFromInit()
387*1fa6dee9SAndroid Build Coastguard Worker
388*1fa6dee9SAndroid Build Coastguard Worker	err := validateNinjaName(name)
389*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
390*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
391*1fa6dee9SAndroid Build Coastguard Worker	}
392*1fa6dee9SAndroid Build Coastguard Worker
393*1fa6dee9SAndroid Build Coastguard Worker	methodValue := reflect.ValueOf(method)
394*1fa6dee9SAndroid Build Coastguard Worker	validateVariableMethod(name, methodValue)
395*1fa6dee9SAndroid Build Coastguard Worker
396*1fa6dee9SAndroid Build Coastguard Worker	fun := func(ctx VariableFuncContext, config interface{}) (string, error) {
397*1fa6dee9SAndroid Build Coastguard Worker		result := methodValue.Call([]reflect.Value{reflect.ValueOf(config)})
398*1fa6dee9SAndroid Build Coastguard Worker		resultStr := result[0].Interface().(string)
399*1fa6dee9SAndroid Build Coastguard Worker		return resultStr, nil
400*1fa6dee9SAndroid Build Coastguard Worker	}
401*1fa6dee9SAndroid Build Coastguard Worker
402*1fa6dee9SAndroid Build Coastguard Worker	v := &variableFunc{
403*1fa6dee9SAndroid Build Coastguard Worker		pctx:   p,
404*1fa6dee9SAndroid Build Coastguard Worker		name_:  name,
405*1fa6dee9SAndroid Build Coastguard Worker		value_: fun,
406*1fa6dee9SAndroid Build Coastguard Worker	}
407*1fa6dee9SAndroid Build Coastguard Worker	err = p.scope.AddVariable(v)
408*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
409*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
410*1fa6dee9SAndroid Build Coastguard Worker	}
411*1fa6dee9SAndroid Build Coastguard Worker
412*1fa6dee9SAndroid Build Coastguard Worker	return v
413*1fa6dee9SAndroid Build Coastguard Worker}
414*1fa6dee9SAndroid Build Coastguard Worker
415*1fa6dee9SAndroid Build Coastguard Workerfunc (v *variableFunc) packageContext() *packageContext {
416*1fa6dee9SAndroid Build Coastguard Worker	return v.pctx
417*1fa6dee9SAndroid Build Coastguard Worker}
418*1fa6dee9SAndroid Build Coastguard Worker
419*1fa6dee9SAndroid Build Coastguard Workerfunc (v *variableFunc) name() string {
420*1fa6dee9SAndroid Build Coastguard Worker	return v.name_
421*1fa6dee9SAndroid Build Coastguard Worker}
422*1fa6dee9SAndroid Build Coastguard Worker
423*1fa6dee9SAndroid Build Coastguard Workerfunc (v *variableFunc) fullName(pkgNames map[*packageContext]string) string {
424*1fa6dee9SAndroid Build Coastguard Worker	return packageNamespacePrefix(pkgNames[v.pctx]) + v.name_
425*1fa6dee9SAndroid Build Coastguard Worker}
426*1fa6dee9SAndroid Build Coastguard Worker
427*1fa6dee9SAndroid Build Coastguard Workerfunc (v *variableFunc) value(ctx VariableFuncContext, config interface{}) (*ninjaString, error) {
428*1fa6dee9SAndroid Build Coastguard Worker	value, err := v.value_(ctx, config)
429*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
430*1fa6dee9SAndroid Build Coastguard Worker		return nil, err
431*1fa6dee9SAndroid Build Coastguard Worker	}
432*1fa6dee9SAndroid Build Coastguard Worker
433*1fa6dee9SAndroid Build Coastguard Worker	ninjaStr, err := parseNinjaString(v.pctx.scope, value)
434*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
435*1fa6dee9SAndroid Build Coastguard Worker		err = fmt.Errorf("error parsing variable %s value: %s", v, err)
436*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
437*1fa6dee9SAndroid Build Coastguard Worker	}
438*1fa6dee9SAndroid Build Coastguard Worker
439*1fa6dee9SAndroid Build Coastguard Worker	return ninjaStr, nil
440*1fa6dee9SAndroid Build Coastguard Worker}
441*1fa6dee9SAndroid Build Coastguard Worker
442*1fa6dee9SAndroid Build Coastguard Workerfunc (v *variableFunc) String() string {
443*1fa6dee9SAndroid Build Coastguard Worker	return v.pctx.pkgPath + "." + v.name_
444*1fa6dee9SAndroid Build Coastguard Worker}
445*1fa6dee9SAndroid Build Coastguard Worker
446*1fa6dee9SAndroid Build Coastguard Workerfunc validateVariableMethod(name string, methodValue reflect.Value) {
447*1fa6dee9SAndroid Build Coastguard Worker	methodType := methodValue.Type()
448*1fa6dee9SAndroid Build Coastguard Worker	if methodType.Kind() != reflect.Func {
449*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("method given for variable %s is not a function",
450*1fa6dee9SAndroid Build Coastguard Worker			name))
451*1fa6dee9SAndroid Build Coastguard Worker	}
452*1fa6dee9SAndroid Build Coastguard Worker	if n := methodType.NumIn(); n != 1 {
453*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("method for variable %s has %d inputs (should be 1)",
454*1fa6dee9SAndroid Build Coastguard Worker			name, n))
455*1fa6dee9SAndroid Build Coastguard Worker	}
456*1fa6dee9SAndroid Build Coastguard Worker	if n := methodType.NumOut(); n != 1 {
457*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("method for variable %s has %d outputs (should be 1)",
458*1fa6dee9SAndroid Build Coastguard Worker			name, n))
459*1fa6dee9SAndroid Build Coastguard Worker	}
460*1fa6dee9SAndroid Build Coastguard Worker	if kind := methodType.Out(0).Kind(); kind != reflect.String {
461*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("method for variable %s does not return a string",
462*1fa6dee9SAndroid Build Coastguard Worker			name))
463*1fa6dee9SAndroid Build Coastguard Worker	}
464*1fa6dee9SAndroid Build Coastguard Worker}
465*1fa6dee9SAndroid Build Coastguard Worker
466*1fa6dee9SAndroid Build Coastguard Worker// An argVariable is a Variable that exists only when it is set by a build
467*1fa6dee9SAndroid Build Coastguard Worker// statement to pass a value to the rule being invoked.  It has no value, so it
468*1fa6dee9SAndroid Build Coastguard Worker// can never be used to create a Ninja assignment statement.  It is inserted
469*1fa6dee9SAndroid Build Coastguard Worker// into the rule's scope, which is used for name lookups within the rule and
470*1fa6dee9SAndroid Build Coastguard Worker// when assigning argument values as part of a build statement.
471*1fa6dee9SAndroid Build Coastguard Workertype argVariable struct {
472*1fa6dee9SAndroid Build Coastguard Worker	name_ string
473*1fa6dee9SAndroid Build Coastguard Worker}
474*1fa6dee9SAndroid Build Coastguard Worker
475*1fa6dee9SAndroid Build Coastguard Workerfunc (v *argVariable) packageContext() *packageContext {
476*1fa6dee9SAndroid Build Coastguard Worker	panic("this should not be called")
477*1fa6dee9SAndroid Build Coastguard Worker}
478*1fa6dee9SAndroid Build Coastguard Worker
479*1fa6dee9SAndroid Build Coastguard Workerfunc (v *argVariable) name() string {
480*1fa6dee9SAndroid Build Coastguard Worker	return v.name_
481*1fa6dee9SAndroid Build Coastguard Worker}
482*1fa6dee9SAndroid Build Coastguard Worker
483*1fa6dee9SAndroid Build Coastguard Workerfunc (v *argVariable) fullName(pkgNames map[*packageContext]string) string {
484*1fa6dee9SAndroid Build Coastguard Worker	return v.name_
485*1fa6dee9SAndroid Build Coastguard Worker}
486*1fa6dee9SAndroid Build Coastguard Worker
487*1fa6dee9SAndroid Build Coastguard Workerfunc (v *argVariable) value(ctx VariableFuncContext, config interface{}) (*ninjaString, error) {
488*1fa6dee9SAndroid Build Coastguard Worker	return nil, errVariableIsArg
489*1fa6dee9SAndroid Build Coastguard Worker}
490*1fa6dee9SAndroid Build Coastguard Worker
491*1fa6dee9SAndroid Build Coastguard Workerfunc (v *argVariable) String() string {
492*1fa6dee9SAndroid Build Coastguard Worker	return "<arg>:" + v.name_
493*1fa6dee9SAndroid Build Coastguard Worker}
494*1fa6dee9SAndroid Build Coastguard Worker
495*1fa6dee9SAndroid Build Coastguard Workertype staticPool struct {
496*1fa6dee9SAndroid Build Coastguard Worker	pctx   *packageContext
497*1fa6dee9SAndroid Build Coastguard Worker	name_  string
498*1fa6dee9SAndroid Build Coastguard Worker	params PoolParams
499*1fa6dee9SAndroid Build Coastguard Worker}
500*1fa6dee9SAndroid Build Coastguard Worker
501*1fa6dee9SAndroid Build Coastguard Worker// StaticPool returns a Pool whose value does not depend on any configuration
502*1fa6dee9SAndroid Build Coastguard Worker// information.  It may only be called during a Go package's initialization -
503*1fa6dee9SAndroid Build Coastguard Worker// either from the init() function or as part of a package-scoped Go variable's
504*1fa6dee9SAndroid Build Coastguard Worker// initialization.
505*1fa6dee9SAndroid Build Coastguard Worker//
506*1fa6dee9SAndroid Build Coastguard Worker// This function is usually used to initialize a package-scoped Go variable that
507*1fa6dee9SAndroid Build Coastguard Worker// represents a Ninja pool that will be output.  The name argument should
508*1fa6dee9SAndroid Build Coastguard Worker// exactly match the Go variable name, and the params fields may reference other
509*1fa6dee9SAndroid Build Coastguard Worker// Ninja variables that are visible within the calling Go package.
510*1fa6dee9SAndroid Build Coastguard Workerfunc (p *packageContext) StaticPool(name string, params PoolParams) Pool {
511*1fa6dee9SAndroid Build Coastguard Worker	checkCalledFromInit()
512*1fa6dee9SAndroid Build Coastguard Worker
513*1fa6dee9SAndroid Build Coastguard Worker	err := validateNinjaName(name)
514*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
515*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
516*1fa6dee9SAndroid Build Coastguard Worker	}
517*1fa6dee9SAndroid Build Coastguard Worker
518*1fa6dee9SAndroid Build Coastguard Worker	pool := &staticPool{
519*1fa6dee9SAndroid Build Coastguard Worker		pctx:   p,
520*1fa6dee9SAndroid Build Coastguard Worker		name_:  name,
521*1fa6dee9SAndroid Build Coastguard Worker		params: params,
522*1fa6dee9SAndroid Build Coastguard Worker	}
523*1fa6dee9SAndroid Build Coastguard Worker	err = p.scope.AddPool(pool)
524*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
525*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
526*1fa6dee9SAndroid Build Coastguard Worker	}
527*1fa6dee9SAndroid Build Coastguard Worker
528*1fa6dee9SAndroid Build Coastguard Worker	return pool
529*1fa6dee9SAndroid Build Coastguard Worker}
530*1fa6dee9SAndroid Build Coastguard Worker
531*1fa6dee9SAndroid Build Coastguard Workerfunc (p *staticPool) packageContext() *packageContext {
532*1fa6dee9SAndroid Build Coastguard Worker	return p.pctx
533*1fa6dee9SAndroid Build Coastguard Worker}
534*1fa6dee9SAndroid Build Coastguard Worker
535*1fa6dee9SAndroid Build Coastguard Workerfunc (p *staticPool) name() string {
536*1fa6dee9SAndroid Build Coastguard Worker	return p.name_
537*1fa6dee9SAndroid Build Coastguard Worker}
538*1fa6dee9SAndroid Build Coastguard Worker
539*1fa6dee9SAndroid Build Coastguard Workerfunc (p *staticPool) fullName(pkgNames map[*packageContext]string) string {
540*1fa6dee9SAndroid Build Coastguard Worker	return packageNamespacePrefix(pkgNames[p.pctx]) + p.name_
541*1fa6dee9SAndroid Build Coastguard Worker}
542*1fa6dee9SAndroid Build Coastguard Worker
543*1fa6dee9SAndroid Build Coastguard Workerfunc (p *staticPool) def(config interface{}) (*poolDef, error) {
544*1fa6dee9SAndroid Build Coastguard Worker	def, err := parsePoolParams(p.pctx.scope, &p.params)
545*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
546*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("error parsing PoolParams for %s: %s", p, err))
547*1fa6dee9SAndroid Build Coastguard Worker	}
548*1fa6dee9SAndroid Build Coastguard Worker	return def, nil
549*1fa6dee9SAndroid Build Coastguard Worker}
550*1fa6dee9SAndroid Build Coastguard Worker
551*1fa6dee9SAndroid Build Coastguard Workerfunc (p *staticPool) String() string {
552*1fa6dee9SAndroid Build Coastguard Worker	return p.pctx.pkgPath + "." + p.name_
553*1fa6dee9SAndroid Build Coastguard Worker}
554*1fa6dee9SAndroid Build Coastguard Worker
555*1fa6dee9SAndroid Build Coastguard Workertype poolFunc struct {
556*1fa6dee9SAndroid Build Coastguard Worker	pctx       *packageContext
557*1fa6dee9SAndroid Build Coastguard Worker	name_      string
558*1fa6dee9SAndroid Build Coastguard Worker	paramsFunc func(interface{}) (PoolParams, error)
559*1fa6dee9SAndroid Build Coastguard Worker}
560*1fa6dee9SAndroid Build Coastguard Worker
561*1fa6dee9SAndroid Build Coastguard Worker// PoolFunc returns a Pool whose value is determined by a function that takes a
562*1fa6dee9SAndroid Build Coastguard Worker// config object as input and returns either the pool parameters or an error. It
563*1fa6dee9SAndroid Build Coastguard Worker// may only be called during a Go package's initialization - either from the
564*1fa6dee9SAndroid Build Coastguard Worker// init() function or as part of a package-scoped variable's initialization.
565*1fa6dee9SAndroid Build Coastguard Worker//
566*1fa6dee9SAndroid Build Coastguard Worker// This function is usually used to initialize a package-scoped Go variable that
567*1fa6dee9SAndroid Build Coastguard Worker// represents a Ninja pool that will be output.  The name argument should
568*1fa6dee9SAndroid Build Coastguard Worker// exactly match the Go variable name, and the string fields of the PoolParams
569*1fa6dee9SAndroid Build Coastguard Worker// returned by f may reference other Ninja variables that are visible within the
570*1fa6dee9SAndroid Build Coastguard Worker// calling Go package.
571*1fa6dee9SAndroid Build Coastguard Workerfunc (p *packageContext) PoolFunc(name string, f func(interface{}) (PoolParams,
572*1fa6dee9SAndroid Build Coastguard Worker	error)) Pool {
573*1fa6dee9SAndroid Build Coastguard Worker
574*1fa6dee9SAndroid Build Coastguard Worker	checkCalledFromInit()
575*1fa6dee9SAndroid Build Coastguard Worker
576*1fa6dee9SAndroid Build Coastguard Worker	err := validateNinjaName(name)
577*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
578*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
579*1fa6dee9SAndroid Build Coastguard Worker	}
580*1fa6dee9SAndroid Build Coastguard Worker
581*1fa6dee9SAndroid Build Coastguard Worker	pool := &poolFunc{
582*1fa6dee9SAndroid Build Coastguard Worker		pctx:       p,
583*1fa6dee9SAndroid Build Coastguard Worker		name_:      name,
584*1fa6dee9SAndroid Build Coastguard Worker		paramsFunc: f,
585*1fa6dee9SAndroid Build Coastguard Worker	}
586*1fa6dee9SAndroid Build Coastguard Worker	err = p.scope.AddPool(pool)
587*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
588*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
589*1fa6dee9SAndroid Build Coastguard Worker	}
590*1fa6dee9SAndroid Build Coastguard Worker
591*1fa6dee9SAndroid Build Coastguard Worker	return pool
592*1fa6dee9SAndroid Build Coastguard Worker}
593*1fa6dee9SAndroid Build Coastguard Worker
594*1fa6dee9SAndroid Build Coastguard Workerfunc (p *poolFunc) packageContext() *packageContext {
595*1fa6dee9SAndroid Build Coastguard Worker	return p.pctx
596*1fa6dee9SAndroid Build Coastguard Worker}
597*1fa6dee9SAndroid Build Coastguard Worker
598*1fa6dee9SAndroid Build Coastguard Workerfunc (p *poolFunc) name() string {
599*1fa6dee9SAndroid Build Coastguard Worker	return p.name_
600*1fa6dee9SAndroid Build Coastguard Worker}
601*1fa6dee9SAndroid Build Coastguard Worker
602*1fa6dee9SAndroid Build Coastguard Workerfunc (p *poolFunc) fullName(pkgNames map[*packageContext]string) string {
603*1fa6dee9SAndroid Build Coastguard Worker	return packageNamespacePrefix(pkgNames[p.pctx]) + p.name_
604*1fa6dee9SAndroid Build Coastguard Worker}
605*1fa6dee9SAndroid Build Coastguard Worker
606*1fa6dee9SAndroid Build Coastguard Workerfunc (p *poolFunc) def(config interface{}) (*poolDef, error) {
607*1fa6dee9SAndroid Build Coastguard Worker	params, err := p.paramsFunc(config)
608*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
609*1fa6dee9SAndroid Build Coastguard Worker		return nil, err
610*1fa6dee9SAndroid Build Coastguard Worker	}
611*1fa6dee9SAndroid Build Coastguard Worker	def, err := parsePoolParams(p.pctx.scope, &params)
612*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
613*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("error parsing PoolParams for %s: %s", p, err))
614*1fa6dee9SAndroid Build Coastguard Worker	}
615*1fa6dee9SAndroid Build Coastguard Worker	return def, nil
616*1fa6dee9SAndroid Build Coastguard Worker}
617*1fa6dee9SAndroid Build Coastguard Worker
618*1fa6dee9SAndroid Build Coastguard Workerfunc (p *poolFunc) String() string {
619*1fa6dee9SAndroid Build Coastguard Worker	return p.pctx.pkgPath + "." + p.name_
620*1fa6dee9SAndroid Build Coastguard Worker}
621*1fa6dee9SAndroid Build Coastguard Worker
622*1fa6dee9SAndroid Build Coastguard Workertype builtinPool struct {
623*1fa6dee9SAndroid Build Coastguard Worker	name_ string
624*1fa6dee9SAndroid Build Coastguard Worker}
625*1fa6dee9SAndroid Build Coastguard Worker
626*1fa6dee9SAndroid Build Coastguard Workerfunc (p *builtinPool) packageContext() *packageContext {
627*1fa6dee9SAndroid Build Coastguard Worker	return nil
628*1fa6dee9SAndroid Build Coastguard Worker}
629*1fa6dee9SAndroid Build Coastguard Worker
630*1fa6dee9SAndroid Build Coastguard Workerfunc (p *builtinPool) name() string {
631*1fa6dee9SAndroid Build Coastguard Worker	return p.name_
632*1fa6dee9SAndroid Build Coastguard Worker}
633*1fa6dee9SAndroid Build Coastguard Worker
634*1fa6dee9SAndroid Build Coastguard Workerfunc (p *builtinPool) fullName(pkgNames map[*packageContext]string) string {
635*1fa6dee9SAndroid Build Coastguard Worker	return p.name_
636*1fa6dee9SAndroid Build Coastguard Worker}
637*1fa6dee9SAndroid Build Coastguard Worker
638*1fa6dee9SAndroid Build Coastguard Workerfunc (p *builtinPool) def(config interface{}) (*poolDef, error) {
639*1fa6dee9SAndroid Build Coastguard Worker	return nil, errPoolIsBuiltin
640*1fa6dee9SAndroid Build Coastguard Worker}
641*1fa6dee9SAndroid Build Coastguard Worker
642*1fa6dee9SAndroid Build Coastguard Worker// NewBuiltinPool returns a Pool object that refers to a pool name created outside of Blueprint
643*1fa6dee9SAndroid Build Coastguard Workerfunc NewBuiltinPool(name string) Pool {
644*1fa6dee9SAndroid Build Coastguard Worker	return &builtinPool{
645*1fa6dee9SAndroid Build Coastguard Worker		name_: name,
646*1fa6dee9SAndroid Build Coastguard Worker	}
647*1fa6dee9SAndroid Build Coastguard Worker}
648*1fa6dee9SAndroid Build Coastguard Worker
649*1fa6dee9SAndroid Build Coastguard Workerfunc (p *builtinPool) String() string {
650*1fa6dee9SAndroid Build Coastguard Worker	return "<builtin>:" + p.name_
651*1fa6dee9SAndroid Build Coastguard Worker}
652*1fa6dee9SAndroid Build Coastguard Worker
653*1fa6dee9SAndroid Build Coastguard Workertype staticRule struct {
654*1fa6dee9SAndroid Build Coastguard Worker	pctx       *packageContext
655*1fa6dee9SAndroid Build Coastguard Worker	name_      string
656*1fa6dee9SAndroid Build Coastguard Worker	params     RuleParams
657*1fa6dee9SAndroid Build Coastguard Worker	argNames   map[string]bool
658*1fa6dee9SAndroid Build Coastguard Worker	scope_     *basicScope
659*1fa6dee9SAndroid Build Coastguard Worker	sync.Mutex // protects scope_ during lazy creation
660*1fa6dee9SAndroid Build Coastguard Worker}
661*1fa6dee9SAndroid Build Coastguard Worker
662*1fa6dee9SAndroid Build Coastguard Worker// StaticRule returns a Rule whose value does not depend on any configuration
663*1fa6dee9SAndroid Build Coastguard Worker// information.  It may only be called during a Go package's initialization -
664*1fa6dee9SAndroid Build Coastguard Worker// either from the init() function or as part of a package-scoped Go variable's
665*1fa6dee9SAndroid Build Coastguard Worker// initialization.
666*1fa6dee9SAndroid Build Coastguard Worker//
667*1fa6dee9SAndroid Build Coastguard Worker// This function is usually used to initialize a package-scoped Go variable that
668*1fa6dee9SAndroid Build Coastguard Worker// represents a Ninja rule that will be output.  The name argument should
669*1fa6dee9SAndroid Build Coastguard Worker// exactly match the Go variable name, and the params fields may reference other
670*1fa6dee9SAndroid Build Coastguard Worker// Ninja variables that are visible within the calling Go package.
671*1fa6dee9SAndroid Build Coastguard Worker//
672*1fa6dee9SAndroid Build Coastguard Worker// The argNames arguments list Ninja variables that may be overridden by Ninja
673*1fa6dee9SAndroid Build Coastguard Worker// build statements that invoke the rule.  These arguments may be referenced in
674*1fa6dee9SAndroid Build Coastguard Worker// any of the string fields of params.  Arguments can shadow package-scoped
675*1fa6dee9SAndroid Build Coastguard Worker// variables defined within the caller's Go package, but they may not shadow
676*1fa6dee9SAndroid Build Coastguard Worker// those defined in another package.  Shadowing a package-scoped variable
677*1fa6dee9SAndroid Build Coastguard Worker// results in the package-scoped variable's value being used for build
678*1fa6dee9SAndroid Build Coastguard Worker// statements that do not override the argument.  For argument names that do not
679*1fa6dee9SAndroid Build Coastguard Worker// shadow package-scoped variables the default value is an empty string.
680*1fa6dee9SAndroid Build Coastguard Workerfunc (p *packageContext) StaticRule(name string, params RuleParams,
681*1fa6dee9SAndroid Build Coastguard Worker	argNames ...string) Rule {
682*1fa6dee9SAndroid Build Coastguard Worker
683*1fa6dee9SAndroid Build Coastguard Worker	checkCalledFromInit()
684*1fa6dee9SAndroid Build Coastguard Worker
685*1fa6dee9SAndroid Build Coastguard Worker	err := validateNinjaName(name)
686*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
687*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
688*1fa6dee9SAndroid Build Coastguard Worker	}
689*1fa6dee9SAndroid Build Coastguard Worker
690*1fa6dee9SAndroid Build Coastguard Worker	err = validateArgNames(argNames)
691*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
692*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("invalid argument name: %s", err))
693*1fa6dee9SAndroid Build Coastguard Worker	}
694*1fa6dee9SAndroid Build Coastguard Worker
695*1fa6dee9SAndroid Build Coastguard Worker	argNamesSet := make(map[string]bool)
696*1fa6dee9SAndroid Build Coastguard Worker	for _, argName := range argNames {
697*1fa6dee9SAndroid Build Coastguard Worker		argNamesSet[argName] = true
698*1fa6dee9SAndroid Build Coastguard Worker	}
699*1fa6dee9SAndroid Build Coastguard Worker
700*1fa6dee9SAndroid Build Coastguard Worker	ruleScope := (*basicScope)(nil) // This will get created lazily
701*1fa6dee9SAndroid Build Coastguard Worker
702*1fa6dee9SAndroid Build Coastguard Worker	r := &staticRule{
703*1fa6dee9SAndroid Build Coastguard Worker		pctx:     p,
704*1fa6dee9SAndroid Build Coastguard Worker		name_:    name,
705*1fa6dee9SAndroid Build Coastguard Worker		params:   params,
706*1fa6dee9SAndroid Build Coastguard Worker		argNames: argNamesSet,
707*1fa6dee9SAndroid Build Coastguard Worker		scope_:   ruleScope,
708*1fa6dee9SAndroid Build Coastguard Worker	}
709*1fa6dee9SAndroid Build Coastguard Worker	err = p.scope.AddRule(r)
710*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
711*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
712*1fa6dee9SAndroid Build Coastguard Worker	}
713*1fa6dee9SAndroid Build Coastguard Worker
714*1fa6dee9SAndroid Build Coastguard Worker	return r
715*1fa6dee9SAndroid Build Coastguard Worker}
716*1fa6dee9SAndroid Build Coastguard Worker
717*1fa6dee9SAndroid Build Coastguard Workerfunc (r *staticRule) packageContext() *packageContext {
718*1fa6dee9SAndroid Build Coastguard Worker	return r.pctx
719*1fa6dee9SAndroid Build Coastguard Worker}
720*1fa6dee9SAndroid Build Coastguard Worker
721*1fa6dee9SAndroid Build Coastguard Workerfunc (r *staticRule) name() string {
722*1fa6dee9SAndroid Build Coastguard Worker	return r.name_
723*1fa6dee9SAndroid Build Coastguard Worker}
724*1fa6dee9SAndroid Build Coastguard Worker
725*1fa6dee9SAndroid Build Coastguard Workerfunc (r *staticRule) fullName(pkgNames map[*packageContext]string) string {
726*1fa6dee9SAndroid Build Coastguard Worker	return packageNamespacePrefix(pkgNames[r.pctx]) + r.name_
727*1fa6dee9SAndroid Build Coastguard Worker}
728*1fa6dee9SAndroid Build Coastguard Worker
729*1fa6dee9SAndroid Build Coastguard Workerfunc (r *staticRule) def(interface{}) (*ruleDef, error) {
730*1fa6dee9SAndroid Build Coastguard Worker	def, err := parseRuleParams(r.scope(), &r.params)
731*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
732*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("error parsing RuleParams for %s: %s", r, err))
733*1fa6dee9SAndroid Build Coastguard Worker	}
734*1fa6dee9SAndroid Build Coastguard Worker	return def, nil
735*1fa6dee9SAndroid Build Coastguard Worker}
736*1fa6dee9SAndroid Build Coastguard Worker
737*1fa6dee9SAndroid Build Coastguard Workerfunc (r *staticRule) scope() *basicScope {
738*1fa6dee9SAndroid Build Coastguard Worker	// We lazily create the scope so that all the package-scoped variables get
739*1fa6dee9SAndroid Build Coastguard Worker	// declared before the args are created.  Otherwise we could incorrectly
740*1fa6dee9SAndroid Build Coastguard Worker	// shadow a package-scoped variable with an arg variable.
741*1fa6dee9SAndroid Build Coastguard Worker	r.Lock()
742*1fa6dee9SAndroid Build Coastguard Worker	defer r.Unlock()
743*1fa6dee9SAndroid Build Coastguard Worker
744*1fa6dee9SAndroid Build Coastguard Worker	if r.scope_ == nil {
745*1fa6dee9SAndroid Build Coastguard Worker		r.scope_ = makeRuleScope(r.pctx.scope, r.argNames)
746*1fa6dee9SAndroid Build Coastguard Worker	}
747*1fa6dee9SAndroid Build Coastguard Worker	return r.scope_
748*1fa6dee9SAndroid Build Coastguard Worker}
749*1fa6dee9SAndroid Build Coastguard Worker
750*1fa6dee9SAndroid Build Coastguard Workerfunc (r *staticRule) isArg(argName string) bool {
751*1fa6dee9SAndroid Build Coastguard Worker	return r.argNames[argName]
752*1fa6dee9SAndroid Build Coastguard Worker}
753*1fa6dee9SAndroid Build Coastguard Worker
754*1fa6dee9SAndroid Build Coastguard Workerfunc (r *staticRule) String() string {
755*1fa6dee9SAndroid Build Coastguard Worker	return r.pctx.pkgPath + "." + r.name_
756*1fa6dee9SAndroid Build Coastguard Worker}
757*1fa6dee9SAndroid Build Coastguard Worker
758*1fa6dee9SAndroid Build Coastguard Workertype ruleFunc struct {
759*1fa6dee9SAndroid Build Coastguard Worker	pctx       *packageContext
760*1fa6dee9SAndroid Build Coastguard Worker	name_      string
761*1fa6dee9SAndroid Build Coastguard Worker	paramsFunc func(interface{}) (RuleParams, error)
762*1fa6dee9SAndroid Build Coastguard Worker	argNames   map[string]bool
763*1fa6dee9SAndroid Build Coastguard Worker	scope_     *basicScope
764*1fa6dee9SAndroid Build Coastguard Worker	sync.Mutex // protects scope_ during lazy creation
765*1fa6dee9SAndroid Build Coastguard Worker}
766*1fa6dee9SAndroid Build Coastguard Worker
767*1fa6dee9SAndroid Build Coastguard Worker// RuleFunc returns a Rule whose value is determined by a function that takes a
768*1fa6dee9SAndroid Build Coastguard Worker// config object as input and returns either the rule parameters or an error. It
769*1fa6dee9SAndroid Build Coastguard Worker// may only be called during a Go package's initialization - either from the
770*1fa6dee9SAndroid Build Coastguard Worker// init() function or as part of a package-scoped variable's initialization.
771*1fa6dee9SAndroid Build Coastguard Worker//
772*1fa6dee9SAndroid Build Coastguard Worker// This function is usually used to initialize a package-scoped Go variable that
773*1fa6dee9SAndroid Build Coastguard Worker// represents a Ninja rule that will be output.  The name argument should
774*1fa6dee9SAndroid Build Coastguard Worker// exactly match the Go variable name, and the string fields of the RuleParams
775*1fa6dee9SAndroid Build Coastguard Worker// returned by f may reference other Ninja variables that are visible within the
776*1fa6dee9SAndroid Build Coastguard Worker// calling Go package.
777*1fa6dee9SAndroid Build Coastguard Worker//
778*1fa6dee9SAndroid Build Coastguard Worker// The argNames arguments list Ninja variables that may be overridden by Ninja
779*1fa6dee9SAndroid Build Coastguard Worker// build statements that invoke the rule.  These arguments may be referenced in
780*1fa6dee9SAndroid Build Coastguard Worker// any of the string fields of the RuleParams returned by f.  Arguments can
781*1fa6dee9SAndroid Build Coastguard Worker// shadow package-scoped variables defined within the caller's Go package, but
782*1fa6dee9SAndroid Build Coastguard Worker// they may not shadow those defined in another package.  Shadowing a package-
783*1fa6dee9SAndroid Build Coastguard Worker// scoped variable results in the package-scoped variable's value being used for
784*1fa6dee9SAndroid Build Coastguard Worker// build statements that do not override the argument.  For argument names that
785*1fa6dee9SAndroid Build Coastguard Worker// do not shadow package-scoped variables the default value is an empty string.
786*1fa6dee9SAndroid Build Coastguard Workerfunc (p *packageContext) RuleFunc(name string, f func(interface{}) (RuleParams,
787*1fa6dee9SAndroid Build Coastguard Worker	error), argNames ...string) Rule {
788*1fa6dee9SAndroid Build Coastguard Worker
789*1fa6dee9SAndroid Build Coastguard Worker	checkCalledFromInit()
790*1fa6dee9SAndroid Build Coastguard Worker
791*1fa6dee9SAndroid Build Coastguard Worker	err := validateNinjaName(name)
792*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
793*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
794*1fa6dee9SAndroid Build Coastguard Worker	}
795*1fa6dee9SAndroid Build Coastguard Worker
796*1fa6dee9SAndroid Build Coastguard Worker	err = validateArgNames(argNames)
797*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
798*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("invalid argument name: %s", err))
799*1fa6dee9SAndroid Build Coastguard Worker	}
800*1fa6dee9SAndroid Build Coastguard Worker
801*1fa6dee9SAndroid Build Coastguard Worker	argNamesSet := make(map[string]bool)
802*1fa6dee9SAndroid Build Coastguard Worker	for _, argName := range argNames {
803*1fa6dee9SAndroid Build Coastguard Worker		argNamesSet[argName] = true
804*1fa6dee9SAndroid Build Coastguard Worker	}
805*1fa6dee9SAndroid Build Coastguard Worker
806*1fa6dee9SAndroid Build Coastguard Worker	ruleScope := (*basicScope)(nil) // This will get created lazily
807*1fa6dee9SAndroid Build Coastguard Worker
808*1fa6dee9SAndroid Build Coastguard Worker	rule := &ruleFunc{
809*1fa6dee9SAndroid Build Coastguard Worker		pctx:       p,
810*1fa6dee9SAndroid Build Coastguard Worker		name_:      name,
811*1fa6dee9SAndroid Build Coastguard Worker		paramsFunc: f,
812*1fa6dee9SAndroid Build Coastguard Worker		argNames:   argNamesSet,
813*1fa6dee9SAndroid Build Coastguard Worker		scope_:     ruleScope,
814*1fa6dee9SAndroid Build Coastguard Worker	}
815*1fa6dee9SAndroid Build Coastguard Worker	err = p.scope.AddRule(rule)
816*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
817*1fa6dee9SAndroid Build Coastguard Worker		panic(err)
818*1fa6dee9SAndroid Build Coastguard Worker	}
819*1fa6dee9SAndroid Build Coastguard Worker
820*1fa6dee9SAndroid Build Coastguard Worker	return rule
821*1fa6dee9SAndroid Build Coastguard Worker}
822*1fa6dee9SAndroid Build Coastguard Worker
823*1fa6dee9SAndroid Build Coastguard Workerfunc (r *ruleFunc) packageContext() *packageContext {
824*1fa6dee9SAndroid Build Coastguard Worker	return r.pctx
825*1fa6dee9SAndroid Build Coastguard Worker}
826*1fa6dee9SAndroid Build Coastguard Worker
827*1fa6dee9SAndroid Build Coastguard Workerfunc (r *ruleFunc) name() string {
828*1fa6dee9SAndroid Build Coastguard Worker	return r.name_
829*1fa6dee9SAndroid Build Coastguard Worker}
830*1fa6dee9SAndroid Build Coastguard Worker
831*1fa6dee9SAndroid Build Coastguard Workerfunc (r *ruleFunc) fullName(pkgNames map[*packageContext]string) string {
832*1fa6dee9SAndroid Build Coastguard Worker	return packageNamespacePrefix(pkgNames[r.pctx]) + r.name_
833*1fa6dee9SAndroid Build Coastguard Worker}
834*1fa6dee9SAndroid Build Coastguard Worker
835*1fa6dee9SAndroid Build Coastguard Workerfunc (r *ruleFunc) def(config interface{}) (*ruleDef, error) {
836*1fa6dee9SAndroid Build Coastguard Worker	params, err := r.paramsFunc(config)
837*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
838*1fa6dee9SAndroid Build Coastguard Worker		return nil, err
839*1fa6dee9SAndroid Build Coastguard Worker	}
840*1fa6dee9SAndroid Build Coastguard Worker	def, err := parseRuleParams(r.scope(), &params)
841*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
842*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Errorf("error parsing RuleParams for %s: %s", r, err))
843*1fa6dee9SAndroid Build Coastguard Worker	}
844*1fa6dee9SAndroid Build Coastguard Worker	return def, nil
845*1fa6dee9SAndroid Build Coastguard Worker}
846*1fa6dee9SAndroid Build Coastguard Worker
847*1fa6dee9SAndroid Build Coastguard Workerfunc (r *ruleFunc) scope() *basicScope {
848*1fa6dee9SAndroid Build Coastguard Worker	// We lazily create the scope so that all the global variables get declared
849*1fa6dee9SAndroid Build Coastguard Worker	// before the args are created.  Otherwise we could incorrectly shadow a
850*1fa6dee9SAndroid Build Coastguard Worker	// global variable with an arg variable.
851*1fa6dee9SAndroid Build Coastguard Worker	r.Lock()
852*1fa6dee9SAndroid Build Coastguard Worker	defer r.Unlock()
853*1fa6dee9SAndroid Build Coastguard Worker
854*1fa6dee9SAndroid Build Coastguard Worker	if r.scope_ == nil {
855*1fa6dee9SAndroid Build Coastguard Worker		r.scope_ = makeRuleScope(r.pctx.scope, r.argNames)
856*1fa6dee9SAndroid Build Coastguard Worker	}
857*1fa6dee9SAndroid Build Coastguard Worker	return r.scope_
858*1fa6dee9SAndroid Build Coastguard Worker}
859*1fa6dee9SAndroid Build Coastguard Worker
860*1fa6dee9SAndroid Build Coastguard Workerfunc (r *ruleFunc) isArg(argName string) bool {
861*1fa6dee9SAndroid Build Coastguard Worker	return r.argNames[argName]
862*1fa6dee9SAndroid Build Coastguard Worker}
863*1fa6dee9SAndroid Build Coastguard Worker
864*1fa6dee9SAndroid Build Coastguard Workerfunc (r *ruleFunc) String() string {
865*1fa6dee9SAndroid Build Coastguard Worker	return r.pctx.pkgPath + "." + r.name_
866*1fa6dee9SAndroid Build Coastguard Worker}
867*1fa6dee9SAndroid Build Coastguard Worker
868*1fa6dee9SAndroid Build Coastguard Workertype builtinRule struct {
869*1fa6dee9SAndroid Build Coastguard Worker	name_      string
870*1fa6dee9SAndroid Build Coastguard Worker	scope_     *basicScope
871*1fa6dee9SAndroid Build Coastguard Worker	sync.Mutex // protects scope_ during lazy creation
872*1fa6dee9SAndroid Build Coastguard Worker}
873*1fa6dee9SAndroid Build Coastguard Worker
874*1fa6dee9SAndroid Build Coastguard Workerfunc (r *builtinRule) packageContext() *packageContext {
875*1fa6dee9SAndroid Build Coastguard Worker	return nil
876*1fa6dee9SAndroid Build Coastguard Worker}
877*1fa6dee9SAndroid Build Coastguard Worker
878*1fa6dee9SAndroid Build Coastguard Workerfunc (r *builtinRule) name() string {
879*1fa6dee9SAndroid Build Coastguard Worker	return r.name_
880*1fa6dee9SAndroid Build Coastguard Worker}
881*1fa6dee9SAndroid Build Coastguard Worker
882*1fa6dee9SAndroid Build Coastguard Workerfunc (r *builtinRule) fullName(pkgNames map[*packageContext]string) string {
883*1fa6dee9SAndroid Build Coastguard Worker	return r.name_
884*1fa6dee9SAndroid Build Coastguard Worker}
885*1fa6dee9SAndroid Build Coastguard Worker
886*1fa6dee9SAndroid Build Coastguard Workerfunc (r *builtinRule) def(config interface{}) (*ruleDef, error) {
887*1fa6dee9SAndroid Build Coastguard Worker	return nil, errRuleIsBuiltin
888*1fa6dee9SAndroid Build Coastguard Worker}
889*1fa6dee9SAndroid Build Coastguard Worker
890*1fa6dee9SAndroid Build Coastguard Workerfunc (r *builtinRule) scope() *basicScope {
891*1fa6dee9SAndroid Build Coastguard Worker	r.Lock()
892*1fa6dee9SAndroid Build Coastguard Worker	defer r.Unlock()
893*1fa6dee9SAndroid Build Coastguard Worker
894*1fa6dee9SAndroid Build Coastguard Worker	if r.scope_ == nil {
895*1fa6dee9SAndroid Build Coastguard Worker		r.scope_ = makeRuleScope(nil, nil)
896*1fa6dee9SAndroid Build Coastguard Worker	}
897*1fa6dee9SAndroid Build Coastguard Worker	return r.scope_
898*1fa6dee9SAndroid Build Coastguard Worker}
899*1fa6dee9SAndroid Build Coastguard Worker
900*1fa6dee9SAndroid Build Coastguard Workerfunc (r *builtinRule) isArg(argName string) bool {
901*1fa6dee9SAndroid Build Coastguard Worker	return false
902*1fa6dee9SAndroid Build Coastguard Worker}
903*1fa6dee9SAndroid Build Coastguard Worker
904*1fa6dee9SAndroid Build Coastguard Workerfunc (r *builtinRule) String() string {
905*1fa6dee9SAndroid Build Coastguard Worker	return "<builtin>:" + r.name_
906*1fa6dee9SAndroid Build Coastguard Worker}
907*1fa6dee9SAndroid Build Coastguard Worker
908*1fa6dee9SAndroid Build Coastguard Worker// NewBuiltinRule returns a Rule object that refers to a rule that was created outside of Blueprint
909*1fa6dee9SAndroid Build Coastguard Workerfunc NewBuiltinRule(name string) Rule {
910*1fa6dee9SAndroid Build Coastguard Worker	return &builtinRule{
911*1fa6dee9SAndroid Build Coastguard Worker		name_: name,
912*1fa6dee9SAndroid Build Coastguard Worker	}
913*1fa6dee9SAndroid Build Coastguard Worker}
914*1fa6dee9SAndroid Build Coastguard Worker
915*1fa6dee9SAndroid Build Coastguard Workerfunc (p *packageContext) AddNinjaFileDeps(deps ...string) {
916*1fa6dee9SAndroid Build Coastguard Worker	p.ninjaFileDeps = append(p.ninjaFileDeps, deps...)
917*1fa6dee9SAndroid Build Coastguard Worker}
918