blob: 5677638b739145d29b1900456cb7793741dd0f59 [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 Duffinafa9fa12020-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 Duffinafa9fa12020-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 Duffinafa9fa12020-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) {
Ustafe201fe2021-12-06 15:13:36 -050092 if module.base().module == nil {
Colin Crosseabaedd2020-02-06 17:01:55 -080093 panic("InitAndroidModule must be called before InitDefaultableModule")
94 }
Liz Kammer416201d2021-12-15 13:18:42 -050095
Ustafe201fe2021-12-06 15:13:36 -050096 module.setProperties(module.GetProperties(), module.base().variableProperties)
Colin Cross1f44a3a2017-07-07 14:33:33 -070097
98 module.AddProperties(module.defaults())
Liz Kammerdbd48092020-09-21 22:24:17 +000099
100 module.base().customizableProperties = module.GetProperties()
Colin Cross1f44a3a2017-07-07 14:33:33 -0700101}
102
Paul Duffinafa9fa12020-04-29 16:47:28 +0100103// A restricted subset of context methods, similar to LoadHookContext.
104type DefaultableHookContext interface {
105 EarlyModuleContext
106
107 CreateModule(ModuleFactory, ...interface{}) Module
Colin Cross18f840c2021-05-20 17:56:54 -0700108 AddMissingDependencies(missingDeps []string)
Paul Duffinafa9fa12020-04-29 16:47:28 +0100109}
110
111type DefaultableHook func(ctx DefaultableHookContext)
112
Paul Duffin95d53b52019-07-24 13:45:05 +0100113// The Defaults_visibility property.
114type DefaultsVisibilityProperties struct {
115
116 // Controls the visibility of the defaults module itself.
117 Defaults_visibility []string
118}
119
Colin Cross1f44a3a2017-07-07 14:33:33 -0700120type DefaultsModuleBase struct {
121 DefaultableModuleBase
Liz Kammer416201d2021-12-15 13:18:42 -0500122
123 // Included to support setting bazel_module.label for multiple Soong modules to the same Bazel
124 // target. This is primarily useful for modules that were architecture specific and instead are
125 // handled in Bazel as a select().
126 BazelModuleBase
Colin Crosscfad1192015-11-02 16:43:11 -0800127}
128
Martin Stjernholmebd757d2019-05-24 11:00:30 +0100129// The common pattern for defaults modules is to register separate instances of
130// the xxxProperties structs in the AddProperties calls, rather than reusing the
131// ones inherited from Module.
132//
133// The effect is that e.g. myDefaultsModuleInstance.base().xxxProperties won't
134// contain the values that have been set for the defaults module. Rather, to
135// retrieve the values it is necessary to iterate over properties(). E.g. to get
136// the commonProperties instance that have the real values:
137//
138// d := myModule.(Defaults)
139// for _, props := range d.properties() {
140// if cp, ok := props.(*commonProperties); ok {
141// ... access property values in cp ...
142// }
143// }
144//
145// The rationale is that the properties on a defaults module apply to the
146// defaultable modules using it, not to the defaults module itself. E.g. setting
147// the "enabled" property false makes inheriting modules disabled by default,
148// rather than disabling the defaults module itself.
Colin Crosscfad1192015-11-02 16:43:11 -0800149type Defaults interface {
Colin Crosse7b07132016-07-27 10:15:06 -0700150 Defaultable
Paul Duffin7df7fb02019-07-24 12:26:14 +0100151
152 // Although this function is unused it is actually needed to ensure that only modules that embed
153 // DefaultsModuleBase will type-assert to the Defaults interface.
Colin Crosscfad1192015-11-02 16:43:11 -0800154 isDefaults() bool
Paul Duffin7df7fb02019-07-24 12:26:14 +0100155
156 // Get the structures containing the properties for which defaults can be provided.
Colin Crosscfad1192015-11-02 16:43:11 -0800157 properties() []interface{}
Paul Duffin63c6e182019-07-24 14:24:38 +0100158
Colin Crosseabaedd2020-02-06 17:01:55 -0800159 productVariableProperties() interface{}
Colin Crosscfad1192015-11-02 16:43:11 -0800160}
161
Colin Cross1f44a3a2017-07-07 14:33:33 -0700162func (d *DefaultsModuleBase) isDefaults() bool {
Colin Crosscfad1192015-11-02 16:43:11 -0800163 return true
164}
165
Paul Duffine62432f2019-07-24 12:51:21 +0100166type DefaultsModule interface {
167 Module
168 Defaults
Liz Kammer416201d2021-12-15 13:18:42 -0500169 Bazelable
Paul Duffine62432f2019-07-24 12:51:21 +0100170}
171
Colin Cross1f44a3a2017-07-07 14:33:33 -0700172func (d *DefaultsModuleBase) properties() []interface{} {
Colin Crosse7b07132016-07-27 10:15:06 -0700173 return d.defaultableProperties
Colin Crosscfad1192015-11-02 16:43:11 -0800174}
175
Colin Crosseabaedd2020-02-06 17:01:55 -0800176func (d *DefaultsModuleBase) productVariableProperties() interface{} {
177 return d.defaultableVariableProperties
178}
179
Liz Kammer416201d2021-12-15 13:18:42 -0500180func (d *DefaultsModuleBase) GenerateAndroidBuildActions(ctx ModuleContext) {}
Colin Cross59037622019-06-10 13:12:56 -0700181
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400182// ConvertWithBp2build to fulfill Bazelable interface; however, at this time defaults module are
183// *NOT* converted with bp2build
184func (defaultable *DefaultsModuleBase) ConvertWithBp2build(ctx TopDownMutatorContext) {}
185
Paul Duffine62432f2019-07-24 12:51:21 +0100186func InitDefaultsModule(module DefaultsModule) {
Paul Duffin3f98d142020-09-02 13:28:25 +0100187 commonProperties := &commonProperties{}
Paul Duffin63c6e182019-07-24 14:24:38 +0100188
Colin Cross36242852017-06-23 15:06:31 -0700189 module.AddProperties(
Colin Crossfc754582016-05-17 16:34:16 -0700190 &hostAndDeviceProperties{},
Paul Duffin63c6e182019-07-24 14:24:38 +0100191 commonProperties,
Paul Duffined875132020-09-02 13:08:57 +0100192 &ApexProperties{},
193 &distProperties{})
Colin Crossfc754582016-05-17 16:34:16 -0700194
Liz Kammer416201d2021-12-15 13:18:42 -0500195 // Bazel module must be initialized _before_ Defaults to be included in cc_defaults module.
196 InitBazelModule(module)
Colin Crosseabaedd2020-02-06 17:01:55 -0800197 initAndroidModuleBase(module)
198 initProductVariableModule(module)
Colin Crossa6845402020-11-16 15:08:19 -0800199 initArchModule(module)
Colin Cross1f44a3a2017-07-07 14:33:33 -0700200 InitDefaultableModule(module)
Colin Crossfc754582016-05-17 16:34:16 -0700201
Paul Duffin7df7fb02019-07-24 12:26:14 +0100202 // Add properties that will not have defaults applied to them.
Colin Cross08d6f8f2020-11-19 02:33:19 +0000203 base := module.base()
Paul Duffin3f98d142020-09-02 13:28:25 +0100204 defaultsVisibility := &DefaultsVisibilityProperties{}
Paul Duffin95d53b52019-07-24 13:45:05 +0100205 module.AddProperties(&base.nameProperties, defaultsVisibility)
Colin Crossfc754582016-05-17 16:34:16 -0700206
Paul Duffin63c6e182019-07-24 14:24:38 +0100207 // Unlike non-defaults modules the visibility property is not stored in m.base().commonProperties.
Paul Duffin5ec73ec2020-05-01 17:52:01 +0100208 // Instead it is stored in a separate instance of commonProperties created above so clear the
209 // existing list of properties.
210 clearVisibilityProperties(module)
211
212 // The defaults_visibility property controls the visibility of a defaults module so it must be
213 // set as the primary property, which also adds it to the list.
214 setPrimaryVisibilityProperty(module, "defaults_visibility", &defaultsVisibility.Defaults_visibility)
215
Paul Duffin63c6e182019-07-24 14:24:38 +0100216 // The visibility property needs to be checked (but not parsed) by the visibility module during
Paul Duffin5ec73ec2020-05-01 17:52:01 +0100217 // its checking phase and parsing phase so add it to the list as a normal property.
218 AddVisibilityProperty(module, "visibility", &commonProperties.Visibility)
Paul Duffin63c6e182019-07-24 14:24:38 +0100219
Bob Badour37af0462021-01-07 03:34:31 +0000220 // The applicable licenses property for defaults is 'licenses'.
221 setPrimaryLicensesProperty(module, "licenses", &commonProperties.Licenses)
222
Colin Crosscfad1192015-11-02 16:43:11 -0800223}
224
Colin Cross1f44a3a2017-07-07 14:33:33 -0700225var _ Defaults = (*DefaultsModuleBase)(nil)
Colin Crosscfad1192015-11-02 16:43:11 -0800226
Jingwen Chen84817de2021-11-17 10:57:35 +0000227// applyNamespacedVariableDefaults only runs in bp2build mode for
228// defaultable/defaults modules. Its purpose is to merge namespaced product
229// variable props from defaults deps, even if those defaults are custom module
230// types created from soong_config_module_type, e.g. one that's wrapping a
231// cc_defaults or java_defaults.
232func applyNamespacedVariableDefaults(defaultDep Defaults, ctx TopDownMutatorContext) {
233 var dep, b Bazelable
234
235 dep, ok := defaultDep.(Bazelable)
236 if !ok {
237 if depMod, ok := defaultDep.(Module); ok {
238 // Track that this dependency hasn't been converted to bp2build yet.
239 ctx.AddUnconvertedBp2buildDep(depMod.Name())
240 return
241 } else {
242 panic("Expected default dep to be a Module.")
243 }
244 }
245
246 b, ok = ctx.Module().(Bazelable)
247 if !ok {
248 return
249 }
250
251 // namespacedVariableProps is a map from namespaces (e.g. acme, android,
252 // vendor_foo) to a slice of soong_config_variable struct pointers,
253 // containing properties for that particular module.
254 src := dep.namespacedVariableProps()
255 dst := b.namespacedVariableProps()
256 if dst == nil {
257 dst = make(namespacedVariableProperties)
258 }
259
260 // Propagate all soong_config_variable structs from the dep. We'll merge the
261 // actual property values later in variable.go.
262 for namespace := range src {
263 if dst[namespace] == nil {
264 dst[namespace] = []interface{}{}
265 }
266 for _, i := range src[namespace] {
267 dst[namespace] = append(dst[namespace], i)
268 }
269 }
270
271 b.setNamespacedVariableProps(dst)
272}
273
Colin Cross1f44a3a2017-07-07 14:33:33 -0700274func (defaultable *DefaultableModuleBase) applyDefaults(ctx TopDownMutatorContext,
Colin Cross13177012016-08-09 12:00:45 -0700275 defaultsList []Defaults) {
Colin Crosscfad1192015-11-02 16:43:11 -0800276
Colin Cross13177012016-08-09 12:00:45 -0700277 for _, defaults := range defaultsList {
Jingwen Chen84817de2021-11-17 10:57:35 +0000278 if ctx.Config().runningAsBp2Build {
279 applyNamespacedVariableDefaults(defaults, ctx)
280 }
Colin Cross13177012016-08-09 12:00:45 -0700281 for _, prop := range defaultable.defaultableProperties {
Colin Crosseabaedd2020-02-06 17:01:55 -0800282 if prop == defaultable.defaultableVariableProperties {
283 defaultable.applyDefaultVariableProperties(ctx, defaults, prop)
284 } else {
285 defaultable.applyDefaultProperties(ctx, defaults, prop)
286 }
287 }
288 }
289}
290
291// Product variable properties need special handling, the type of the filtered product variable
292// property struct may not be identical between the defaults module and the defaultable module.
293// Use PrependMatchingProperties to apply whichever properties match.
294func (defaultable *DefaultableModuleBase) applyDefaultVariableProperties(ctx TopDownMutatorContext,
295 defaults Defaults, defaultableProp interface{}) {
296 if defaultableProp == nil {
297 return
298 }
299
300 defaultsProp := defaults.productVariableProperties()
301 if defaultsProp == nil {
302 return
303 }
304
305 dst := []interface{}{
306 defaultableProp,
307 // Put an empty copy of the src properties into dst so that properties in src that are not in dst
308 // don't cause a "failed to find property to extend" error.
309 proptools.CloneEmptyProperties(reflect.ValueOf(defaultsProp)).Interface(),
310 }
311
312 err := proptools.PrependMatchingProperties(dst, defaultsProp, nil)
313 if err != nil {
314 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
315 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
316 } else {
317 panic(err)
318 }
319 }
320}
321
322func (defaultable *DefaultableModuleBase) applyDefaultProperties(ctx TopDownMutatorContext,
323 defaults Defaults, defaultableProp interface{}) {
324
325 for _, def := range defaults.properties() {
326 if proptools.TypeEqual(defaultableProp, def) {
327 err := proptools.PrependProperties(defaultableProp, def, nil)
328 if err != nil {
329 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
330 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
331 } else {
332 panic(err)
Colin Crosscfad1192015-11-02 16:43:11 -0800333 }
334 }
335 }
336 }
337}
338
Colin Cross89536d42017-07-07 14:35:50 -0700339func RegisterDefaultsPreArchMutators(ctx RegisterMutatorsContext) {
Colin Crosscec81712017-07-13 14:43:27 -0700340 ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel()
341 ctx.TopDown("defaults", defaultsMutator).Parallel()
342}
343
Colin Cross635c3b02016-05-18 15:37:25 -0700344func defaultsDepsMutator(ctx BottomUpMutatorContext) {
Colin Crosscfad1192015-11-02 16:43:11 -0800345 if defaultable, ok := ctx.Module().(Defaultable); ok {
Colin Crossc99deeb2016-04-11 15:06:20 -0700346 ctx.AddDependency(ctx.Module(), DefaultsDepTag, defaultable.defaults().Defaults...)
Colin Crosscfad1192015-11-02 16:43:11 -0800347 }
348}
349
Colin Cross13177012016-08-09 12:00:45 -0700350func defaultsMutator(ctx TopDownMutatorContext) {
Paul Duffinafa9fa12020-04-29 16:47:28 +0100351 if defaultable, ok := ctx.Module().(Defaultable); ok {
352 if len(defaultable.defaults().Defaults) > 0 {
353 var defaultsList []Defaults
354 seen := make(map[Defaults]bool)
Colin Crossa1ce2a02018-06-20 15:19:39 -0700355
Paul Duffinafa9fa12020-04-29 16:47:28 +0100356 ctx.WalkDeps(func(module, parent Module) bool {
357 if ctx.OtherModuleDependencyTag(module) == DefaultsDepTag {
358 if defaults, ok := module.(Defaults); ok {
359 if !seen[defaults] {
360 seen[defaults] = true
361 defaultsList = append(defaultsList, defaults)
362 return len(defaults.defaults().Defaults) > 0
363 }
364 } else {
365 ctx.PropertyErrorf("defaults", "module %s is not an defaults module",
366 ctx.OtherModuleName(module))
Colin Crossa1ce2a02018-06-20 15:19:39 -0700367 }
Colin Crosscfad1192015-11-02 16:43:11 -0800368 }
Paul Duffinafa9fa12020-04-29 16:47:28 +0100369 return false
370 })
371 defaultable.applyDefaults(ctx, defaultsList)
372 }
373
374 defaultable.callHookIfAvailable(ctx)
Colin Crosscfad1192015-11-02 16:43:11 -0800375 }
376}