123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- // Copyright 2015 Google Inc. All rights reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package android
- import (
- "fmt"
- "reflect"
- "github.com/google/blueprint"
- )
- // A sortable component is one whose registration order affects the order in which it is executed
- // and so affects the behavior of the build system. As a result it is important for the order in
- // which they are registered during tests to match the order used at runtime and so the test
- // infrastructure will sort them to match.
- //
- // The sortable components are mutators, singletons and pre-singletons. Module types are not
- // sortable because their order of registration does not affect the runtime behavior.
- type sortableComponent interface {
- // componentName returns the name of the component.
- //
- // Uniquely identifies the components within the set of components used at runtime and during
- // tests.
- componentName() string
- // registers this component in the supplied context.
- register(ctx *Context)
- }
- type sortableComponents []sortableComponent
- // registerAll registers all components in this slice with the supplied context.
- func (r sortableComponents) registerAll(ctx *Context) {
- for _, c := range r {
- c.register(ctx)
- }
- }
- type moduleType struct {
- name string
- factory ModuleFactory
- }
- func (t moduleType) register(ctx *Context) {
- ctx.RegisterModuleType(t.name, ModuleFactoryAdaptor(t.factory))
- }
- var moduleTypes []moduleType
- var moduleTypesForDocs = map[string]reflect.Value{}
- var moduleTypeByFactory = map[reflect.Value]string{}
- type singleton struct {
- // True if this should be registered as a pre-singleton, false otherwise.
- pre bool
- // True if this should be registered as a parallel singleton.
- parallel bool
- name string
- factory SingletonFactory
- }
- func newSingleton(name string, factory SingletonFactory, parallel bool) singleton {
- return singleton{pre: false, parallel: parallel, name: name, factory: factory}
- }
- func newPreSingleton(name string, factory SingletonFactory) singleton {
- return singleton{pre: true, parallel: false, name: name, factory: factory}
- }
- func (s singleton) componentName() string {
- return s.name
- }
- func (s singleton) register(ctx *Context) {
- adaptor := SingletonFactoryAdaptor(ctx, s.factory)
- if s.pre {
- ctx.RegisterPreSingletonType(s.name, adaptor)
- } else {
- ctx.RegisterSingletonType(s.name, adaptor, s.parallel)
- }
- }
- var _ sortableComponent = singleton{}
- var singletons sortableComponents
- var preSingletons sortableComponents
- type mutator struct {
- name string
- bottomUpMutator blueprint.BottomUpMutator
- topDownMutator blueprint.TopDownMutator
- transitionMutator blueprint.TransitionMutator
- parallel bool
- }
- var _ sortableComponent = &mutator{}
- type ModuleFactory func() Module
- // ModuleFactoryAdaptor wraps a ModuleFactory into a blueprint.ModuleFactory by converting a Module
- // into a blueprint.Module and a list of property structs
- func ModuleFactoryAdaptor(factory ModuleFactory) blueprint.ModuleFactory {
- return func() (blueprint.Module, []interface{}) {
- module := factory()
- return module, module.GetProperties()
- }
- }
- type SingletonFactory func() Singleton
- // SingletonFactoryAdaptor wraps a SingletonFactory into a blueprint.SingletonFactory by converting
- // a Singleton into a blueprint.Singleton
- func SingletonFactoryAdaptor(ctx *Context, factory SingletonFactory) blueprint.SingletonFactory {
- return func() blueprint.Singleton {
- singleton := factory()
- if makevars, ok := singleton.(SingletonMakeVarsProvider); ok {
- ctx.registerSingletonMakeVarsProvider(makevars)
- }
- return &singletonAdaptor{Singleton: singleton}
- }
- }
- func RegisterModuleType(name string, factory ModuleFactory) {
- moduleTypes = append(moduleTypes, moduleType{name, factory})
- RegisterModuleTypeForDocs(name, reflect.ValueOf(factory))
- }
- // RegisterModuleTypeForDocs associates a module type name with a reflect.Value of the factory
- // function that has documentation for the module type. It is normally called automatically
- // by RegisterModuleType, but can be called manually after RegisterModuleType in order to
- // override the factory method used for documentation, for example if the method passed to
- // RegisterModuleType was a lambda.
- func RegisterModuleTypeForDocs(name string, factory reflect.Value) {
- moduleTypesForDocs[name] = factory
- moduleTypeByFactory[factory] = name
- }
- func registerSingletonType(name string, factory SingletonFactory, parallel bool) {
- singletons = append(singletons, newSingleton(name, factory, parallel))
- }
- func RegisterSingletonType(name string, factory SingletonFactory) {
- registerSingletonType(name, factory, false)
- }
- func RegisterParallelSingletonType(name string, factory SingletonFactory) {
- registerSingletonType(name, factory, true)
- }
- func RegisterPreSingletonType(name string, factory SingletonFactory) {
- preSingletons = append(preSingletons, newPreSingleton(name, factory))
- }
- type Context struct {
- *blueprint.Context
- config Config
- }
- func NewContext(config Config) *Context {
- ctx := &Context{blueprint.NewContext(), config}
- ctx.SetSrcDir(absSrcDir)
- ctx.AddIncludeTags(config.IncludeTags()...)
- ctx.AddSourceRootDirs(config.SourceRootDirs()...)
- return ctx
- }
- // Helper function to register the module types used in bp2build and
- // api_bp2build.
- func registerModuleTypes(ctx *Context) {
- for _, t := range moduleTypes {
- t.register(ctx)
- }
- // Required for SingletonModule types, even though we are not using them.
- for _, t := range singletons {
- t.register(ctx)
- }
- }
- // RegisterForBazelConversion registers an alternate shadow pipeline of
- // singletons, module types and mutators to register for converting Blueprint
- // files to semantically equivalent BUILD files.
- func (ctx *Context) RegisterForBazelConversion() {
- registerModuleTypes(ctx)
- RegisterMutatorsForBazelConversion(ctx, bp2buildPreArchMutators)
- }
- // RegisterForApiBazelConversion is similar to RegisterForBazelConversion except that
- // it only generates API targets in the generated workspace
- func (ctx *Context) RegisterForApiBazelConversion() {
- registerModuleTypes(ctx)
- RegisterMutatorsForApiBazelConversion(ctx, bp2buildPreArchMutators)
- }
- // Register the pipeline of singletons, module types, and mutators for
- // generating build.ninja and other files for Kati, from Android.bp files.
- func (ctx *Context) Register() {
- preSingletons.registerAll(ctx)
- for _, t := range moduleTypes {
- t.register(ctx)
- }
- mutators := collateGloballyRegisteredMutators()
- mutators.registerAll(ctx)
- singletons := collateGloballyRegisteredSingletons()
- singletons.registerAll(ctx)
- }
- func (ctx *Context) Config() Config {
- return ctx.config
- }
- func (ctx *Context) registerSingletonMakeVarsProvider(makevars SingletonMakeVarsProvider) {
- registerSingletonMakeVarsProvider(ctx.config, makevars)
- }
- func collateGloballyRegisteredSingletons() sortableComponents {
- allSingletons := append(sortableComponents(nil), singletons...)
- allSingletons = append(allSingletons,
- singleton{pre: false, parallel: true, name: "bazeldeps", factory: BazelSingleton},
- // Register phony just before makevars so it can write out its phony rules as Make rules
- singleton{pre: false, parallel: false, name: "phony", factory: phonySingletonFactory},
- // Register makevars after other singletons so they can export values through makevars
- singleton{pre: false, parallel: false, name: "makevars", factory: makeVarsSingletonFunc},
- // Register env and ninjadeps last so that they can track all used environment variables and
- // Ninja file dependencies stored in the config.
- singleton{pre: false, parallel: false, name: "ninjadeps", factory: ninjaDepsSingletonFactory},
- )
- return allSingletons
- }
- func ModuleTypeFactories() map[string]ModuleFactory {
- ret := make(map[string]ModuleFactory)
- for _, t := range moduleTypes {
- ret[t.name] = t.factory
- }
- return ret
- }
- func ModuleTypeFactoriesForDocs() map[string]reflect.Value {
- return moduleTypesForDocs
- }
- func ModuleTypeByFactory() map[reflect.Value]string {
- return moduleTypeByFactory
- }
- // Interface for registering build components.
- //
- // Provided to allow registration of build components to be shared between the runtime
- // and test environments.
- type RegistrationContext interface {
- RegisterModuleType(name string, factory ModuleFactory)
- RegisterSingletonModuleType(name string, factory SingletonModuleFactory)
- RegisterParallelSingletonModuleType(name string, factory SingletonModuleFactory)
- RegisterPreSingletonType(name string, factory SingletonFactory)
- RegisterParallelSingletonType(name string, factory SingletonFactory)
- RegisterSingletonType(name string, factory SingletonFactory)
- PreArchMutators(f RegisterMutatorFunc)
- // Register pre arch mutators that are hard coded into mutator.go.
- //
- // Only registers mutators for testing, is a noop on the InitRegistrationContext.
- HardCodedPreArchMutators(f RegisterMutatorFunc)
- PreDepsMutators(f RegisterMutatorFunc)
- PostDepsMutators(f RegisterMutatorFunc)
- FinalDepsMutators(f RegisterMutatorFunc)
- }
- // Used to register build components from an init() method, e.g.
- //
- // init() {
- // RegisterBuildComponents(android.InitRegistrationContext)
- // }
- //
- // func RegisterBuildComponents(ctx android.RegistrationContext) {
- // ctx.RegisterModuleType(...)
- // ...
- // }
- //
- // Extracting the actual registration into a separate RegisterBuildComponents(ctx) function
- // allows it to be used to initialize test context, e.g.
- //
- // ctx := android.NewTestContext(config)
- // RegisterBuildComponents(ctx)
- var InitRegistrationContext RegistrationContext = &initRegistrationContext{
- moduleTypes: make(map[string]ModuleFactory),
- singletonTypes: make(map[string]SingletonFactory),
- preSingletonTypes: make(map[string]SingletonFactory),
- }
- // Make sure the TestContext implements RegistrationContext.
- var _ RegistrationContext = (*TestContext)(nil)
- type initRegistrationContext struct {
- moduleTypes map[string]ModuleFactory
- singletonTypes map[string]SingletonFactory
- preSingletonTypes map[string]SingletonFactory
- moduleTypesForDocs map[string]reflect.Value
- }
- func (ctx *initRegistrationContext) RegisterModuleType(name string, factory ModuleFactory) {
- if _, present := ctx.moduleTypes[name]; present {
- panic(fmt.Sprintf("module type %q is already registered", name))
- }
- ctx.moduleTypes[name] = factory
- RegisterModuleType(name, factory)
- RegisterModuleTypeForDocs(name, reflect.ValueOf(factory))
- }
- func (ctx *initRegistrationContext) RegisterSingletonModuleType(name string, factory SingletonModuleFactory) {
- ctx.registerSingletonModuleType(name, factory, false)
- }
- func (ctx *initRegistrationContext) RegisterParallelSingletonModuleType(name string, factory SingletonModuleFactory) {
- ctx.registerSingletonModuleType(name, factory, true)
- }
- func (ctx *initRegistrationContext) registerSingletonModuleType(name string, factory SingletonModuleFactory, parallel bool) {
- s, m := SingletonModuleFactoryAdaptor(name, factory)
- ctx.registerSingletonType(name, s, parallel)
- ctx.RegisterModuleType(name, m)
- // Overwrite moduleTypesForDocs with the original factory instead of the lambda returned by
- // SingletonModuleFactoryAdaptor so that docs can find the module type documentation on the
- // factory method.
- RegisterModuleTypeForDocs(name, reflect.ValueOf(factory))
- }
- func (ctx *initRegistrationContext) registerSingletonType(name string, factory SingletonFactory, parallel bool) {
- if _, present := ctx.singletonTypes[name]; present {
- panic(fmt.Sprintf("singleton type %q is already registered", name))
- }
- ctx.singletonTypes[name] = factory
- registerSingletonType(name, factory, parallel)
- }
- func (ctx *initRegistrationContext) RegisterSingletonType(name string, factory SingletonFactory) {
- ctx.registerSingletonType(name, factory, false)
- }
- func (ctx *initRegistrationContext) RegisterParallelSingletonType(name string, factory SingletonFactory) {
- ctx.registerSingletonType(name, factory, true)
- }
- func (ctx *initRegistrationContext) RegisterPreSingletonType(name string, factory SingletonFactory) {
- if _, present := ctx.preSingletonTypes[name]; present {
- panic(fmt.Sprintf("pre singleton type %q is already registered", name))
- }
- ctx.preSingletonTypes[name] = factory
- RegisterPreSingletonType(name, factory)
- }
- func (ctx *initRegistrationContext) PreArchMutators(f RegisterMutatorFunc) {
- PreArchMutators(f)
- }
- func (ctx *initRegistrationContext) HardCodedPreArchMutators(_ RegisterMutatorFunc) {
- // Nothing to do as the mutators are hard code in preArch in mutator.go
- }
- func (ctx *initRegistrationContext) PreDepsMutators(f RegisterMutatorFunc) {
- PreDepsMutators(f)
- }
- func (ctx *initRegistrationContext) PostDepsMutators(f RegisterMutatorFunc) {
- PostDepsMutators(f)
- }
- func (ctx *initRegistrationContext) FinalDepsMutators(f RegisterMutatorFunc) {
- FinalDepsMutators(f)
- }
|