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 "github.com/google/blueprint" 19 "github.com/google/blueprint/proptools" 20) 21 22// Phases: 23// run Pre-arch mutators 24// run archMutator 25// run Pre-deps mutators 26// run depsMutator 27// run PostDeps mutators 28// continue on to GenerateAndroidBuildActions 29 30func registerMutatorsToContext(ctx *blueprint.Context, mutators []*mutator) { 31 for _, t := range mutators { 32 var handle blueprint.MutatorHandle 33 if t.bottomUpMutator != nil { 34 handle = ctx.RegisterBottomUpMutator(t.name, t.bottomUpMutator) 35 } else if t.topDownMutator != nil { 36 handle = ctx.RegisterTopDownMutator(t.name, t.topDownMutator) 37 } 38 if t.parallel { 39 handle.Parallel() 40 } 41 } 42} 43 44func registerMutators(ctx *blueprint.Context, preArch, preDeps, postDeps []RegisterMutatorFunc) { 45 mctx := ®isterMutatorsContext{} 46 47 register := func(funcs []RegisterMutatorFunc) { 48 for _, f := range funcs { 49 f(mctx) 50 } 51 } 52 53 register(preArch) 54 55 register(preDeps) 56 57 mctx.BottomUp("deps", depsMutator).Parallel() 58 59 register(postDeps) 60 61 registerMutatorsToContext(ctx, mctx.mutators) 62} 63 64type registerMutatorsContext struct { 65 mutators []*mutator 66} 67 68type RegisterMutatorsContext interface { 69 TopDown(name string, m AndroidTopDownMutator) MutatorHandle 70 BottomUp(name string, m AndroidBottomUpMutator) MutatorHandle 71} 72 73type RegisterMutatorFunc func(RegisterMutatorsContext) 74 75var preArch = []RegisterMutatorFunc{ 76 func(ctx RegisterMutatorsContext) { 77 ctx.TopDown("load_hooks", LoadHookMutator).Parallel() 78 }, 79 RegisterNamespaceMutator, 80 RegisterPrebuiltsPreArchMutators, 81 RegisterDefaultsPreArchMutators, 82 RegisterOverridePreArchMutators, 83} 84 85func registerArchMutator(ctx RegisterMutatorsContext) { 86 ctx.BottomUp("arch", archMutator).Parallel() 87 ctx.TopDown("arch_hooks", archHookMutator).Parallel() 88} 89 90var preDeps = []RegisterMutatorFunc{ 91 registerArchMutator, 92} 93 94var postDeps = []RegisterMutatorFunc{ 95 registerPathDepsMutator, 96 RegisterPrebuiltsPostDepsMutators, 97 registerNeverallowMutator, 98} 99 100func PreArchMutators(f RegisterMutatorFunc) { 101 preArch = append(preArch, f) 102} 103 104func PreDepsMutators(f RegisterMutatorFunc) { 105 preDeps = append(preDeps, f) 106} 107 108func PostDepsMutators(f RegisterMutatorFunc) { 109 postDeps = append(postDeps, f) 110} 111 112type AndroidTopDownMutator func(TopDownMutatorContext) 113 114type TopDownMutatorContext interface { 115 BaseModuleContext 116 androidBaseContext 117 118 OtherModuleExists(name string) bool 119 Rename(name string) 120 Module() Module 121 122 OtherModuleName(m blueprint.Module) string 123 OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) 124 OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag 125 126 CreateModule(blueprint.ModuleFactory, ...interface{}) 127 128 GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module 129 GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) 130 131 VisitDirectDeps(visit func(Module)) 132 VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) 133 VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) 134 VisitDepsDepthFirst(visit func(Module)) 135 VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) 136 WalkDeps(visit func(Module, Module) bool) 137 // GetWalkPath is supposed to be called in visit function passed in WalkDeps() 138 // and returns a top-down dependency path from a start module to current child module. 139 GetWalkPath() []Module 140} 141 142type androidTopDownMutatorContext struct { 143 blueprint.TopDownMutatorContext 144 androidBaseContextImpl 145 walkPath []Module 146} 147 148type AndroidBottomUpMutator func(BottomUpMutatorContext) 149 150type BottomUpMutatorContext interface { 151 BaseModuleContext 152 androidBaseContext 153 154 OtherModuleExists(name string) bool 155 Rename(name string) 156 Module() blueprint.Module 157 158 AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) 159 AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string) 160 CreateVariations(...string) []blueprint.Module 161 CreateLocalVariations(...string) []blueprint.Module 162 SetDependencyVariation(string) 163 AddVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string) 164 AddFarVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string) 165 AddInterVariantDependency(tag blueprint.DependencyTag, from, to blueprint.Module) 166 ReplaceDependencies(string) 167} 168 169type androidBottomUpMutatorContext struct { 170 blueprint.BottomUpMutatorContext 171 androidBaseContextImpl 172} 173 174func (x *registerMutatorsContext) BottomUp(name string, m AndroidBottomUpMutator) MutatorHandle { 175 f := func(ctx blueprint.BottomUpMutatorContext) { 176 if a, ok := ctx.Module().(Module); ok { 177 actx := &androidBottomUpMutatorContext{ 178 BottomUpMutatorContext: ctx, 179 androidBaseContextImpl: a.base().androidBaseContextFactory(ctx), 180 } 181 m(actx) 182 } 183 } 184 mutator := &mutator{name: name, bottomUpMutator: f} 185 x.mutators = append(x.mutators, mutator) 186 return mutator 187} 188 189func (x *registerMutatorsContext) TopDown(name string, m AndroidTopDownMutator) MutatorHandle { 190 f := func(ctx blueprint.TopDownMutatorContext) { 191 if a, ok := ctx.Module().(Module); ok { 192 actx := &androidTopDownMutatorContext{ 193 TopDownMutatorContext: ctx, 194 androidBaseContextImpl: a.base().androidBaseContextFactory(ctx), 195 } 196 m(actx) 197 } 198 } 199 mutator := &mutator{name: name, topDownMutator: f} 200 x.mutators = append(x.mutators, mutator) 201 return mutator 202} 203 204type MutatorHandle interface { 205 Parallel() MutatorHandle 206} 207 208func (mutator *mutator) Parallel() MutatorHandle { 209 mutator.parallel = true 210 return mutator 211} 212 213func depsMutator(ctx BottomUpMutatorContext) { 214 if m, ok := ctx.Module().(Module); ok && m.Enabled() { 215 m.DepsMutator(ctx) 216 } 217} 218 219func (a *androidTopDownMutatorContext) Config() Config { 220 return a.config 221} 222 223func (a *androidBottomUpMutatorContext) Config() Config { 224 return a.config 225} 226 227func (a *androidTopDownMutatorContext) Module() Module { 228 module, _ := a.TopDownMutatorContext.Module().(Module) 229 return module 230} 231 232func (a *androidTopDownMutatorContext) VisitDirectDeps(visit func(Module)) { 233 a.TopDownMutatorContext.VisitDirectDeps(func(module blueprint.Module) { 234 if aModule, _ := module.(Module); aModule != nil { 235 visit(aModule) 236 } 237 }) 238} 239 240func (a *androidTopDownMutatorContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) { 241 a.TopDownMutatorContext.VisitDirectDeps(func(module blueprint.Module) { 242 if aModule, _ := module.(Module); aModule != nil { 243 if a.TopDownMutatorContext.OtherModuleDependencyTag(aModule) == tag { 244 visit(aModule) 245 } 246 } 247 }) 248} 249 250func (a *androidTopDownMutatorContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) { 251 a.TopDownMutatorContext.VisitDirectDepsIf( 252 // pred 253 func(module blueprint.Module) bool { 254 if aModule, _ := module.(Module); aModule != nil { 255 return pred(aModule) 256 } else { 257 return false 258 } 259 }, 260 // visit 261 func(module blueprint.Module) { 262 visit(module.(Module)) 263 }) 264} 265 266func (a *androidTopDownMutatorContext) VisitDepsDepthFirst(visit func(Module)) { 267 a.TopDownMutatorContext.VisitDepsDepthFirst(func(module blueprint.Module) { 268 if aModule, _ := module.(Module); aModule != nil { 269 visit(aModule) 270 } 271 }) 272} 273 274func (a *androidTopDownMutatorContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) { 275 a.TopDownMutatorContext.VisitDepsDepthFirstIf( 276 // pred 277 func(module blueprint.Module) bool { 278 if aModule, _ := module.(Module); aModule != nil { 279 return pred(aModule) 280 } else { 281 return false 282 } 283 }, 284 // visit 285 func(module blueprint.Module) { 286 visit(module.(Module)) 287 }) 288} 289 290func (a *androidTopDownMutatorContext) WalkDeps(visit func(Module, Module) bool) { 291 a.walkPath = []Module{a.Module()} 292 a.TopDownMutatorContext.WalkDeps(func(child, parent blueprint.Module) bool { 293 childAndroidModule, _ := child.(Module) 294 parentAndroidModule, _ := parent.(Module) 295 if childAndroidModule != nil && parentAndroidModule != nil { 296 // record walkPath before visit 297 for a.walkPath[len(a.walkPath)-1] != parentAndroidModule { 298 a.walkPath = a.walkPath[0 : len(a.walkPath)-1] 299 } 300 a.walkPath = append(a.walkPath, childAndroidModule) 301 return visit(childAndroidModule, parentAndroidModule) 302 } else { 303 return false 304 } 305 }) 306} 307 308func (a *androidTopDownMutatorContext) GetWalkPath() []Module { 309 return a.walkPath 310} 311 312func (a *androidTopDownMutatorContext) AppendProperties(props ...interface{}) { 313 for _, p := range props { 314 err := proptools.AppendMatchingProperties(a.Module().base().customizableProperties, 315 p, nil) 316 if err != nil { 317 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok { 318 a.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error()) 319 } else { 320 panic(err) 321 } 322 } 323 } 324} 325 326func (a *androidTopDownMutatorContext) PrependProperties(props ...interface{}) { 327 for _, p := range props { 328 err := proptools.PrependMatchingProperties(a.Module().base().customizableProperties, 329 p, nil) 330 if err != nil { 331 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok { 332 a.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error()) 333 } else { 334 panic(err) 335 } 336 } 337 } 338} 339