1// Copyright 2015 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package android 16 17import ( 18 "fmt" 19 "runtime" 20 "strings" 21 22 "github.com/google/blueprint" 23 "github.com/google/blueprint/pathtools" 24) 25 26// PackageContext is a wrapper for blueprint.PackageContext that adds 27// some android-specific helper functions. 28type PackageContext struct { 29 blueprint.PackageContext 30} 31 32func NewPackageContext(pkgPath string) PackageContext { 33 return PackageContext{blueprint.NewPackageContext(pkgPath)} 34} 35 36// configErrorWrapper can be used with Path functions when a Context is not 37// available. A Config can be provided, and errors are stored as a list for 38// later retrieval. 39// 40// The most common use here will be with VariableFunc, where only a config is 41// provided, and an error should be returned. 42type configErrorWrapper struct { 43 pctx PackageContext 44 config Config 45 errors []error 46} 47 48var _ PathContext = &configErrorWrapper{} 49var _ errorfContext = &configErrorWrapper{} 50var _ PackageVarContext = &configErrorWrapper{} 51var _ PackagePoolContext = &configErrorWrapper{} 52var _ PackageRuleContext = &configErrorWrapper{} 53 54func (e *configErrorWrapper) Config() Config { 55 return e.config 56} 57func (e *configErrorWrapper) Errorf(format string, args ...interface{}) { 58 e.errors = append(e.errors, fmt.Errorf(format, args...)) 59} 60func (e *configErrorWrapper) AddNinjaFileDeps(deps ...string) { 61 e.pctx.AddNinjaFileDeps(deps...) 62} 63 64func (e *configErrorWrapper) Fs() pathtools.FileSystem { 65 return nil 66} 67 68type PackageVarContext interface { 69 PathContext 70 errorfContext 71} 72 73type PackagePoolContext PackageVarContext 74type PackageRuleContext PackageVarContext 75 76// VariableFunc wraps blueprint.PackageContext.VariableFunc, converting the interface{} config 77// argument to a PackageVarContext. 78func (p PackageContext) VariableFunc(name string, 79 f func(PackageVarContext) string) blueprint.Variable { 80 81 return p.PackageContext.VariableFunc(name, func(config interface{}) (string, error) { 82 ctx := &configErrorWrapper{p, config.(Config), nil} 83 ret := f(ctx) 84 if len(ctx.errors) > 0 { 85 return "", ctx.errors[0] 86 } 87 return ret, nil 88 }) 89} 90 91// PoolFunc wraps blueprint.PackageContext.PoolFunc, converting the interface{} config 92// argument to a Context that supports Config(). 93func (p PackageContext) PoolFunc(name string, 94 f func(PackagePoolContext) blueprint.PoolParams) blueprint.Pool { 95 96 return p.PackageContext.PoolFunc(name, func(config interface{}) (blueprint.PoolParams, error) { 97 ctx := &configErrorWrapper{p, config.(Config), nil} 98 params := f(ctx) 99 if len(ctx.errors) > 0 { 100 return params, ctx.errors[0] 101 } 102 return params, nil 103 }) 104} 105 106// RuleFunc wraps blueprint.PackageContext.RuleFunc, converting the interface{} config 107// argument to a Context that supports Config(). 108func (p PackageContext) RuleFunc(name string, 109 f func(PackageRuleContext) blueprint.RuleParams, argNames ...string) blueprint.Rule { 110 111 return p.PackageContext.RuleFunc(name, func(config interface{}) (blueprint.RuleParams, error) { 112 ctx := &configErrorWrapper{p, config.(Config), nil} 113 params := f(ctx) 114 if len(ctx.errors) > 0 { 115 return params, ctx.errors[0] 116 } 117 return params, nil 118 }, argNames...) 119} 120 121// SourcePathVariable returns a Variable whose value is the source directory 122// appended with the supplied path. It may only be called during a Go package's 123// initialization - either from the init() function or as part of a 124// package-scoped variable's initialization. 125func (p PackageContext) SourcePathVariable(name, path string) blueprint.Variable { 126 return p.VariableFunc(name, func(ctx PackageVarContext) string { 127 p, err := safePathForSource(ctx, path) 128 if err != nil { 129 ctx.Errorf("%s", err.Error()) 130 } 131 return p.String() 132 }) 133} 134 135// SourcePathsVariable returns a Variable whose value is the source directory 136// appended with the supplied paths, joined with separator. It may only be 137// called during a Go package's initialization - either from the init() 138// function or as part of a package-scoped variable's initialization. 139func (p PackageContext) SourcePathsVariable(name, separator string, paths ...string) blueprint.Variable { 140 return p.VariableFunc(name, func(ctx PackageVarContext) string { 141 var ret []string 142 for _, path := range paths { 143 p, err := safePathForSource(ctx, path) 144 if err != nil { 145 ctx.Errorf("%s", err.Error()) 146 } 147 ret = append(ret, p.String()) 148 } 149 return strings.Join(ret, separator) 150 }) 151} 152 153// SourcePathVariableWithEnvOverride returns a Variable whose value is the source directory 154// appended with the supplied path, or the value of the given environment variable if it is set. 155// The environment variable is not required to point to a path inside the source tree. 156// It may only be called during a Go package's initialization - either from the init() function or 157// as part of a package-scoped variable's initialization. 158func (p PackageContext) SourcePathVariableWithEnvOverride(name, path, env string) blueprint.Variable { 159 return p.VariableFunc(name, func(ctx PackageVarContext) string { 160 p, err := safePathForSource(ctx, path) 161 if err != nil { 162 ctx.Errorf("%s", err.Error()) 163 } 164 return ctx.Config().GetenvWithDefault(env, p.String()) 165 }) 166} 167 168// HostBinToolVariable returns a Variable whose value is the path to a host tool 169// in the bin directory for host targets. It may only be called during a Go 170// package's initialization - either from the init() function or as part of a 171// package-scoped variable's initialization. 172func (p PackageContext) HostBinToolVariable(name, path string) blueprint.Variable { 173 return p.VariableFunc(name, func(ctx PackageVarContext) string { 174 return p.HostBinToolPath(ctx, path).String() 175 }) 176} 177 178func (p PackageContext) HostBinToolPath(ctx PackageVarContext, path string) Path { 179 return PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "bin", path) 180} 181 182// HostJNIToolVariable returns a Variable whose value is the path to a host tool 183// in the lib directory for host targets. It may only be called during a Go 184// package's initialization - either from the init() function or as part of a 185// package-scoped variable's initialization. 186func (p PackageContext) HostJNIToolVariable(name, path string) blueprint.Variable { 187 return p.VariableFunc(name, func(ctx PackageVarContext) string { 188 return p.HostJNIToolPath(ctx, path).String() 189 }) 190} 191 192func (p PackageContext) HostJNIToolPath(ctx PackageVarContext, path string) Path { 193 ext := ".so" 194 if runtime.GOOS == "darwin" { 195 ext = ".dylib" 196 } 197 return PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "lib64", path+ext) 198} 199 200// HostJavaToolVariable returns a Variable whose value is the path to a host 201// tool in the frameworks directory for host targets. It may only be called 202// during a Go package's initialization - either from the init() function or as 203// part of a package-scoped variable's initialization. 204func (p PackageContext) HostJavaToolVariable(name, path string) blueprint.Variable { 205 return p.VariableFunc(name, func(ctx PackageVarContext) string { 206 return p.HostJavaToolPath(ctx, path).String() 207 }) 208} 209 210func (p PackageContext) HostJavaToolPath(ctx PackageVarContext, path string) Path { 211 return PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", path) 212} 213 214// IntermediatesPathVariable returns a Variable whose value is the intermediate 215// directory appended with the supplied path. It may only be called during a Go 216// package's initialization - either from the init() function or as part of a 217// package-scoped variable's initialization. 218func (p PackageContext) IntermediatesPathVariable(name, path string) blueprint.Variable { 219 return p.VariableFunc(name, func(ctx PackageVarContext) string { 220 return PathForIntermediates(ctx, path).String() 221 }) 222} 223 224// PrefixedExistentPathsForSourcesVariable returns a Variable whose value is the 225// list of present source paths prefixed with the supplied prefix. It may only 226// be called during a Go package's initialization - either from the init() 227// function or as part of a package-scoped variable's initialization. 228func (p PackageContext) PrefixedExistentPathsForSourcesVariable( 229 name, prefix string, paths []string) blueprint.Variable { 230 231 return p.VariableFunc(name, func(ctx PackageVarContext) string { 232 paths := ExistentPathsForSources(ctx, paths) 233 return JoinWithPrefix(paths.Strings(), prefix) 234 }) 235} 236 237// AndroidStaticRule wraps blueprint.StaticRule and provides a default Pool if none is specified 238func (p PackageContext) AndroidStaticRule(name string, params blueprint.RuleParams, 239 argNames ...string) blueprint.Rule { 240 return p.AndroidRuleFunc(name, func(PackageRuleContext) blueprint.RuleParams { 241 return params 242 }, argNames...) 243} 244 245// AndroidGomaStaticRule wraps blueprint.StaticRule but uses goma's parallelism if goma is enabled 246func (p PackageContext) AndroidGomaStaticRule(name string, params blueprint.RuleParams, 247 argNames ...string) blueprint.Rule { 248 return p.StaticRule(name, params, argNames...) 249} 250 251func (p PackageContext) AndroidRuleFunc(name string, 252 f func(PackageRuleContext) blueprint.RuleParams, argNames ...string) blueprint.Rule { 253 return p.RuleFunc(name, func(ctx PackageRuleContext) blueprint.RuleParams { 254 params := f(ctx) 255 if ctx.Config().UseGoma() && params.Pool == nil { 256 // When USE_GOMA=true is set and the rule is not supported by goma, restrict jobs to the 257 // local parallelism value 258 params.Pool = localPool 259 } 260 return params 261 }, argNames...) 262} 263