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 15 package android 16 17 import ( 18 "github.com/google/blueprint" 19 "github.com/google/blueprint/proptools" 20 ) 21 22 type defaultsDependencyTag struct { 23 blueprint.BaseDependencyTag 24 } 25 26 var DefaultsDepTag defaultsDependencyTag 27 28 type defaultsProperties struct { 29 Defaults []string 30 } 31 32 type DefaultableModuleBase struct { 33 defaultsProperties defaultsProperties 34 defaultableProperties []interface{} 35 } 36 37 func (d *DefaultableModuleBase) defaults() *defaultsProperties { 38 return &d.defaultsProperties 39 } 40 41 func (d *DefaultableModuleBase) setProperties(props []interface{}) { 42 d.defaultableProperties = props 43 } 44 45 type Defaultable interface { 46 defaults() *defaultsProperties 47 setProperties([]interface{}) 48 applyDefaults(TopDownMutatorContext, []Defaults) 49 } 50 51 type DefaultableModule interface { 52 Module 53 Defaultable 54 } 55 56 var _ Defaultable = (*DefaultableModuleBase)(nil) 57 58 func InitDefaultableModule(module DefaultableModule) { 59 module.(Defaultable).setProperties(module.(Module).GetProperties()) 60 61 module.AddProperties(module.defaults()) 62 } 63 64 type DefaultsModuleBase struct { 65 DefaultableModuleBase 66 defaultProperties []interface{} 67 } 68 69 type Defaults interface { 70 Defaultable 71 isDefaults() bool 72 properties() []interface{} 73 } 74 75 func (d *DefaultsModuleBase) isDefaults() bool { 76 return true 77 } 78 79 func (d *DefaultsModuleBase) properties() []interface{} { 80 return d.defaultableProperties 81 } 82 83 func InitDefaultsModule(module DefaultableModule) { 84 module.AddProperties( 85 &hostAndDeviceProperties{}, 86 &commonProperties{}, 87 &variableProperties{}) 88 89 InitArchModule(module) 90 InitDefaultableModule(module) 91 92 module.AddProperties(&module.base().nameProperties) 93 94 module.base().module = module 95 } 96 97 var _ Defaults = (*DefaultsModuleBase)(nil) 98 99 func (defaultable *DefaultableModuleBase) applyDefaults(ctx TopDownMutatorContext, 100 defaultsList []Defaults) { 101 102 for _, defaults := range defaultsList { 103 for _, prop := range defaultable.defaultableProperties { 104 for _, def := range defaults.properties() { 105 if proptools.TypeEqual(prop, def) { 106 err := proptools.PrependProperties(prop, def, nil) 107 if err != nil { 108 if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok { 109 ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error()) 110 } else { 111 panic(err) 112 } 113 } 114 } 115 } 116 } 117 } 118 } 119 120 func RegisterDefaultsPreArchMutators(ctx RegisterMutatorsContext) { 121 ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel() 122 ctx.TopDown("defaults", defaultsMutator).Parallel() 123 } 124 125 func defaultsDepsMutator(ctx BottomUpMutatorContext) { 126 if defaultable, ok := ctx.Module().(Defaultable); ok { 127 ctx.AddDependency(ctx.Module(), DefaultsDepTag, defaultable.defaults().Defaults...) 128 } 129 } 130 131 func defaultsMutator(ctx TopDownMutatorContext) { 132 if defaultable, ok := ctx.Module().(Defaultable); ok && len(defaultable.defaults().Defaults) > 0 { 133 var defaultsList []Defaults 134 seen := make(map[Defaults]bool) 135 136 ctx.WalkDeps(func(module, parent Module) bool { 137 if ctx.OtherModuleDependencyTag(module) == DefaultsDepTag { 138 if defaults, ok := module.(Defaults); ok { 139 if !seen[defaults] { 140 seen[defaults] = true 141 defaultsList = append(defaultsList, defaults) 142 return len(defaults.defaults().Defaults) > 0 143 } 144 } else { 145 ctx.PropertyErrorf("defaults", "module %s is not an defaults module", 146 ctx.OtherModuleName(module)) 147 } 148 } 149 return false 150 }) 151 defaultable.applyDefaults(ctx, defaultsList) 152 } 153 } 154