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, ¶ms) 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(), ¶ms) 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