1// Copyright 2017 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 "github.com/google/blueprint" 19) 20 21// SingletonContext 22type SingletonContext interface { 23 blueprintSingletonContext() blueprint.SingletonContext 24 25 Config() Config 26 DeviceConfig() DeviceConfig 27 28 ModuleName(module blueprint.Module) string 29 ModuleDir(module blueprint.Module) string 30 ModuleSubDir(module blueprint.Module) string 31 ModuleType(module blueprint.Module) string 32 BlueprintFile(module blueprint.Module) string 33 34 // ModuleVariantsFromName returns the list of module variants named `name` in the same namespace as `referer` enforcing visibility rules. 35 // Allows generating build actions for `referer` based on the metadata for `name` deferred until the singleton context. 36 ModuleVariantsFromName(referer Module, name string) []Module 37 38 otherModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) 39 40 ModuleErrorf(module blueprint.Module, format string, args ...interface{}) 41 Errorf(format string, args ...interface{}) 42 Failed() bool 43 44 Variable(pctx PackageContext, name, value string) 45 Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule 46 Build(pctx PackageContext, params BuildParams) 47 48 // Phony creates a Make-style phony rule, a rule with no commands that can depend on other 49 // phony rules or real files. Phony can be called on the same name multiple times to add 50 // additional dependencies. 51 Phony(name string, deps ...Path) 52 53 RequireNinjaVersion(major, minor, micro int) 54 55 // SetOutDir sets the value of the top-level "builddir" Ninja variable 56 // that controls where Ninja stores its build log files. This value can be 57 // set at most one time for a single build, later calls are ignored. 58 SetOutDir(pctx PackageContext, value string) 59 60 // Eval takes a string with embedded ninja variables, and returns a string 61 // with all of the variables recursively expanded. Any variables references 62 // are expanded in the scope of the PackageContext. 63 Eval(pctx PackageContext, ninjaStr string) (string, error) 64 65 VisitAllModulesBlueprint(visit func(blueprint.Module)) 66 VisitAllModules(visit func(Module)) 67 VisitAllModuleProxies(visit func(proxy ModuleProxy)) 68 VisitAllModulesIf(pred func(Module) bool, visit func(Module)) 69 70 VisitDirectDeps(module Module, visit func(Module)) 71 VisitDirectDepsIf(module Module, pred func(Module) bool, visit func(Module)) 72 73 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module 74 VisitDepsDepthFirst(module Module, visit func(Module)) 75 // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module 76 VisitDepsDepthFirstIf(module Module, pred func(Module) bool, 77 visit func(Module)) 78 79 VisitAllModuleVariants(module Module, visit func(Module)) 80 81 VisitAllModuleVariantProxies(module Module, visit func(proxy ModuleProxy)) 82 83 PrimaryModule(module Module) Module 84 IsFinalModule(module Module) bool 85 86 AddNinjaFileDeps(deps ...string) 87 88 // GlobWithDeps returns a list of files that match the specified pattern but do not match any 89 // of the patterns in excludes. It also adds efficient dependencies to rerun the primary 90 // builder whenever a file matching the pattern as added or removed, without rerunning if a 91 // file that does not match the pattern is added to a searched directory. 92 GlobWithDeps(pattern string, excludes []string) ([]string, error) 93 94 // OtherModulePropertyErrorf reports an error on the line number of the given property of the given module 95 OtherModulePropertyErrorf(module Module, property string, format string, args ...interface{}) 96 97 // HasMutatorFinished returns true if the given mutator has finished running. 98 // It will panic if given an invalid mutator name. 99 HasMutatorFinished(mutatorName string) bool 100} 101 102type singletonAdaptor struct { 103 Singleton 104 105 buildParams []BuildParams 106 ruleParams map[blueprint.Rule]blueprint.RuleParams 107} 108 109var _ testBuildProvider = (*singletonAdaptor)(nil) 110 111func (s *singletonAdaptor) GenerateBuildActions(ctx blueprint.SingletonContext) { 112 sctx := &singletonContextAdaptor{SingletonContext: ctx} 113 if sctx.Config().captureBuild { 114 sctx.ruleParams = make(map[blueprint.Rule]blueprint.RuleParams) 115 } 116 117 s.Singleton.GenerateBuildActions(sctx) 118 119 s.buildParams = sctx.buildParams 120 s.ruleParams = sctx.ruleParams 121} 122 123func (s *singletonAdaptor) BuildParamsForTests() []BuildParams { 124 return s.buildParams 125} 126 127func (s *singletonAdaptor) RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams { 128 return s.ruleParams 129} 130 131type Singleton interface { 132 GenerateBuildActions(SingletonContext) 133} 134 135type singletonContextAdaptor struct { 136 blueprint.SingletonContext 137 138 buildParams []BuildParams 139 ruleParams map[blueprint.Rule]blueprint.RuleParams 140} 141 142func (s *singletonContextAdaptor) blueprintSingletonContext() blueprint.SingletonContext { 143 return s.SingletonContext 144} 145 146func (s *singletonContextAdaptor) Config() Config { 147 return s.SingletonContext.Config().(Config) 148} 149 150func (s *singletonContextAdaptor) DeviceConfig() DeviceConfig { 151 return DeviceConfig{s.Config().deviceConfig} 152} 153 154func (s *singletonContextAdaptor) Variable(pctx PackageContext, name, value string) { 155 s.SingletonContext.Variable(pctx.PackageContext, name, value) 156} 157 158func (s *singletonContextAdaptor) Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule { 159 if s.Config().UseRemoteBuild() { 160 if params.Pool == nil { 161 // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict 162 // jobs to the local parallelism value 163 params.Pool = localPool 164 } else if params.Pool == remotePool { 165 // remotePool is a fake pool used to identify rule that are supported for remoting. If the rule's 166 // pool is the remotePool, replace with nil so that ninja runs it at NINJA_REMOTE_NUM_JOBS 167 // parallelism. 168 params.Pool = nil 169 } 170 } 171 rule := s.SingletonContext.Rule(pctx.PackageContext, name, params, argNames...) 172 if s.Config().captureBuild { 173 s.ruleParams[rule] = params 174 } 175 return rule 176} 177 178func (s *singletonContextAdaptor) Build(pctx PackageContext, params BuildParams) { 179 if s.Config().captureBuild { 180 s.buildParams = append(s.buildParams, params) 181 } 182 bparams := convertBuildParams(params) 183 s.SingletonContext.Build(pctx.PackageContext, bparams) 184} 185 186func (s *singletonContextAdaptor) Phony(name string, deps ...Path) { 187 addSingletonPhony(s.Config(), name, deps...) 188} 189 190func (s *singletonContextAdaptor) SetOutDir(pctx PackageContext, value string) { 191 s.SingletonContext.SetOutDir(pctx.PackageContext, value) 192} 193 194func (s *singletonContextAdaptor) Eval(pctx PackageContext, ninjaStr string) (string, error) { 195 return s.SingletonContext.Eval(pctx.PackageContext, ninjaStr) 196} 197 198// visitAdaptor wraps a visit function that takes an android.Module parameter into 199// a function that takes a blueprint.Module parameter and only calls the visit function if the 200// blueprint.Module is an android.Module. 201func visitAdaptor(visit func(Module)) func(blueprint.Module) { 202 return func(module blueprint.Module) { 203 if aModule, ok := module.(Module); ok { 204 visit(aModule) 205 } 206 } 207} 208 209// visitProxyAdaptor wraps a visit function that takes an android.ModuleProxy parameter into 210// a function that takes a blueprint.ModuleProxy parameter. 211func visitProxyAdaptor(visit func(proxy ModuleProxy)) func(proxy blueprint.ModuleProxy) { 212 return func(module blueprint.ModuleProxy) { 213 visit(ModuleProxy{ 214 module: module, 215 }) 216 } 217} 218 219// predAdaptor wraps a pred function that takes an android.Module parameter 220// into a function that takes an blueprint.Module parameter and only calls the visit function if the 221// blueprint.Module is an android.Module, otherwise returns false. 222func predAdaptor(pred func(Module) bool) func(blueprint.Module) bool { 223 return func(module blueprint.Module) bool { 224 if aModule, ok := module.(Module); ok { 225 return pred(aModule) 226 } else { 227 return false 228 } 229 } 230} 231 232func (s *singletonContextAdaptor) VisitAllModulesBlueprint(visit func(blueprint.Module)) { 233 s.SingletonContext.VisitAllModules(visit) 234} 235 236func (s *singletonContextAdaptor) VisitAllModules(visit func(Module)) { 237 s.SingletonContext.VisitAllModules(visitAdaptor(visit)) 238} 239 240func (s *singletonContextAdaptor) VisitAllModuleProxies(visit func(proxy ModuleProxy)) { 241 s.SingletonContext.VisitAllModuleProxies(visitProxyAdaptor(visit)) 242} 243 244func (s *singletonContextAdaptor) VisitAllModulesIf(pred func(Module) bool, visit func(Module)) { 245 s.SingletonContext.VisitAllModulesIf(predAdaptor(pred), visitAdaptor(visit)) 246} 247 248func (s *singletonContextAdaptor) VisitDirectDeps(module Module, visit func(Module)) { 249 s.SingletonContext.VisitDirectDeps(module, visitAdaptor(visit)) 250} 251 252func (s *singletonContextAdaptor) VisitDirectDepsIf(module Module, pred func(Module) bool, visit func(Module)) { 253 s.SingletonContext.VisitDirectDepsIf(module, predAdaptor(pred), visitAdaptor(visit)) 254} 255 256func (s *singletonContextAdaptor) VisitDepsDepthFirst(module Module, visit func(Module)) { 257 s.SingletonContext.VisitDepsDepthFirst(module, visitAdaptor(visit)) 258} 259 260func (s *singletonContextAdaptor) VisitDepsDepthFirstIf(module Module, pred func(Module) bool, visit func(Module)) { 261 s.SingletonContext.VisitDepsDepthFirstIf(module, predAdaptor(pred), visitAdaptor(visit)) 262} 263 264func (s *singletonContextAdaptor) VisitAllModuleVariants(module Module, visit func(Module)) { 265 s.SingletonContext.VisitAllModuleVariants(module, visitAdaptor(visit)) 266} 267 268func (s *singletonContextAdaptor) VisitAllModuleVariantProxies(module Module, visit func(proxy ModuleProxy)) { 269 s.SingletonContext.VisitAllModuleVariantProxies(module, visitProxyAdaptor(visit)) 270} 271 272func (s *singletonContextAdaptor) PrimaryModule(module Module) Module { 273 return s.SingletonContext.PrimaryModule(module).(Module) 274} 275 276func (s *singletonContextAdaptor) IsFinalModule(module Module) bool { 277 return s.SingletonContext.IsFinalModule(module) 278} 279 280func (s *singletonContextAdaptor) ModuleVariantsFromName(referer Module, name string) []Module { 281 // get module reference for visibility enforcement 282 qualified := createVisibilityModuleReference(s.ModuleName(referer), s.ModuleDir(referer), referer) 283 284 modules := s.SingletonContext.ModuleVariantsFromName(referer, name) 285 result := make([]Module, 0, len(modules)) 286 for _, m := range modules { 287 if module, ok := m.(Module); ok { 288 // enforce visibility 289 depName := s.ModuleName(module) 290 depDir := s.ModuleDir(module) 291 depQualified := qualifiedModuleName{depDir, depName} 292 // Targets are always visible to other targets in their own package. 293 if depQualified.pkg != qualified.name.pkg { 294 rule := effectiveVisibilityRules(s.Config(), depQualified) 295 if !rule.matches(qualified) { 296 s.ModuleErrorf(referer, "module %q references %q which is not visible to this module\nYou may need to add %q to its visibility", 297 referer.Name(), depQualified, "//"+s.ModuleDir(referer)) 298 continue 299 } 300 } 301 result = append(result, module) 302 } 303 } 304 return result 305} 306 307func (s *singletonContextAdaptor) otherModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) { 308 return s.SingletonContext.ModuleProvider(module, provider) 309} 310 311func (s *singletonContextAdaptor) OtherModulePropertyErrorf(module Module, property string, format string, args ...interface{}) { 312 s.blueprintSingletonContext().OtherModulePropertyErrorf(module, property, format, args...) 313} 314 315func (s *singletonContextAdaptor) HasMutatorFinished(mutatorName string) bool { 316 return s.blueprintSingletonContext().HasMutatorFinished(mutatorName) 317} 318