blob: 880c689274048911e871ac98c94d3c3b78c85c57 [file] [log] [blame]
Colin Crosscfad1192015-11-02 16:43:11 -08001// 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
Colin Cross635c3b02016-05-18 15:37:25 -070015package android
Colin Crosscfad1192015-11-02 16:43:11 -080016
17import (
Colin Crosseabaedd2020-02-06 17:01:55 -080018 "reflect"
19
Colin Crosscfad1192015-11-02 16:43:11 -080020 "github.com/google/blueprint"
21 "github.com/google/blueprint/proptools"
22)
23
Colin Crossc99deeb2016-04-11 15:06:20 -070024type defaultsDependencyTag struct {
25 blueprint.BaseDependencyTag
26}
27
28var DefaultsDepTag defaultsDependencyTag
29
Colin Crosscfad1192015-11-02 16:43:11 -080030type defaultsProperties struct {
31 Defaults []string
32}
33
Colin Cross1f44a3a2017-07-07 14:33:33 -070034type DefaultableModuleBase struct {
Colin Crosseabaedd2020-02-06 17:01:55 -080035 defaultsProperties defaultsProperties
36 defaultableProperties []interface{}
37 defaultableVariableProperties interface{}
Paul Duffin1b115d32020-04-29 16:47:28 +010038
39 // The optional hook to call after any defaults have been applied.
40 hook DefaultableHook
Colin Crosscfad1192015-11-02 16:43:11 -080041}
42
Colin Cross1f44a3a2017-07-07 14:33:33 -070043func (d *DefaultableModuleBase) defaults() *defaultsProperties {
Colin Crosscfad1192015-11-02 16:43:11 -080044 return &d.defaultsProperties
45}
46
Colin Crosseabaedd2020-02-06 17:01:55 -080047func (d *DefaultableModuleBase) setProperties(props []interface{}, variableProperties interface{}) {
Colin Crosscfad1192015-11-02 16:43:11 -080048 d.defaultableProperties = props
Colin Crosseabaedd2020-02-06 17:01:55 -080049 d.defaultableVariableProperties = variableProperties
Colin Crosscfad1192015-11-02 16:43:11 -080050}
51
Paul Duffin1b115d32020-04-29 16:47:28 +010052func (d *DefaultableModuleBase) SetDefaultableHook(hook DefaultableHook) {
53 d.hook = hook
54}
55
56func (d *DefaultableModuleBase) callHookIfAvailable(ctx DefaultableHookContext) {
57 if d.hook != nil {
58 d.hook(ctx)
59 }
60}
61
Paul Duffin7df7fb02019-07-24 12:26:14 +010062// Interface that must be supported by any module to which defaults can be applied.
Colin Crosscfad1192015-11-02 16:43:11 -080063type Defaultable interface {
Paul Duffin7df7fb02019-07-24 12:26:14 +010064 // Get a pointer to the struct containing the Defaults property.
Colin Crosscfad1192015-11-02 16:43:11 -080065 defaults() *defaultsProperties
Paul Duffin7df7fb02019-07-24 12:26:14 +010066
67 // Set the property structures into which defaults will be added.
Colin Crosseabaedd2020-02-06 17:01:55 -080068 setProperties(props []interface{}, variableProperties interface{})
Paul Duffin7df7fb02019-07-24 12:26:14 +010069
70 // Apply defaults from the supplied Defaults to the property structures supplied to
71 // setProperties(...).
Colin Cross13177012016-08-09 12:00:45 -070072 applyDefaults(TopDownMutatorContext, []Defaults)
Paul Duffin1b115d32020-04-29 16:47:28 +010073
74 // Set the hook to be called after any defaults have been applied.
75 //
76 // Should be used in preference to a AddLoadHook when the behavior of the load
77 // hook is dependent on properties supplied in the Android.bp file.
78 SetDefaultableHook(hook DefaultableHook)
79
80 // Call the hook if specified.
81 callHookIfAvailable(context DefaultableHookContext)
Colin Crosscfad1192015-11-02 16:43:11 -080082}
83
Colin Cross1f44a3a2017-07-07 14:33:33 -070084type DefaultableModule interface {
85 Module
86 Defaultable
Colin Crosscfad1192015-11-02 16:43:11 -080087}
88
Colin Cross1f44a3a2017-07-07 14:33:33 -070089var _ Defaultable = (*DefaultableModuleBase)(nil)
90
91func InitDefaultableModule(module DefaultableModule) {
Colin Crosseabaedd2020-02-06 17:01:55 -080092 if module.(Module).base().module == nil {
93 panic("InitAndroidModule must be called before InitDefaultableModule")
94 }
95 module.setProperties(module.(Module).GetProperties(), module.(Module).base().variableProperties)
Colin Cross1f44a3a2017-07-07 14:33:33 -070096
97 module.AddProperties(module.defaults())
Liz Kammer319e3ae2020-09-21 22:24:17 +000098
99 module.base().customizableProperties = module.GetProperties()
Colin Cross1f44a3a2017-07-07 14:33:33 -0700100}
101
Paul Duffin1b115d32020-04-29 16:47:28 +0100102// A restricted subset of context methods, similar to LoadHookContext.
103type DefaultableHookContext interface {
104 EarlyModuleContext
105
106 CreateModule(ModuleFactory, ...interface{}) Module
107}
108
109type DefaultableHook func(ctx DefaultableHookContext)
110
Paul Duffin95d53b52019-07-24 13:45:05 +0100111// The Defaults_visibility property.
112type DefaultsVisibilityProperties struct {
113
114 // Controls the visibility of the defaults module itself.
115 Defaults_visibility []string
116}
117
Colin Cross1f44a3a2017-07-07 14:33:33 -0700118type DefaultsModuleBase struct {
119 DefaultableModuleBase
Paul Duffin63c6e182019-07-24 14:24:38 +0100120
121 // Container for defaults of the common properties
122 commonProperties commonProperties
Paul Duffin95d53b52019-07-24 13:45:05 +0100123
124 defaultsVisibilityProperties DefaultsVisibilityProperties
Colin Crosscfad1192015-11-02 16:43:11 -0800125}
126
Martin Stjernholmebd757d2019-05-24 11:00:30 +0100127// The common pattern for defaults modules is to register separate instances of
128// the xxxProperties structs in the AddProperties calls, rather than reusing the
129// ones inherited from Module.
130//
131// The effect is that e.g. myDefaultsModuleInstance.base().xxxProperties won't
132// contain the values that have been set for the defaults module. Rather, to
133// retrieve the values it is necessary to iterate over properties(). E.g. to get
134// the commonProperties instance that have the real values:
135//
136// d := myModule.(Defaults)
137// for _, props := range d.properties() {
138// if cp, ok := props.(*commonProperties); ok {
139// ... access property values in cp ...
140// }
141// }
142//
143// The rationale is that the properties on a defaults module apply to the
144// defaultable modules using it, not to the defaults module itself. E.g. setting
145// the "enabled" property false makes inheriting modules disabled by default,
146// rather than disabling the defaults module itself.
Colin Crosscfad1192015-11-02 16:43:11 -0800147type Defaults interface {
Colin Crosse7b07132016-07-27 10:15:06 -0700148 Defaultable
Paul Duffin7df7fb02019-07-24 12:26:14 +0100149
150 // Although this function is unused it is actually needed to ensure that only modules that embed
151 // DefaultsModuleBase will type-assert to the Defaults interface.
Colin Crosscfad1192015-11-02 16:43:11 -0800152 isDefaults() bool
Paul Duffin7df7fb02019-07-24 12:26:14 +0100153
154 // Get the structures containing the properties for which defaults can be provided.
Colin Crosscfad1192015-11-02 16:43:11 -0800155 properties() []interface{}
Paul Duffin63c6e182019-07-24 14:24:38 +0100156
Colin Crosseabaedd2020-02-06 17:01:55 -0800157 productVariableProperties() interface{}
158
Paul Duffin63c6e182019-07-24 14:24:38 +0100159 // Return the defaults common properties.
160 common() *commonProperties
Paul Duffin95d53b52019-07-24 13:45:05 +0100161
162 // Return the defaults visibility properties.
163 defaultsVisibility() *DefaultsVisibilityProperties
Colin Crosscfad1192015-11-02 16:43:11 -0800164}
165
Colin Cross1f44a3a2017-07-07 14:33:33 -0700166func (d *DefaultsModuleBase) isDefaults() bool {
Colin Crosscfad1192015-11-02 16:43:11 -0800167 return true
168}
169
Paul Duffine62432f2019-07-24 12:51:21 +0100170type DefaultsModule interface {
171 Module
172 Defaults
173}
174
Colin Cross1f44a3a2017-07-07 14:33:33 -0700175func (d *DefaultsModuleBase) properties() []interface{} {
Colin Crosse7b07132016-07-27 10:15:06 -0700176 return d.defaultableProperties
Colin Crosscfad1192015-11-02 16:43:11 -0800177}
178
Colin Crosseabaedd2020-02-06 17:01:55 -0800179func (d *DefaultsModuleBase) productVariableProperties() interface{} {
180 return d.defaultableVariableProperties
181}
182
Paul Duffin63c6e182019-07-24 14:24:38 +0100183func (d *DefaultsModuleBase) common() *commonProperties {
184 return &d.commonProperties
185}
186
Paul Duffin95d53b52019-07-24 13:45:05 +0100187func (d *DefaultsModuleBase) defaultsVisibility() *DefaultsVisibilityProperties {
188 return &d.defaultsVisibilityProperties
189}
190
Colin Cross59037622019-06-10 13:12:56 -0700191func (d *DefaultsModuleBase) GenerateAndroidBuildActions(ctx ModuleContext) {
192}
193
Paul Duffine62432f2019-07-24 12:51:21 +0100194func InitDefaultsModule(module DefaultsModule) {
Paul Duffin63c6e182019-07-24 14:24:38 +0100195 commonProperties := module.common()
196
Colin Cross36242852017-06-23 15:06:31 -0700197 module.AddProperties(
Colin Crossfc754582016-05-17 16:34:16 -0700198 &hostAndDeviceProperties{},
Paul Duffin63c6e182019-07-24 14:24:38 +0100199 commonProperties,
Paul Duffin1be8e6c2020-09-02 13:08:57 +0100200 &ApexProperties{},
201 &distProperties{})
Colin Crossfc754582016-05-17 16:34:16 -0700202
Colin Crosseabaedd2020-02-06 17:01:55 -0800203 initAndroidModuleBase(module)
204 initProductVariableModule(module)
Colin Cross36242852017-06-23 15:06:31 -0700205 InitArchModule(module)
Colin Cross1f44a3a2017-07-07 14:33:33 -0700206 InitDefaultableModule(module)
Colin Crossfc754582016-05-17 16:34:16 -0700207
Paul Duffin7df7fb02019-07-24 12:26:14 +0100208 // Add properties that will not have defaults applied to them.
Paul Duffin63c6e182019-07-24 14:24:38 +0100209 base := module.base()
Paul Duffin95d53b52019-07-24 13:45:05 +0100210 defaultsVisibility := module.defaultsVisibility()
211 module.AddProperties(&base.nameProperties, defaultsVisibility)
Colin Crossfc754582016-05-17 16:34:16 -0700212
Paul Duffin63c6e182019-07-24 14:24:38 +0100213 // Unlike non-defaults modules the visibility property is not stored in m.base().commonProperties.
Paul Duffinabc9a642020-05-01 17:52:01 +0100214 // Instead it is stored in a separate instance of commonProperties created above so clear the
215 // existing list of properties.
216 clearVisibilityProperties(module)
217
218 // The defaults_visibility property controls the visibility of a defaults module so it must be
219 // set as the primary property, which also adds it to the list.
220 setPrimaryVisibilityProperty(module, "defaults_visibility", &defaultsVisibility.Defaults_visibility)
221
Paul Duffin63c6e182019-07-24 14:24:38 +0100222 // The visibility property needs to be checked (but not parsed) by the visibility module during
Paul Duffinabc9a642020-05-01 17:52:01 +0100223 // its checking phase and parsing phase so add it to the list as a normal property.
224 AddVisibilityProperty(module, "visibility", &commonProperties.Visibility)
Paul Duffin63c6e182019-07-24 14:24:38 +0100225
Bob Badour5553f7f2021-01-07 03:34:31 +0000226 // The applicable licenses property for defaults is 'licenses'.
227 setPrimaryLicensesProperty(module, "licenses", &commonProperties.Licenses)
228
Paul Duffin63c6e182019-07-24 14:24:38 +0100229 base.module = module
Colin Crosscfad1192015-11-02 16:43:11 -0800230}
231
Colin Cross1f44a3a2017-07-07 14:33:33 -0700232var _ Defaults = (*DefaultsModuleBase)(nil)
Colin Crosscfad1192015-11-02 16:43:11 -0800233
Colin Cross1f44a3a2017-07-07 14:33:33 -0700234func (defaultable *DefaultableModuleBase) applyDefaults(ctx TopDownMutatorContext,
Colin Cross13177012016-08-09 12:00:45 -0700235 defaultsList []Defaults) {
Colin Crosscfad1192015-11-02 16:43:11 -0800236
Colin Cross13177012016-08-09 12:00:45 -0700237 for _, defaults := range defaultsList {
238 for _, prop := range defaultable.defaultableProperties {
Colin Crosseabaedd2020-02-06 17:01:55 -0800239 if prop == defaultable.defaultableVariableProperties {
240 defaultable.applyDefaultVariableProperties(ctx, defaults, prop)
241 } else {
242 defaultable.applyDefaultProperties(ctx, defaults, prop)
243 }
244 }
245 }
246}
247
248// Product variable properties need special handling, the type of the filtered product variable
249// property struct may not be identical between the defaults module and the defaultable module.
250// Use PrependMatchingProperties to apply whichever properties match.
251func (defaultable *DefaultableModuleBase) applyDefaultVariableProperties(ctx TopDownMutatorContext,
252 defaults Defaults, defaultableProp interface{}) {
253 if defaultableProp == nil {
254 return
255 }
256
257 defaultsProp := defaults.productVariableProperties()
258 if defaultsProp == nil {
259 return
260 }
261
262 dst := []interface{}{
263 defaultableProp,
264 // Put an empty copy of the src properties into dst so that properties in src that are not in dst
265 // don't cause a "failed to find property to extend" error.
266 proptools.CloneEmptyProperties(reflect.ValueOf(defaultsProp)).Interface(),
267 }
268
269 err := proptools.PrependMatchingProperties(dst, defaultsProp, nil)
270 if err != nil {
271 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
272 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
273 } else {
274 panic(err)
275 }
276 }
277}
278
279func (defaultable *DefaultableModuleBase) applyDefaultProperties(ctx TopDownMutatorContext,
280 defaults Defaults, defaultableProp interface{}) {
281
282 for _, def := range defaults.properties() {
283 if proptools.TypeEqual(defaultableProp, def) {
284 err := proptools.PrependProperties(defaultableProp, def, nil)
285 if err != nil {
286 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
287 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
288 } else {
289 panic(err)
Colin Crosscfad1192015-11-02 16:43:11 -0800290 }
291 }
292 }
293 }
294}
295
Colin Cross89536d42017-07-07 14:35:50 -0700296func RegisterDefaultsPreArchMutators(ctx RegisterMutatorsContext) {
Colin Crosscec81712017-07-13 14:43:27 -0700297 ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel()
298 ctx.TopDown("defaults", defaultsMutator).Parallel()
299}
300
Colin Cross635c3b02016-05-18 15:37:25 -0700301func defaultsDepsMutator(ctx BottomUpMutatorContext) {
Colin Crosscfad1192015-11-02 16:43:11 -0800302 if defaultable, ok := ctx.Module().(Defaultable); ok {
Colin Crossc99deeb2016-04-11 15:06:20 -0700303 ctx.AddDependency(ctx.Module(), DefaultsDepTag, defaultable.defaults().Defaults...)
Colin Crosscfad1192015-11-02 16:43:11 -0800304 }
305}
306
Colin Cross13177012016-08-09 12:00:45 -0700307func defaultsMutator(ctx TopDownMutatorContext) {
Paul Duffin1b115d32020-04-29 16:47:28 +0100308 if defaultable, ok := ctx.Module().(Defaultable); ok {
309 if len(defaultable.defaults().Defaults) > 0 {
310 var defaultsList []Defaults
311 seen := make(map[Defaults]bool)
Colin Crossa1ce2a02018-06-20 15:19:39 -0700312
Paul Duffin1b115d32020-04-29 16:47:28 +0100313 ctx.WalkDeps(func(module, parent Module) bool {
314 if ctx.OtherModuleDependencyTag(module) == DefaultsDepTag {
315 if defaults, ok := module.(Defaults); ok {
316 if !seen[defaults] {
317 seen[defaults] = true
318 defaultsList = append(defaultsList, defaults)
319 return len(defaults.defaults().Defaults) > 0
320 }
321 } else {
322 ctx.PropertyErrorf("defaults", "module %s is not an defaults module",
323 ctx.OtherModuleName(module))
Colin Crossa1ce2a02018-06-20 15:19:39 -0700324 }
Colin Crosscfad1192015-11-02 16:43:11 -0800325 }
Paul Duffin1b115d32020-04-29 16:47:28 +0100326 return false
327 })
328 defaultable.applyDefaults(ctx, defaultsList)
329 }
330
331 defaultable.callHookIfAvailable(ctx)
Colin Crosscfad1192015-11-02 16:43:11 -0800332 }
333}