defaults.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  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. package android
  15. import (
  16. "reflect"
  17. "android/soong/ui/metrics/bp2build_metrics_proto"
  18. "github.com/google/blueprint"
  19. "github.com/google/blueprint/proptools"
  20. )
  21. type defaultsDependencyTag struct {
  22. blueprint.BaseDependencyTag
  23. }
  24. var DefaultsDepTag defaultsDependencyTag
  25. type defaultsProperties struct {
  26. Defaults []string
  27. }
  28. type DefaultableModuleBase struct {
  29. defaultsProperties defaultsProperties
  30. defaultableProperties []interface{}
  31. defaultableVariableProperties interface{}
  32. // The optional hook to call after any defaults have been applied.
  33. hook DefaultableHook
  34. }
  35. func (d *DefaultableModuleBase) defaults() *defaultsProperties {
  36. return &d.defaultsProperties
  37. }
  38. func (d *DefaultableModuleBase) setProperties(props []interface{}, variableProperties interface{}) {
  39. d.defaultableProperties = props
  40. d.defaultableVariableProperties = variableProperties
  41. }
  42. func (d *DefaultableModuleBase) SetDefaultableHook(hook DefaultableHook) {
  43. d.hook = hook
  44. }
  45. func (d *DefaultableModuleBase) CallHookIfAvailable(ctx DefaultableHookContext) {
  46. if d.hook != nil {
  47. d.hook(ctx)
  48. }
  49. }
  50. // Interface that must be supported by any module to which defaults can be applied.
  51. type Defaultable interface {
  52. // Get a pointer to the struct containing the Defaults property.
  53. defaults() *defaultsProperties
  54. // Set the property structures into which defaults will be added.
  55. setProperties(props []interface{}, variableProperties interface{})
  56. // Apply defaults from the supplied Defaults to the property structures supplied to
  57. // setProperties(...).
  58. applyDefaults(TopDownMutatorContext, []Defaults)
  59. // Set the hook to be called after any defaults have been applied.
  60. //
  61. // Should be used in preference to a AddLoadHook when the behavior of the load
  62. // hook is dependent on properties supplied in the Android.bp file.
  63. SetDefaultableHook(hook DefaultableHook)
  64. // Call the hook if specified.
  65. CallHookIfAvailable(context DefaultableHookContext)
  66. }
  67. type DefaultableModule interface {
  68. Module
  69. Defaultable
  70. }
  71. var _ Defaultable = (*DefaultableModuleBase)(nil)
  72. func InitDefaultableModule(module DefaultableModule) {
  73. if module.base().module == nil {
  74. panic("InitAndroidModule must be called before InitDefaultableModule")
  75. }
  76. module.setProperties(module.GetProperties(), module.base().variableProperties)
  77. module.AddProperties(module.defaults())
  78. }
  79. // A restricted subset of context methods, similar to LoadHookContext.
  80. type DefaultableHookContext interface {
  81. EarlyModuleContext
  82. CreateModule(ModuleFactory, ...interface{}) Module
  83. AddMissingDependencies(missingDeps []string)
  84. }
  85. type DefaultableHook func(ctx DefaultableHookContext)
  86. // The Defaults_visibility property.
  87. type DefaultsVisibilityProperties struct {
  88. // Controls the visibility of the defaults module itself.
  89. Defaults_visibility []string
  90. }
  91. type DefaultsModuleBase struct {
  92. DefaultableModuleBase
  93. // Included to support setting bazel_module.label for multiple Soong modules to the same Bazel
  94. // target. This is primarily useful for modules that were architecture specific and instead are
  95. // handled in Bazel as a select().
  96. BazelModuleBase
  97. }
  98. // The common pattern for defaults modules is to register separate instances of
  99. // the xxxProperties structs in the AddProperties calls, rather than reusing the
  100. // ones inherited from Module.
  101. //
  102. // The effect is that e.g. myDefaultsModuleInstance.base().xxxProperties won't
  103. // contain the values that have been set for the defaults module. Rather, to
  104. // retrieve the values it is necessary to iterate over properties(). E.g. to get
  105. // the commonProperties instance that have the real values:
  106. //
  107. // d := myModule.(Defaults)
  108. // for _, props := range d.properties() {
  109. // if cp, ok := props.(*commonProperties); ok {
  110. // ... access property values in cp ...
  111. // }
  112. // }
  113. //
  114. // The rationale is that the properties on a defaults module apply to the
  115. // defaultable modules using it, not to the defaults module itself. E.g. setting
  116. // the "enabled" property false makes inheriting modules disabled by default,
  117. // rather than disabling the defaults module itself.
  118. type Defaults interface {
  119. Defaultable
  120. // Although this function is unused it is actually needed to ensure that only modules that embed
  121. // DefaultsModuleBase will type-assert to the Defaults interface.
  122. isDefaults() bool
  123. // Get the structures containing the properties for which defaults can be provided.
  124. properties() []interface{}
  125. productVariableProperties() interface{}
  126. }
  127. func (d *DefaultsModuleBase) isDefaults() bool {
  128. return true
  129. }
  130. type DefaultsModule interface {
  131. Module
  132. Defaults
  133. Bazelable
  134. }
  135. func (d *DefaultsModuleBase) properties() []interface{} {
  136. return d.defaultableProperties
  137. }
  138. func (d *DefaultsModuleBase) productVariableProperties() interface{} {
  139. return d.defaultableVariableProperties
  140. }
  141. func (d *DefaultsModuleBase) GenerateAndroidBuildActions(ctx ModuleContext) {}
  142. // ConvertWithBp2build to fulfill Bazelable interface; however, at this time defaults module are
  143. // *NOT* converted with bp2build
  144. func (defaultable *DefaultsModuleBase) ConvertWithBp2build(ctx TopDownMutatorContext) {
  145. // Defaults types are never convertible.
  146. ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
  147. }
  148. func InitDefaultsModule(module DefaultsModule) {
  149. commonProperties := &commonProperties{}
  150. module.AddProperties(
  151. &hostAndDeviceProperties{},
  152. commonProperties,
  153. &ApexProperties{},
  154. &distProperties{})
  155. // Bazel module must be initialized _before_ Defaults to be included in cc_defaults module.
  156. InitBazelModule(module)
  157. initAndroidModuleBase(module)
  158. initProductVariableModule(module)
  159. initArchModule(module)
  160. InitDefaultableModule(module)
  161. // Add properties that will not have defaults applied to them.
  162. base := module.base()
  163. defaultsVisibility := &DefaultsVisibilityProperties{}
  164. module.AddProperties(&base.nameProperties, defaultsVisibility)
  165. // Unlike non-defaults modules the visibility property is not stored in m.base().commonProperties.
  166. // Instead it is stored in a separate instance of commonProperties created above so clear the
  167. // existing list of properties.
  168. clearVisibilityProperties(module)
  169. // The defaults_visibility property controls the visibility of a defaults module so it must be
  170. // set as the primary property, which also adds it to the list.
  171. setPrimaryVisibilityProperty(module, "defaults_visibility", &defaultsVisibility.Defaults_visibility)
  172. // The visibility property needs to be checked (but not parsed) by the visibility module during
  173. // its checking phase and parsing phase so add it to the list as a normal property.
  174. AddVisibilityProperty(module, "visibility", &commonProperties.Visibility)
  175. // The applicable licenses property for defaults is 'licenses'.
  176. setPrimaryLicensesProperty(module, "licenses", &commonProperties.Licenses)
  177. }
  178. var _ Defaults = (*DefaultsModuleBase)(nil)
  179. // applyNamespacedVariableDefaults only runs in bp2build mode for
  180. // defaultable/defaults modules. Its purpose is to merge namespaced product
  181. // variable props from defaults deps, even if those defaults are custom module
  182. // types created from soong_config_module_type, e.g. one that's wrapping a
  183. // cc_defaults or java_defaults.
  184. func applyNamespacedVariableDefaults(defaultDep Defaults, ctx TopDownMutatorContext) {
  185. var dep, b Bazelable
  186. dep, ok := defaultDep.(Bazelable)
  187. if !ok {
  188. if depMod, ok := defaultDep.(Module); ok {
  189. // Track that this dependency hasn't been converted to bp2build yet.
  190. ctx.AddUnconvertedBp2buildDep(depMod.Name())
  191. return
  192. } else {
  193. panic("Expected default dep to be a Module.")
  194. }
  195. }
  196. b, ok = ctx.Module().(Bazelable)
  197. if !ok {
  198. return
  199. }
  200. // namespacedVariableProps is a map from namespaces (e.g. acme, android,
  201. // vendor_foo) to a slice of soong_config_variable struct pointers,
  202. // containing properties for that particular module.
  203. src := dep.namespacedVariableProps()
  204. dst := b.namespacedVariableProps()
  205. if dst == nil {
  206. dst = make(namespacedVariableProperties)
  207. }
  208. // Propagate all soong_config_variable structs from the dep. We'll merge the
  209. // actual property values later in variable.go.
  210. for namespace := range src {
  211. if dst[namespace] == nil {
  212. dst[namespace] = []interface{}{}
  213. }
  214. for _, i := range src[namespace] {
  215. dst[namespace] = append(dst[namespace], i)
  216. }
  217. }
  218. b.setNamespacedVariableProps(dst)
  219. }
  220. func (defaultable *DefaultableModuleBase) applyDefaults(ctx TopDownMutatorContext,
  221. defaultsList []Defaults) {
  222. for _, defaults := range defaultsList {
  223. if ctx.Config().BuildMode == Bp2build {
  224. applyNamespacedVariableDefaults(defaults, ctx)
  225. }
  226. for _, prop := range defaultable.defaultableProperties {
  227. if prop == defaultable.defaultableVariableProperties {
  228. defaultable.applyDefaultVariableProperties(ctx, defaults, prop)
  229. } else {
  230. defaultable.applyDefaultProperties(ctx, defaults, prop)
  231. }
  232. }
  233. }
  234. }
  235. // Product variable properties need special handling, the type of the filtered product variable
  236. // property struct may not be identical between the defaults module and the defaultable module.
  237. // Use PrependMatchingProperties to apply whichever properties match.
  238. func (defaultable *DefaultableModuleBase) applyDefaultVariableProperties(ctx TopDownMutatorContext,
  239. defaults Defaults, defaultableProp interface{}) {
  240. if defaultableProp == nil {
  241. return
  242. }
  243. defaultsProp := defaults.productVariableProperties()
  244. if defaultsProp == nil {
  245. return
  246. }
  247. dst := []interface{}{
  248. defaultableProp,
  249. // Put an empty copy of the src properties into dst so that properties in src that are not in dst
  250. // don't cause a "failed to find property to extend" error.
  251. proptools.CloneEmptyProperties(reflect.ValueOf(defaultsProp)).Interface(),
  252. }
  253. err := proptools.PrependMatchingProperties(dst, defaultsProp, nil)
  254. if err != nil {
  255. if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
  256. ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
  257. } else {
  258. panic(err)
  259. }
  260. }
  261. }
  262. func (defaultable *DefaultableModuleBase) applyDefaultProperties(ctx TopDownMutatorContext,
  263. defaults Defaults, defaultableProp interface{}) {
  264. for _, def := range defaults.properties() {
  265. if proptools.TypeEqual(defaultableProp, def) {
  266. err := proptools.PrependProperties(defaultableProp, def, nil)
  267. if err != nil {
  268. if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
  269. ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
  270. } else {
  271. panic(err)
  272. }
  273. }
  274. }
  275. }
  276. }
  277. func RegisterDefaultsPreArchMutators(ctx RegisterMutatorsContext) {
  278. ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel()
  279. ctx.TopDown("defaults", defaultsMutator).Parallel()
  280. }
  281. func defaultsDepsMutator(ctx BottomUpMutatorContext) {
  282. if defaultable, ok := ctx.Module().(Defaultable); ok {
  283. ctx.AddDependency(ctx.Module(), DefaultsDepTag, defaultable.defaults().Defaults...)
  284. }
  285. }
  286. func defaultsMutator(ctx TopDownMutatorContext) {
  287. if defaultable, ok := ctx.Module().(Defaultable); ok {
  288. if len(defaultable.defaults().Defaults) > 0 {
  289. var defaultsList []Defaults
  290. seen := make(map[Defaults]bool)
  291. ctx.WalkDeps(func(module, parent Module) bool {
  292. if ctx.OtherModuleDependencyTag(module) == DefaultsDepTag {
  293. if defaults, ok := module.(Defaults); ok {
  294. if !seen[defaults] {
  295. seen[defaults] = true
  296. defaultsList = append(defaultsList, defaults)
  297. return len(defaults.defaults().Defaults) > 0
  298. }
  299. } else {
  300. ctx.PropertyErrorf("defaults", "module %s is not an defaults module",
  301. ctx.OtherModuleName(module))
  302. }
  303. }
  304. return false
  305. })
  306. defaultable.applyDefaults(ctx, defaultsList)
  307. }
  308. defaultable.CallHookIfAvailable(ctx)
  309. }
  310. }