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