• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 := &registerMutatorsContext{}
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