blob: cc723f728b9783c96260e5a8bb7e50f43a45da84 [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
Chris Parsons39a16972023-06-08 14:28:51 +000020 "android/soong/ui/metrics/bp2build_metrics_proto"
Colin Crosscfad1192015-11-02 16:43:11 -080021 "github.com/google/blueprint"
22 "github.com/google/blueprint/proptools"
23)
24
Colin Crossc99deeb2016-04-11 15:06:20 -070025type defaultsDependencyTag struct {
26 blueprint.BaseDependencyTag
27}
28
29var DefaultsDepTag defaultsDependencyTag
30
Colin Crosscfad1192015-11-02 16:43:11 -080031type defaultsProperties struct {
32 Defaults []string
33}
34
Colin Cross1f44a3a2017-07-07 14:33:33 -070035type DefaultableModuleBase struct {
Colin Crosseabaedd2020-02-06 17:01:55 -080036 defaultsProperties defaultsProperties
37 defaultableProperties []interface{}
38 defaultableVariableProperties interface{}
Paul Duffinafa9fa12020-04-29 16:47:28 +010039
40 // The optional hook to call after any defaults have been applied.
41 hook DefaultableHook
Colin Crosscfad1192015-11-02 16:43:11 -080042}
43
Colin Cross1f44a3a2017-07-07 14:33:33 -070044func (d *DefaultableModuleBase) defaults() *defaultsProperties {
Colin Crosscfad1192015-11-02 16:43:11 -080045 return &d.defaultsProperties
46}
47
Colin Crosseabaedd2020-02-06 17:01:55 -080048func (d *DefaultableModuleBase) setProperties(props []interface{}, variableProperties interface{}) {
Colin Crosscfad1192015-11-02 16:43:11 -080049 d.defaultableProperties = props
Colin Crosseabaedd2020-02-06 17:01:55 -080050 d.defaultableVariableProperties = variableProperties
Colin Crosscfad1192015-11-02 16:43:11 -080051}
52
Paul Duffinafa9fa12020-04-29 16:47:28 +010053func (d *DefaultableModuleBase) SetDefaultableHook(hook DefaultableHook) {
54 d.hook = hook
55}
56
Jihoon Kangd48abd52023-02-02 22:32:31 +000057func (d *DefaultableModuleBase) CallHookIfAvailable(ctx DefaultableHookContext) {
Paul Duffinafa9fa12020-04-29 16:47:28 +010058 if d.hook != nil {
59 d.hook(ctx)
60 }
61}
62
Paul Duffin7df7fb02019-07-24 12:26:14 +010063// Interface that must be supported by any module to which defaults can be applied.
Colin Crosscfad1192015-11-02 16:43:11 -080064type Defaultable interface {
Paul Duffin7df7fb02019-07-24 12:26:14 +010065 // Get a pointer to the struct containing the Defaults property.
Colin Crosscfad1192015-11-02 16:43:11 -080066 defaults() *defaultsProperties
Paul Duffin7df7fb02019-07-24 12:26:14 +010067
68 // Set the property structures into which defaults will be added.
Colin Crosseabaedd2020-02-06 17:01:55 -080069 setProperties(props []interface{}, variableProperties interface{})
Paul Duffin7df7fb02019-07-24 12:26:14 +010070
Liz Kammereeeb9522023-03-10 18:53:41 -050071 // Apply defaults from the supplied Defaults to the property structures supplied to
Paul Duffin7df7fb02019-07-24 12:26:14 +010072 // setProperties(...).
Liz Kammereeeb9522023-03-10 18:53:41 -050073 applyDefaults(TopDownMutatorContext, []Defaults)
Paul Duffinafa9fa12020-04-29 16:47:28 +010074
75 // Set the hook to be called after any defaults have been applied.
76 //
77 // Should be used in preference to a AddLoadHook when the behavior of the load
78 // hook is dependent on properties supplied in the Android.bp file.
79 SetDefaultableHook(hook DefaultableHook)
80
81 // Call the hook if specified.
Jihoon Kangd48abd52023-02-02 22:32:31 +000082 CallHookIfAvailable(context DefaultableHookContext)
Colin Crosscfad1192015-11-02 16:43:11 -080083}
84
Colin Cross1f44a3a2017-07-07 14:33:33 -070085type DefaultableModule interface {
86 Module
87 Defaultable
Colin Crosscfad1192015-11-02 16:43:11 -080088}
89
Colin Cross1f44a3a2017-07-07 14:33:33 -070090var _ Defaultable = (*DefaultableModuleBase)(nil)
91
92func InitDefaultableModule(module DefaultableModule) {
Ustafe201fe2021-12-06 15:13:36 -050093 if module.base().module == nil {
Colin Crosseabaedd2020-02-06 17:01:55 -080094 panic("InitAndroidModule must be called before InitDefaultableModule")
95 }
Liz Kammer416201d2021-12-15 13:18:42 -050096
Ustafe201fe2021-12-06 15:13:36 -050097 module.setProperties(module.GetProperties(), module.base().variableProperties)
Colin Cross1f44a3a2017-07-07 14:33:33 -070098
99 module.AddProperties(module.defaults())
100}
101
Paul Duffinafa9fa12020-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
Colin Cross18f840c2021-05-20 17:56:54 -0700107 AddMissingDependencies(missingDeps []string)
Paul Duffinafa9fa12020-04-29 16:47:28 +0100108}
109
110type DefaultableHook func(ctx DefaultableHookContext)
111
Paul Duffin95d53b52019-07-24 13:45:05 +0100112// The Defaults_visibility property.
113type DefaultsVisibilityProperties struct {
114
115 // Controls the visibility of the defaults module itself.
116 Defaults_visibility []string
117}
118
Colin Cross1f44a3a2017-07-07 14:33:33 -0700119type DefaultsModuleBase struct {
120 DefaultableModuleBase
Liz Kammer416201d2021-12-15 13:18:42 -0500121
122 // Included to support setting bazel_module.label for multiple Soong modules to the same Bazel
123 // target. This is primarily useful for modules that were architecture specific and instead are
124 // handled in Bazel as a select().
125 BazelModuleBase
Colin Crosscfad1192015-11-02 16:43:11 -0800126}
127
Martin Stjernholmebd757d2019-05-24 11:00:30 +0100128// The common pattern for defaults modules is to register separate instances of
129// the xxxProperties structs in the AddProperties calls, rather than reusing the
130// ones inherited from Module.
131//
132// The effect is that e.g. myDefaultsModuleInstance.base().xxxProperties won't
133// contain the values that have been set for the defaults module. Rather, to
134// retrieve the values it is necessary to iterate over properties(). E.g. to get
135// the commonProperties instance that have the real values:
136//
Colin Crossd079e0b2022-08-16 10:27:33 -0700137// d := myModule.(Defaults)
138// for _, props := range d.properties() {
139// if cp, ok := props.(*commonProperties); ok {
140// ... access property values in cp ...
141// }
142// }
Martin Stjernholmebd757d2019-05-24 11:00:30 +0100143//
144// The rationale is that the properties on a defaults module apply to the
145// defaultable modules using it, not to the defaults module itself. E.g. setting
146// the "enabled" property false makes inheriting modules disabled by default,
147// rather than disabling the defaults module itself.
Colin Crosscfad1192015-11-02 16:43:11 -0800148type Defaults interface {
Colin Crosse7b07132016-07-27 10:15:06 -0700149 Defaultable
Paul Duffin7df7fb02019-07-24 12:26:14 +0100150
151 // Although this function is unused it is actually needed to ensure that only modules that embed
152 // DefaultsModuleBase will type-assert to the Defaults interface.
Colin Crosscfad1192015-11-02 16:43:11 -0800153 isDefaults() bool
Paul Duffin7df7fb02019-07-24 12:26:14 +0100154
155 // Get the structures containing the properties for which defaults can be provided.
Colin Crosscfad1192015-11-02 16:43:11 -0800156 properties() []interface{}
Paul Duffin63c6e182019-07-24 14:24:38 +0100157
Colin Crosseabaedd2020-02-06 17:01:55 -0800158 productVariableProperties() interface{}
Colin Crosscfad1192015-11-02 16:43:11 -0800159}
160
Colin Cross1f44a3a2017-07-07 14:33:33 -0700161func (d *DefaultsModuleBase) isDefaults() bool {
Colin Crosscfad1192015-11-02 16:43:11 -0800162 return true
163}
164
Paul Duffine62432f2019-07-24 12:51:21 +0100165type DefaultsModule interface {
166 Module
167 Defaults
Liz Kammer416201d2021-12-15 13:18:42 -0500168 Bazelable
Paul Duffine62432f2019-07-24 12:51:21 +0100169}
170
Colin Cross1f44a3a2017-07-07 14:33:33 -0700171func (d *DefaultsModuleBase) properties() []interface{} {
Colin Crosse7b07132016-07-27 10:15:06 -0700172 return d.defaultableProperties
Colin Crosscfad1192015-11-02 16:43:11 -0800173}
174
Colin Crosseabaedd2020-02-06 17:01:55 -0800175func (d *DefaultsModuleBase) productVariableProperties() interface{} {
176 return d.defaultableVariableProperties
177}
178
Liz Kammer416201d2021-12-15 13:18:42 -0500179func (d *DefaultsModuleBase) GenerateAndroidBuildActions(ctx ModuleContext) {}
Colin Cross59037622019-06-10 13:12:56 -0700180
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400181// ConvertWithBp2build to fulfill Bazelable interface; however, at this time defaults module are
182// *NOT* converted with bp2build
Chris Parsons637458d2023-09-19 20:09:00 +0000183func (defaultable *DefaultsModuleBase) ConvertWithBp2build(ctx Bp2buildMutatorContext) {
Chris Parsons39a16972023-06-08 14:28:51 +0000184 // Defaults types are never convertible.
185 ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
186}
Liz Kammerbe46fcc2021-11-01 15:32:43 -0400187
Paul Duffine62432f2019-07-24 12:51:21 +0100188func InitDefaultsModule(module DefaultsModule) {
Paul Duffin3f98d142020-09-02 13:28:25 +0100189 commonProperties := &commonProperties{}
Paul Duffin63c6e182019-07-24 14:24:38 +0100190
Colin Cross36242852017-06-23 15:06:31 -0700191 module.AddProperties(
Colin Crossfc754582016-05-17 16:34:16 -0700192 &hostAndDeviceProperties{},
Paul Duffin63c6e182019-07-24 14:24:38 +0100193 commonProperties,
Paul Duffined875132020-09-02 13:08:57 +0100194 &ApexProperties{},
195 &distProperties{})
Colin Crossfc754582016-05-17 16:34:16 -0700196
Liz Kammer416201d2021-12-15 13:18:42 -0500197 // Bazel module must be initialized _before_ Defaults to be included in cc_defaults module.
198 InitBazelModule(module)
Colin Crosseabaedd2020-02-06 17:01:55 -0800199 initAndroidModuleBase(module)
200 initProductVariableModule(module)
Colin Crossa6845402020-11-16 15:08:19 -0800201 initArchModule(module)
Colin Cross1f44a3a2017-07-07 14:33:33 -0700202 InitDefaultableModule(module)
Colin Crossfc754582016-05-17 16:34:16 -0700203
Paul Duffin7df7fb02019-07-24 12:26:14 +0100204 // Add properties that will not have defaults applied to them.
Colin Cross08d6f8f2020-11-19 02:33:19 +0000205 base := module.base()
Paul Duffin3f98d142020-09-02 13:28:25 +0100206 defaultsVisibility := &DefaultsVisibilityProperties{}
Paul Duffin95d53b52019-07-24 13:45:05 +0100207 module.AddProperties(&base.nameProperties, defaultsVisibility)
Colin Crossfc754582016-05-17 16:34:16 -0700208
Paul Duffin63c6e182019-07-24 14:24:38 +0100209 // Unlike non-defaults modules the visibility property is not stored in m.base().commonProperties.
Paul Duffin5ec73ec2020-05-01 17:52:01 +0100210 // Instead it is stored in a separate instance of commonProperties created above so clear the
211 // existing list of properties.
212 clearVisibilityProperties(module)
213
214 // The defaults_visibility property controls the visibility of a defaults module so it must be
215 // set as the primary property, which also adds it to the list.
216 setPrimaryVisibilityProperty(module, "defaults_visibility", &defaultsVisibility.Defaults_visibility)
217
Paul Duffin63c6e182019-07-24 14:24:38 +0100218 // The visibility property needs to be checked (but not parsed) by the visibility module during
Paul Duffin5ec73ec2020-05-01 17:52:01 +0100219 // its checking phase and parsing phase so add it to the list as a normal property.
220 AddVisibilityProperty(module, "visibility", &commonProperties.Visibility)
Paul Duffin63c6e182019-07-24 14:24:38 +0100221
Bob Badour37af0462021-01-07 03:34:31 +0000222 // The applicable licenses property for defaults is 'licenses'.
223 setPrimaryLicensesProperty(module, "licenses", &commonProperties.Licenses)
Colin Crosscfad1192015-11-02 16:43:11 -0800224}
225
Colin Cross1f44a3a2017-07-07 14:33:33 -0700226var _ Defaults = (*DefaultsModuleBase)(nil)
Colin Crosscfad1192015-11-02 16:43:11 -0800227
Jingwen Chen84817de2021-11-17 10:57:35 +0000228// applyNamespacedVariableDefaults only runs in bp2build mode for
229// defaultable/defaults modules. Its purpose is to merge namespaced product
230// variable props from defaults deps, even if those defaults are custom module
231// types created from soong_config_module_type, e.g. one that's wrapping a
232// cc_defaults or java_defaults.
233func applyNamespacedVariableDefaults(defaultDep Defaults, ctx TopDownMutatorContext) {
234 var dep, b Bazelable
235
236 dep, ok := defaultDep.(Bazelable)
237 if !ok {
238 if depMod, ok := defaultDep.(Module); ok {
239 // Track that this dependency hasn't been converted to bp2build yet.
240 ctx.AddUnconvertedBp2buildDep(depMod.Name())
241 return
242 } else {
243 panic("Expected default dep to be a Module.")
244 }
245 }
246
247 b, ok = ctx.Module().(Bazelable)
248 if !ok {
249 return
250 }
251
252 // namespacedVariableProps is a map from namespaces (e.g. acme, android,
253 // vendor_foo) to a slice of soong_config_variable struct pointers,
254 // containing properties for that particular module.
255 src := dep.namespacedVariableProps()
256 dst := b.namespacedVariableProps()
257 if dst == nil {
258 dst = make(namespacedVariableProperties)
259 }
260
261 // Propagate all soong_config_variable structs from the dep. We'll merge the
262 // actual property values later in variable.go.
263 for namespace := range src {
264 if dst[namespace] == nil {
265 dst[namespace] = []interface{}{}
266 }
267 for _, i := range src[namespace] {
268 dst[namespace] = append(dst[namespace], i)
269 }
270 }
271
272 b.setNamespacedVariableProps(dst)
273}
274
Colin Cross1f44a3a2017-07-07 14:33:33 -0700275func (defaultable *DefaultableModuleBase) applyDefaults(ctx TopDownMutatorContext,
Liz Kammereeeb9522023-03-10 18:53:41 -0500276 defaultsList []Defaults) {
Colin Crosscfad1192015-11-02 16:43:11 -0800277
Colin Cross13177012016-08-09 12:00:45 -0700278 for _, defaults := range defaultsList {
Chris Parsonsad876012022-08-20 14:48:32 -0400279 if ctx.Config().BuildMode == Bp2build {
Jingwen Chen84817de2021-11-17 10:57:35 +0000280 applyNamespacedVariableDefaults(defaults, ctx)
281 }
Liz Kammereeeb9522023-03-10 18:53:41 -0500282 for _, prop := range defaultable.defaultableProperties {
283 if prop == defaultable.defaultableVariableProperties {
284 defaultable.applyDefaultVariableProperties(ctx, defaults, prop)
Paul Duffin79996272022-05-04 11:39:52 +0000285 } else {
Liz Kammereeeb9522023-03-10 18:53:41 -0500286 defaultable.applyDefaultProperties(ctx, defaults, prop)
Paul Duffin79996272022-05-04 11:39:52 +0000287 }
288 }
289 }
290}
291
Colin Crosseabaedd2020-02-06 17:01:55 -0800292// Product variable properties need special handling, the type of the filtered product variable
293// property struct may not be identical between the defaults module and the defaultable module.
294// Use PrependMatchingProperties to apply whichever properties match.
Liz Kammereeeb9522023-03-10 18:53:41 -0500295func (defaultable *DefaultableModuleBase) applyDefaultVariableProperties(ctx TopDownMutatorContext,
296 defaults Defaults, defaultableProp interface{}) {
Colin Crosseabaedd2020-02-06 17:01:55 -0800297 if defaultableProp == nil {
Liz Kammereeeb9522023-03-10 18:53:41 -0500298 return
Colin Crosseabaedd2020-02-06 17:01:55 -0800299 }
300
301 defaultsProp := defaults.productVariableProperties()
302 if defaultsProp == nil {
Liz Kammereeeb9522023-03-10 18:53:41 -0500303 return
Colin Crosseabaedd2020-02-06 17:01:55 -0800304 }
305
306 dst := []interface{}{
307 defaultableProp,
308 // Put an empty copy of the src properties into dst so that properties in src that are not in dst
309 // don't cause a "failed to find property to extend" error.
310 proptools.CloneEmptyProperties(reflect.ValueOf(defaultsProp)).Interface(),
311 }
312
Liz Kammereeeb9522023-03-10 18:53:41 -0500313 err := proptools.PrependMatchingProperties(dst, defaultsProp, nil)
314 if err != nil {
315 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
316 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
317 } else {
318 panic(err)
319 }
320 }
Colin Crosseabaedd2020-02-06 17:01:55 -0800321}
322
Liz Kammereeeb9522023-03-10 18:53:41 -0500323func (defaultable *DefaultableModuleBase) applyDefaultProperties(ctx TopDownMutatorContext,
324 defaults Defaults, defaultableProp interface{}) {
Colin Crosseabaedd2020-02-06 17:01:55 -0800325
326 for _, def := range defaults.properties() {
327 if proptools.TypeEqual(defaultableProp, def) {
Liz Kammereeeb9522023-03-10 18:53:41 -0500328 err := proptools.PrependProperties(defaultableProp, def, nil)
Colin Crosseabaedd2020-02-06 17:01:55 -0800329 if err != nil {
Liz Kammereeeb9522023-03-10 18:53:41 -0500330 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
331 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
332 } else {
333 panic(err)
334 }
Colin Crosscfad1192015-11-02 16:43:11 -0800335 }
336 }
337 }
338}
339
Colin Cross89536d42017-07-07 14:35:50 -0700340func RegisterDefaultsPreArchMutators(ctx RegisterMutatorsContext) {
Colin Crosscec81712017-07-13 14:43:27 -0700341 ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel()
342 ctx.TopDown("defaults", defaultsMutator).Parallel()
343}
344
Colin Cross635c3b02016-05-18 15:37:25 -0700345func defaultsDepsMutator(ctx BottomUpMutatorContext) {
Colin Crosscfad1192015-11-02 16:43:11 -0800346 if defaultable, ok := ctx.Module().(Defaultable); ok {
Colin Crossc99deeb2016-04-11 15:06:20 -0700347 ctx.AddDependency(ctx.Module(), DefaultsDepTag, defaultable.defaults().Defaults...)
Colin Crosscfad1192015-11-02 16:43:11 -0800348 }
349}
350
Colin Cross13177012016-08-09 12:00:45 -0700351func defaultsMutator(ctx TopDownMutatorContext) {
Paul Duffinafa9fa12020-04-29 16:47:28 +0100352 if defaultable, ok := ctx.Module().(Defaultable); ok {
353 if len(defaultable.defaults().Defaults) > 0 {
Liz Kammereeeb9522023-03-10 18:53:41 -0500354 var defaultsList []Defaults
Paul Duffinafa9fa12020-04-29 16:47:28 +0100355 seen := make(map[Defaults]bool)
Colin Crossa1ce2a02018-06-20 15:19:39 -0700356
Paul Duffinafa9fa12020-04-29 16:47:28 +0100357 ctx.WalkDeps(func(module, parent Module) bool {
358 if ctx.OtherModuleDependencyTag(module) == DefaultsDepTag {
Liz Kammereeeb9522023-03-10 18:53:41 -0500359 if defaults, ok := module.(Defaults); ok {
Paul Duffinafa9fa12020-04-29 16:47:28 +0100360 if !seen[defaults] {
361 seen[defaults] = true
362 defaultsList = append(defaultsList, defaults)
363 return len(defaults.defaults().Defaults) > 0
364 }
365 } else {
366 ctx.PropertyErrorf("defaults", "module %s is not an defaults module",
367 ctx.OtherModuleName(module))
Colin Crossa1ce2a02018-06-20 15:19:39 -0700368 }
Colin Crosscfad1192015-11-02 16:43:11 -0800369 }
Paul Duffinafa9fa12020-04-29 16:47:28 +0100370 return false
371 })
372 defaultable.applyDefaults(ctx, defaultsList)
373 }
374
Jihoon Kangd48abd52023-02-02 22:32:31 +0000375 defaultable.CallHookIfAvailable(ctx)
Colin Crosscfad1192015-11-02 16:43:11 -0800376 }
377}