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 "reflect" 20 21 "github.com/google/blueprint" 22) 23 24// A sortable component is one whose registration order affects the order in which it is executed 25// and so affects the behavior of the build system. As a result it is important for the order in 26// which they are registered during tests to match the order used at runtime and so the test 27// infrastructure will sort them to match. 28// 29// The sortable components are mutators, singletons and pre-singletons. Module types are not 30// sortable because their order of registration does not affect the runtime behavior. 31type sortableComponent interface { 32 // componentName returns the name of the component. 33 // 34 // Uniquely identifies the components within the set of components used at runtime and during 35 // tests. 36 componentName() string 37 38 // registers this component in the supplied context. 39 register(ctx *Context) 40} 41 42type sortableComponents []sortableComponent 43 44// registerAll registers all components in this slice with the supplied context. 45func (r sortableComponents) registerAll(ctx *Context) { 46 for _, c := range r { 47 c.register(ctx) 48 } 49} 50 51type moduleType struct { 52 name string 53 factory ModuleFactory 54} 55 56func (t moduleType) register(ctx *Context) { 57 ctx.RegisterModuleType(t.name, ModuleFactoryAdaptor(t.factory)) 58} 59 60var moduleTypes []moduleType 61var moduleTypesForDocs = map[string]reflect.Value{} 62var moduleTypeByFactory = map[reflect.Value]string{} 63 64type singleton struct { 65 // True if this should be registered as a parallel singleton. 66 parallel bool 67 68 name string 69 factory SingletonFactory 70} 71 72func newSingleton(name string, factory SingletonFactory, parallel bool) singleton { 73 return singleton{parallel: parallel, name: name, factory: factory} 74} 75 76func (s singleton) componentName() string { 77 return s.name 78} 79 80func (s singleton) register(ctx *Context) { 81 adaptor := SingletonFactoryAdaptor(ctx, s.factory) 82 ctx.RegisterSingletonType(s.name, adaptor, s.parallel) 83} 84 85var _ sortableComponent = singleton{} 86 87var singletons sortableComponents 88 89type mutator struct { 90 name string 91 bottomUpMutator blueprint.BottomUpMutator 92 topDownMutator blueprint.TopDownMutator 93 transitionMutator blueprint.TransitionMutator 94 parallel bool 95} 96 97var _ sortableComponent = &mutator{} 98 99type ModuleFactory func() Module 100 101// ModuleFactoryAdaptor wraps a ModuleFactory into a blueprint.ModuleFactory by converting a Module 102// into a blueprint.Module and a list of property structs 103func ModuleFactoryAdaptor(factory ModuleFactory) blueprint.ModuleFactory { 104 return func() (blueprint.Module, []interface{}) { 105 module := factory() 106 return module, module.GetProperties() 107 } 108} 109 110type SingletonFactory func() Singleton 111 112// SingletonFactoryAdaptor wraps a SingletonFactory into a blueprint.SingletonFactory by converting 113// a Singleton into a blueprint.Singleton 114func SingletonFactoryAdaptor(ctx *Context, factory SingletonFactory) blueprint.SingletonFactory { 115 return func() blueprint.Singleton { 116 singleton := factory() 117 if makevars, ok := singleton.(SingletonMakeVarsProvider); ok { 118 ctx.registerSingletonMakeVarsProvider(makevars) 119 } 120 return &singletonAdaptor{Singleton: singleton} 121 } 122} 123 124func RegisterModuleType(name string, factory ModuleFactory) { 125 moduleTypes = append(moduleTypes, moduleType{name, factory}) 126 RegisterModuleTypeForDocs(name, reflect.ValueOf(factory)) 127} 128 129// RegisterModuleTypeForDocs associates a module type name with a reflect.Value of the factory 130// function that has documentation for the module type. It is normally called automatically 131// by RegisterModuleType, but can be called manually after RegisterModuleType in order to 132// override the factory method used for documentation, for example if the method passed to 133// RegisterModuleType was a lambda. 134func RegisterModuleTypeForDocs(name string, factory reflect.Value) { 135 moduleTypesForDocs[name] = factory 136 moduleTypeByFactory[factory] = name 137} 138 139func registerSingletonType(name string, factory SingletonFactory, parallel bool) { 140 singletons = append(singletons, newSingleton(name, factory, parallel)) 141} 142 143func RegisterSingletonType(name string, factory SingletonFactory) { 144 registerSingletonType(name, factory, false) 145} 146 147func RegisterParallelSingletonType(name string, factory SingletonFactory) { 148 registerSingletonType(name, factory, true) 149} 150 151type Context struct { 152 *blueprint.Context 153 config Config 154} 155 156func NewContext(config Config) *Context { 157 ctx := &Context{blueprint.NewContext(), config} 158 ctx.SetSrcDir(absSrcDir) 159 ctx.AddSourceRootDirs(config.SourceRootDirs()...) 160 return ctx 161} 162 163// Register the pipeline of singletons, module types, and mutators for 164// generating build.ninja and other files for Kati, from Android.bp files. 165func (ctx *Context) Register() { 166 for _, t := range moduleTypes { 167 t.register(ctx) 168 } 169 170 mutators := collateGloballyRegisteredMutators() 171 mutators.registerAll(ctx) 172 173 singletons := collateGloballyRegisteredSingletons() 174 singletons.registerAll(ctx) 175} 176 177func (ctx *Context) Config() Config { 178 return ctx.config 179} 180 181func (ctx *Context) registerSingletonMakeVarsProvider(makevars SingletonMakeVarsProvider) { 182 registerSingletonMakeVarsProvider(ctx.config, makevars) 183} 184 185func collateGloballyRegisteredSingletons() sortableComponents { 186 allSingletons := append(sortableComponents(nil), singletons...) 187 allSingletons = append(allSingletons, 188 // Register phony just before makevars so it can write out its phony rules as Make rules 189 singleton{parallel: false, name: "phony", factory: phonySingletonFactory}, 190 191 // Register makevars after other singletons so they can export values through makevars 192 singleton{parallel: false, name: "makevars", factory: makeVarsSingletonFunc}, 193 194 // Register rawfiles and ninjadeps last so that they can track all used environment variables and 195 // Ninja file dependencies stored in the config. 196 singleton{parallel: false, name: "rawfiles", factory: rawFilesSingletonFactory}, 197 singleton{parallel: false, name: "ninjadeps", factory: ninjaDepsSingletonFactory}, 198 ) 199 200 return allSingletons 201} 202 203func ModuleTypeFactories() map[string]ModuleFactory { 204 ret := make(map[string]ModuleFactory) 205 for _, t := range moduleTypes { 206 ret[t.name] = t.factory 207 } 208 return ret 209} 210 211func ModuleTypeFactoriesForDocs() map[string]reflect.Value { 212 return moduleTypesForDocs 213} 214 215func ModuleTypeByFactory() map[reflect.Value]string { 216 return moduleTypeByFactory 217} 218 219// Interface for registering build components. 220// 221// Provided to allow registration of build components to be shared between the runtime 222// and test environments. 223type RegistrationContext interface { 224 RegisterModuleType(name string, factory ModuleFactory) 225 RegisterSingletonModuleType(name string, factory SingletonModuleFactory) 226 RegisterParallelSingletonModuleType(name string, factory SingletonModuleFactory) 227 RegisterParallelSingletonType(name string, factory SingletonFactory) 228 RegisterSingletonType(name string, factory SingletonFactory) 229 PreArchMutators(f RegisterMutatorFunc) 230 231 // Register pre arch mutators that are hard coded into mutator.go. 232 // 233 // Only registers mutators for testing, is a noop on the InitRegistrationContext. 234 HardCodedPreArchMutators(f RegisterMutatorFunc) 235 236 PreDepsMutators(f RegisterMutatorFunc) 237 PostDepsMutators(f RegisterMutatorFunc) 238 FinalDepsMutators(f RegisterMutatorFunc) 239} 240 241// Used to register build components from an init() method, e.g. 242// 243// init() { 244// RegisterBuildComponents(android.InitRegistrationContext) 245// } 246// 247// func RegisterBuildComponents(ctx android.RegistrationContext) { 248// ctx.RegisterModuleType(...) 249// ... 250// } 251// 252// Extracting the actual registration into a separate RegisterBuildComponents(ctx) function 253// allows it to be used to initialize test context, e.g. 254// 255// ctx := android.NewTestContext(config) 256// RegisterBuildComponents(ctx) 257var InitRegistrationContext RegistrationContext = &initRegistrationContext{ 258 moduleTypes: make(map[string]ModuleFactory), 259 singletonTypes: make(map[string]SingletonFactory), 260} 261 262// Make sure the TestContext implements RegistrationContext. 263var _ RegistrationContext = (*TestContext)(nil) 264 265type initRegistrationContext struct { 266 moduleTypes map[string]ModuleFactory 267 singletonTypes map[string]SingletonFactory 268 moduleTypesForDocs map[string]reflect.Value 269} 270 271func (ctx *initRegistrationContext) RegisterModuleType(name string, factory ModuleFactory) { 272 if _, present := ctx.moduleTypes[name]; present { 273 panic(fmt.Sprintf("module type %q is already registered", name)) 274 } 275 ctx.moduleTypes[name] = factory 276 RegisterModuleType(name, factory) 277 RegisterModuleTypeForDocs(name, reflect.ValueOf(factory)) 278} 279 280func (ctx *initRegistrationContext) RegisterSingletonModuleType(name string, factory SingletonModuleFactory) { 281 ctx.registerSingletonModuleType(name, factory, false) 282} 283func (ctx *initRegistrationContext) RegisterParallelSingletonModuleType(name string, factory SingletonModuleFactory) { 284 ctx.registerSingletonModuleType(name, factory, true) 285} 286 287func (ctx *initRegistrationContext) registerSingletonModuleType(name string, factory SingletonModuleFactory, parallel bool) { 288 s, m := SingletonModuleFactoryAdaptor(name, factory) 289 ctx.registerSingletonType(name, s, parallel) 290 ctx.RegisterModuleType(name, m) 291 // Overwrite moduleTypesForDocs with the original factory instead of the lambda returned by 292 // SingletonModuleFactoryAdaptor so that docs can find the module type documentation on the 293 // factory method. 294 RegisterModuleTypeForDocs(name, reflect.ValueOf(factory)) 295} 296 297func (ctx *initRegistrationContext) registerSingletonType(name string, factory SingletonFactory, parallel bool) { 298 if _, present := ctx.singletonTypes[name]; present { 299 panic(fmt.Sprintf("singleton type %q is already registered", name)) 300 } 301 ctx.singletonTypes[name] = factory 302 registerSingletonType(name, factory, parallel) 303} 304 305func (ctx *initRegistrationContext) RegisterSingletonType(name string, factory SingletonFactory) { 306 ctx.registerSingletonType(name, factory, false) 307} 308 309func (ctx *initRegistrationContext) RegisterParallelSingletonType(name string, factory SingletonFactory) { 310 ctx.registerSingletonType(name, factory, true) 311} 312 313func (ctx *initRegistrationContext) PreArchMutators(f RegisterMutatorFunc) { 314 PreArchMutators(f) 315} 316 317func (ctx *initRegistrationContext) HardCodedPreArchMutators(_ RegisterMutatorFunc) { 318 // Nothing to do as the mutators are hard code in preArch in mutator.go 319} 320 321func (ctx *initRegistrationContext) PreDepsMutators(f RegisterMutatorFunc) { 322 PreDepsMutators(f) 323} 324 325func (ctx *initRegistrationContext) PostDepsMutators(f RegisterMutatorFunc) { 326 PostDepsMutators(f) 327} 328 329func (ctx *initRegistrationContext) FinalDepsMutators(f RegisterMutatorFunc) { 330 FinalDepsMutators(f) 331} 332