1// Copyright (C) 2019 The Android Open Source Project 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 15package android 16 17import ( 18 "fmt" 19 "sort" 20 "strings" 21 22 "github.com/google/blueprint" 23 "github.com/google/blueprint/proptools" 24) 25 26// sdkAwareWithoutModule is provided simply to improve code navigation with the IDE. 27type sdkAwareWithoutModule interface { 28 // SdkMemberComponentName will return the name to use for a component of this module based on the 29 // base name of this module. 30 // 31 // The baseName is the name returned by ModuleBase.BaseModuleName(), i.e. the name specified in 32 // the name property in the .bp file so will not include the prebuilt_ prefix. 33 // 34 // The componentNameCreator is a func for creating the name of a component from the base name of 35 // the module, e.g. it could just append ".component" to the name passed in. 36 // 37 // This is intended to be called by prebuilt modules that create component models. It is because 38 // prebuilt module base names come in a variety of different forms: 39 // * unversioned - this is the same as the source module. 40 // * internal to an sdk - this is the unversioned name prefixed by the base name of the sdk 41 // module. 42 // * versioned - this is the same as the internal with the addition of an "@<version>" suffix. 43 // 44 // While this can be called from a source module in that case it will behave the same way as the 45 // unversioned name and return the result of calling the componentNameCreator func on the supplied 46 // base name. 47 // 48 // e.g. Assuming the componentNameCreator func simply appends ".component" to the name passed in 49 // then this will work as follows: 50 // * An unversioned name of "foo" will return "foo.component". 51 // * An internal to the sdk name of "sdk_foo" will return "sdk_foo.component". 52 // * A versioned name of "sdk_foo@current" will return "sdk_foo.component@current". 53 // 54 // Note that in the latter case the ".component" suffix is added before the version. Adding it 55 // after would change the version. 56 SdkMemberComponentName(baseName string, componentNameCreator func(string) string) string 57 58 sdkBase() *SdkBase 59 MakeMemberOf(sdk SdkRef) 60 IsInAnySdk() bool 61 62 // IsVersioned determines whether the module is versioned, i.e. has a name of the form 63 // <name>@<version> 64 IsVersioned() bool 65 66 ContainingSdk() SdkRef 67 MemberName() string 68} 69 70// SdkAware is the interface that must be supported by any module to become a member of SDK or to be 71// built with SDK 72type SdkAware interface { 73 Module 74 sdkAwareWithoutModule 75} 76 77// SdkRef refers to a version of an SDK 78type SdkRef struct { 79 Name string 80 Version string 81} 82 83// Unversioned determines if the SdkRef is referencing to the unversioned SDK module 84func (s SdkRef) Unversioned() bool { 85 return s.Version == "" 86} 87 88// String returns string representation of this SdkRef for debugging purpose 89func (s SdkRef) String() string { 90 if s.Name == "" { 91 return "(No Sdk)" 92 } 93 if s.Unversioned() { 94 return s.Name 95 } 96 return s.Name + string(SdkVersionSeparator) + s.Version 97} 98 99// SdkVersionSeparator is a character used to separate an sdk name and its version 100const SdkVersionSeparator = '@' 101 102// ParseSdkRef parses a `name@version` style string into a corresponding SdkRef struct 103func ParseSdkRef(ctx BaseModuleContext, str string, property string) SdkRef { 104 tokens := strings.Split(str, string(SdkVersionSeparator)) 105 if len(tokens) < 1 || len(tokens) > 2 { 106 ctx.PropertyErrorf(property, "%q does not follow name@version syntax", str) 107 return SdkRef{Name: "invalid sdk name", Version: "invalid sdk version"} 108 } 109 110 name := tokens[0] 111 112 var version string 113 if len(tokens) == 2 { 114 version = tokens[1] 115 } 116 117 return SdkRef{Name: name, Version: version} 118} 119 120type SdkRefs []SdkRef 121 122// Contains tells if the given SdkRef is in this list of SdkRef's 123func (refs SdkRefs) Contains(s SdkRef) bool { 124 for _, r := range refs { 125 if r == s { 126 return true 127 } 128 } 129 return false 130} 131 132type sdkProperties struct { 133 // The SDK that this module is a member of. nil if it is not a member of any SDK 134 ContainingSdk *SdkRef `blueprint:"mutated"` 135 136 // Name of the module that this sdk member is representing 137 Sdk_member_name *string 138} 139 140// SdkBase is a struct that is expected to be included in module types to implement the SdkAware 141// interface. InitSdkAwareModule should be called to initialize this struct. 142type SdkBase struct { 143 properties sdkProperties 144 module SdkAware 145} 146 147func (s *SdkBase) sdkBase() *SdkBase { 148 return s 149} 150 151func (s *SdkBase) SdkMemberComponentName(baseName string, componentNameCreator func(string) string) string { 152 if s.MemberName() == "" { 153 return componentNameCreator(baseName) 154 } else { 155 index := strings.LastIndex(baseName, "@") 156 unversionedName := baseName[:index] 157 unversionedComponentName := componentNameCreator(unversionedName) 158 versionSuffix := baseName[index:] 159 return unversionedComponentName + versionSuffix 160 } 161} 162 163// MakeMemberOf sets this module to be a member of a specific SDK 164func (s *SdkBase) MakeMemberOf(sdk SdkRef) { 165 s.properties.ContainingSdk = &sdk 166} 167 168// IsInAnySdk returns true if this module is a member of any SDK 169func (s *SdkBase) IsInAnySdk() bool { 170 return s.properties.ContainingSdk != nil 171} 172 173// IsVersioned returns true if this module is versioned. 174func (s *SdkBase) IsVersioned() bool { 175 return strings.Contains(s.module.Name(), "@") 176} 177 178// ContainingSdk returns the SDK that this module is a member of 179func (s *SdkBase) ContainingSdk() SdkRef { 180 if s.properties.ContainingSdk != nil { 181 return *s.properties.ContainingSdk 182 } 183 return SdkRef{Name: "", Version: ""} 184} 185 186// MemberName returns the name of the module that this SDK member is overriding 187func (s *SdkBase) MemberName() string { 188 return proptools.String(s.properties.Sdk_member_name) 189} 190 191// InitSdkAwareModule initializes the SdkBase struct. This must be called by all modules including 192// SdkBase. 193func InitSdkAwareModule(m SdkAware) { 194 base := m.sdkBase() 195 base.module = m 196 m.AddProperties(&base.properties) 197} 198 199// IsModuleInVersionedSdk returns true if the module is an versioned sdk. 200func IsModuleInVersionedSdk(module Module) bool { 201 if s, ok := module.(SdkAware); ok { 202 if !s.ContainingSdk().Unversioned() { 203 return true 204 } 205 } 206 return false 207} 208 209// SnapshotBuilder provides support for generating the build rules which will build the snapshot. 210type SnapshotBuilder interface { 211 // CopyToSnapshot generates a rule that will copy the src to the dest (which is a snapshot 212 // relative path) and add the dest to the zip. 213 CopyToSnapshot(src Path, dest string) 214 215 // EmptyFile returns the path to an empty file. 216 // 217 // This can be used by sdk member types that need to create an empty file in the snapshot, simply 218 // pass the value returned from this to the CopyToSnapshot() method. 219 EmptyFile() Path 220 221 // UnzipToSnapshot generates a rule that will unzip the supplied zip into the snapshot relative 222 // directory destDir. 223 UnzipToSnapshot(zipPath Path, destDir string) 224 225 // AddPrebuiltModule adds a new prebuilt module to the snapshot. 226 // 227 // It is intended to be called from SdkMemberType.AddPrebuiltModule which can add module type 228 // specific properties that are not variant specific. The following properties will be 229 // automatically populated before returning. 230 // 231 // * name 232 // * sdk_member_name 233 // * prefer 234 // 235 // Properties that are variant specific will be handled by SdkMemberProperties structure. 236 // 237 // Each module created by this method can be output to the generated Android.bp file in two 238 // different forms, depending on the setting of the SOONG_SDK_SNAPSHOT_VERSION build property. 239 // The two forms are: 240 // 1. A versioned Soong module that is referenced from a corresponding similarly versioned 241 // snapshot module. 242 // 2. An unversioned Soong module that. 243 // 244 // See sdk/update.go for more information. 245 AddPrebuiltModule(member SdkMember, moduleType string) BpModule 246 247 // SdkMemberReferencePropertyTag returns a property tag to use when adding a property to a 248 // BpModule that contains references to other sdk members. 249 // 250 // Using this will ensure that the reference is correctly output for both versioned and 251 // unversioned prebuilts in the snapshot. 252 // 253 // "required: true" means that the property must only contain references to other members of the 254 // sdk. Passing a reference to a module that is not a member of the sdk will result in a build 255 // error. 256 // 257 // "required: false" means that the property can contain references to modules that are either 258 // members or not members of the sdk. If a reference is to a module that is a non member then the 259 // reference is left unchanged, i.e. it is not transformed as references to members are. 260 // 261 // The handling of the member names is dependent on whether it is an internal or exported member. 262 // An exported member is one whose name is specified in one of the member type specific 263 // properties. An internal member is one that is added due to being a part of an exported (or 264 // other internal) member and is not itself an exported member. 265 // 266 // Member names are handled as follows: 267 // * When creating the unversioned form of the module the name is left unchecked unless the member 268 // is internal in which case it is transformed into an sdk specific name, i.e. by prefixing with 269 // the sdk name. 270 // 271 // * When creating the versioned form of the module the name is transformed into a versioned sdk 272 // specific name, i.e. by prefixing with the sdk name and suffixing with the version. 273 // 274 // e.g. 275 // bpPropertySet.AddPropertyWithTag("libs", []string{"member1", "member2"}, builder.SdkMemberReferencePropertyTag(true)) 276 SdkMemberReferencePropertyTag(required bool) BpPropertyTag 277} 278 279// BpPropertyTag is a marker interface that can be associated with properties in a BpPropertySet to 280// provide additional information which can be used to customize their behavior. 281type BpPropertyTag interface{} 282 283// BpPropertySet is a set of properties for use in a .bp file. 284type BpPropertySet interface { 285 // AddProperty adds a property. 286 // 287 // The value can be one of the following types: 288 // * string 289 // * array of the above 290 // * bool 291 // For these types it is an error if multiple properties with the same name 292 // are added. 293 // 294 // * pointer to a struct 295 // * BpPropertySet 296 // 297 // A pointer to a Blueprint-style property struct is first converted into a 298 // BpPropertySet by traversing the fields and adding their values as 299 // properties in a BpPropertySet. A field with a struct value is itself 300 // converted into a BpPropertySet before adding. 301 // 302 // Adding a BpPropertySet is done as follows: 303 // * If no property with the name exists then the BpPropertySet is added 304 // directly to this property. Care must be taken to ensure that it does not 305 // introduce a cycle. 306 // * If a property exists with the name and the current value is a 307 // BpPropertySet then every property of the new BpPropertySet is added to 308 // the existing BpPropertySet. 309 // * Otherwise, if a property exists with the name then it is an error. 310 AddProperty(name string, value interface{}) 311 312 // AddPropertyWithTag adds a property with an associated property tag. 313 AddPropertyWithTag(name string, value interface{}, tag BpPropertyTag) 314 315 // AddPropertySet adds a property set with the specified name and returns it so that additional 316 // properties can be added to it. 317 AddPropertySet(name string) BpPropertySet 318 319 // AddCommentForProperty adds a comment for the named property (or property set). 320 AddCommentForProperty(name, text string) 321} 322 323// BpModule represents a module definition in a .bp file. 324type BpModule interface { 325 BpPropertySet 326 327 // ModuleType returns the module type of the module 328 ModuleType() string 329 330 // Name returns the name of the module or "" if no name has been specified. 331 Name() string 332} 333 334// BpPrintable is a marker interface that must be implemented by any struct that is added as a 335// property value. 336type BpPrintable interface { 337 bpPrintable() 338} 339 340// BpPrintableBase must be embedded within any struct that is added as a 341// property value. 342type BpPrintableBase struct { 343} 344 345func (b BpPrintableBase) bpPrintable() { 346} 347 348var _ BpPrintable = BpPrintableBase{} 349 350// sdkRegisterable defines the interface that must be implemented by objects that can be registered 351// in an sdkRegistry. 352type sdkRegisterable interface { 353 // SdkPropertyName returns the name of the corresponding property on an sdk module. 354 SdkPropertyName() string 355} 356 357// sdkRegistry provides support for registering and retrieving objects that define properties for 358// use by sdk and module_exports module types. 359type sdkRegistry struct { 360 // The list of registered objects sorted by property name. 361 list []sdkRegisterable 362} 363 364// copyAndAppend creates a new sdkRegistry that includes all the traits registered in 365// this registry plus the supplied trait. 366func (r *sdkRegistry) copyAndAppend(registerable sdkRegisterable) *sdkRegistry { 367 oldList := r.list 368 369 // Make sure that list does not already contain the property. Uses a simple linear search instead 370 // of a binary search even though the list is sorted. That is because the number of items in the 371 // list is small and so not worth the overhead of a binary search. 372 found := false 373 newPropertyName := registerable.SdkPropertyName() 374 for _, r := range oldList { 375 if r.SdkPropertyName() == newPropertyName { 376 found = true 377 break 378 } 379 } 380 if found { 381 names := []string{} 382 for _, r := range oldList { 383 names = append(names, r.SdkPropertyName()) 384 } 385 panic(fmt.Errorf("duplicate properties found, %q already exists in %q", newPropertyName, names)) 386 } 387 388 // Copy the slice just in case this is being read while being modified, e.g. when testing. 389 list := make([]sdkRegisterable, 0, len(oldList)+1) 390 list = append(list, oldList...) 391 list = append(list, registerable) 392 393 // Sort the registered objects by their property name to ensure that registry order has no effect 394 // on behavior. 395 sort.Slice(list, func(i1, i2 int) bool { 396 t1 := list[i1] 397 t2 := list[i2] 398 399 return t1.SdkPropertyName() < t2.SdkPropertyName() 400 }) 401 402 // Create a new registry so the pointer uniquely identifies the set of registered types. 403 return &sdkRegistry{ 404 list: list, 405 } 406} 407 408// registeredObjects returns the list of registered instances. 409func (r *sdkRegistry) registeredObjects() []sdkRegisterable { 410 return r.list 411} 412 413// uniqueOnceKey returns a key that uniquely identifies this instance and can be used with 414// OncePer.Once 415func (r *sdkRegistry) uniqueOnceKey() OnceKey { 416 // Use the pointer to the registry as the unique key. The pointer is used because it is guaranteed 417 // to uniquely identify the contained list. The list itself cannot be used as slices are not 418 // comparable. Using the pointer does mean that two separate registries with identical lists would 419 // have different keys and so cause whatever information is cached to be created multiple times. 420 // However, that is not an issue in practice as it should not occur outside tests. Constructing a 421 // string representation of the list to use instead would avoid that but is an unnecessary 422 // complication that provides no significant benefit. 423 return NewCustomOnceKey(r) 424} 425 426// SdkMemberTrait represents a trait that members of an sdk module can contribute to the sdk 427// snapshot. 428// 429// A trait is simply a characteristic of sdk member that is not required by default which may be 430// required for some members but not others. Traits can cause additional information to be output 431// to the sdk snapshot or replace the default information exported for a member with something else. 432// e.g. 433// * By default cc libraries only export the default image variants to the SDK. However, for some 434// members it may be necessary to export specific image variants, e.g. vendor, or recovery. 435// * By default cc libraries export all the configured architecture variants except for the native 436// bridge architecture variants. However, for some members it may be necessary to export the 437// native bridge architecture variants as well. 438// * By default cc libraries export the platform variant (i.e. sdk:). However, for some members it 439// may be necessary to export the sdk variant (i.e. sdk:sdk). 440// 441// A sdk can request a module to provide no traits, one trait or a collection of traits. The exact 442// behavior of a trait is determined by how SdkMemberType implementations handle the traits. A trait 443// could be specific to one SdkMemberType or many. Some trait combinations could be incompatible. 444// 445// The sdk module type will create a special traits structure that contains a property for each 446// trait registered with RegisterSdkMemberTrait(). The property names are those returned from 447// SdkPropertyName(). Each property contains a list of modules that are required to have that trait. 448// e.g. something like this: 449// 450// sdk { 451// name: "sdk", 452// ... 453// traits: { 454// recovery_image: ["module1", "module4", "module5"], 455// native_bridge: ["module1", "module2"], 456// native_sdk: ["module1", "module3"], 457// ... 458// }, 459// ... 460// } 461type SdkMemberTrait interface { 462 // SdkPropertyName returns the name of the traits property on an sdk module. 463 SdkPropertyName() string 464} 465 466var _ sdkRegisterable = (SdkMemberTrait)(nil) 467 468// SdkMemberTraitBase is the base struct that must be embedded within any type that implements 469// SdkMemberTrait. 470type SdkMemberTraitBase struct { 471 // PropertyName is the name of the property 472 PropertyName string 473} 474 475func (b *SdkMemberTraitBase) SdkPropertyName() string { 476 return b.PropertyName 477} 478 479// SdkMemberTraitSet is a set of SdkMemberTrait instances. 480type SdkMemberTraitSet interface { 481 // Empty returns true if this set is empty. 482 Empty() bool 483 484 // Contains returns true if this set contains the specified trait. 485 Contains(trait SdkMemberTrait) bool 486 487 // Subtract returns a new set containing all elements of this set except for those in the 488 // other set. 489 Subtract(other SdkMemberTraitSet) SdkMemberTraitSet 490 491 // String returns a string representation of the set and its contents. 492 String() string 493} 494 495func NewSdkMemberTraitSet(traits []SdkMemberTrait) SdkMemberTraitSet { 496 if len(traits) == 0 { 497 return EmptySdkMemberTraitSet() 498 } 499 500 m := sdkMemberTraitSet{} 501 for _, trait := range traits { 502 m[trait] = true 503 } 504 return m 505} 506 507func EmptySdkMemberTraitSet() SdkMemberTraitSet { 508 return (sdkMemberTraitSet)(nil) 509} 510 511type sdkMemberTraitSet map[SdkMemberTrait]bool 512 513var _ SdkMemberTraitSet = (sdkMemberTraitSet{}) 514 515func (s sdkMemberTraitSet) Empty() bool { 516 return len(s) == 0 517} 518 519func (s sdkMemberTraitSet) Contains(trait SdkMemberTrait) bool { 520 return s[trait] 521} 522 523func (s sdkMemberTraitSet) Subtract(other SdkMemberTraitSet) SdkMemberTraitSet { 524 if other.Empty() { 525 return s 526 } 527 528 var remainder []SdkMemberTrait 529 for trait, _ := range s { 530 if !other.Contains(trait) { 531 remainder = append(remainder, trait) 532 } 533 } 534 535 return NewSdkMemberTraitSet(remainder) 536} 537 538func (s sdkMemberTraitSet) String() string { 539 list := []string{} 540 for trait, _ := range s { 541 list = append(list, trait.SdkPropertyName()) 542 } 543 sort.Strings(list) 544 return fmt.Sprintf("[%s]", strings.Join(list, ",")) 545} 546 547var registeredSdkMemberTraits = &sdkRegistry{} 548 549// RegisteredSdkMemberTraits returns a OnceKey and a sorted list of registered traits. 550// 551// The key uniquely identifies the array of traits and can be used with OncePer.Once() to cache 552// information derived from the array of traits. 553func RegisteredSdkMemberTraits() (OnceKey, []SdkMemberTrait) { 554 registerables := registeredSdkMemberTraits.registeredObjects() 555 traits := make([]SdkMemberTrait, len(registerables)) 556 for i, registerable := range registerables { 557 traits[i] = registerable.(SdkMemberTrait) 558 } 559 return registeredSdkMemberTraits.uniqueOnceKey(), traits 560} 561 562// RegisterSdkMemberTrait registers an SdkMemberTrait object to allow them to be used in the 563// module_exports, module_exports_snapshot, sdk and sdk_snapshot module types. 564func RegisterSdkMemberTrait(trait SdkMemberTrait) { 565 registeredSdkMemberTraits = registeredSdkMemberTraits.copyAndAppend(trait) 566} 567 568// SdkMember is an individual member of the SDK. 569// 570// It includes all of the variants that the SDK depends upon. 571type SdkMember interface { 572 // Name returns the name of the member. 573 Name() string 574 575 // Variants returns all the variants of this module depended upon by the SDK. 576 Variants() []SdkAware 577} 578 579// SdkMemberDependencyTag is the interface that a tag must implement in order to allow the 580// dependent module to be automatically added to the sdk. 581type SdkMemberDependencyTag interface { 582 blueprint.DependencyTag 583 584 // SdkMemberType returns the SdkMemberType that will be used to automatically add the child module 585 // to the sdk. 586 // 587 // Returning nil will prevent the module being added to the sdk. 588 SdkMemberType(child Module) SdkMemberType 589 590 // ExportMember determines whether a module added to the sdk through this tag will be exported 591 // from the sdk or not. 592 // 593 // An exported member is added to the sdk using its own name, e.g. if "foo" was exported from sdk 594 // "bar" then its prebuilt would be simply called "foo". A member can be added to the sdk via 595 // multiple tags and if any of those tags returns true from this method then the membe will be 596 // exported. Every module added directly to the sdk via one of the member type specific 597 // properties, e.g. java_libs, will automatically be exported. 598 // 599 // If a member is not exported then it is treated as an internal implementation detail of the 600 // sdk and so will be added with an sdk specific name. e.g. if "foo" was an internal member of sdk 601 // "bar" then its prebuilt would be called "bar_foo". Additionally its visibility will be set to 602 // "//visibility:private" so it will not be accessible from outside its Android.bp file. 603 ExportMember() bool 604} 605 606var _ SdkMemberDependencyTag = (*sdkMemberDependencyTag)(nil) 607var _ ReplaceSourceWithPrebuilt = (*sdkMemberDependencyTag)(nil) 608 609type sdkMemberDependencyTag struct { 610 blueprint.BaseDependencyTag 611 memberType SdkMemberType 612 export bool 613} 614 615func (t *sdkMemberDependencyTag) SdkMemberType(_ Module) SdkMemberType { 616 return t.memberType 617} 618 619func (t *sdkMemberDependencyTag) ExportMember() bool { 620 return t.export 621} 622 623// ReplaceSourceWithPrebuilt prevents dependencies from the sdk/module_exports onto their members 624// from being replaced with a preferred prebuilt. 625func (t *sdkMemberDependencyTag) ReplaceSourceWithPrebuilt() bool { 626 return false 627} 628 629// DependencyTagForSdkMemberType creates an SdkMemberDependencyTag that will cause any 630// dependencies added by the tag to be added to the sdk as the specified SdkMemberType and exported 631// (or not) as specified by the export parameter. 632func DependencyTagForSdkMemberType(memberType SdkMemberType, export bool) SdkMemberDependencyTag { 633 return &sdkMemberDependencyTag{memberType: memberType, export: export} 634} 635 636// SdkMemberType is the interface that must be implemented for every type that can be a member of an 637// sdk. 638// 639// The basic implementation should look something like this, where ModuleType is 640// the name of the module type being supported. 641// 642// type moduleTypeSdkMemberType struct { 643// android.SdkMemberTypeBase 644// } 645// 646// func init() { 647// android.RegisterSdkMemberType(&moduleTypeSdkMemberType{ 648// SdkMemberTypeBase: android.SdkMemberTypeBase{ 649// PropertyName: "module_types", 650// }, 651// } 652// } 653// 654// ...methods... 655// 656type SdkMemberType interface { 657 // SdkPropertyName returns the name of the member type property on an sdk module. 658 SdkPropertyName() string 659 660 // RequiresBpProperty returns true if this member type requires its property to be usable within 661 // an Android.bp file. 662 RequiresBpProperty() bool 663 664 // SupportedBuildReleases returns the string representation of a set of target build releases that 665 // support this member type. 666 SupportedBuildReleases() string 667 668 // UsableWithSdkAndSdkSnapshot returns true if the member type supports the sdk/sdk_snapshot, 669 // false otherwise. 670 UsableWithSdkAndSdkSnapshot() bool 671 672 // IsHostOsDependent returns true if prebuilt host artifacts may be specific to the host OS. Only 673 // applicable to modules where HostSupported() is true. If this is true, snapshots will list each 674 // host OS variant explicitly and disable all other host OS'es. 675 IsHostOsDependent() bool 676 677 // AddDependencies adds dependencies from the SDK module to all the module variants the member 678 // type contributes to the SDK. `names` is the list of module names given in the member type 679 // property (as returned by SdkPropertyName()) in the SDK module. The exact set of variants 680 // required is determined by the SDK and its properties. The dependencies must be added with the 681 // supplied tag. 682 // 683 // The BottomUpMutatorContext provided is for the SDK module. 684 AddDependencies(ctx SdkDependencyContext, dependencyTag blueprint.DependencyTag, names []string) 685 686 // IsInstance returns true if the supplied module is an instance of this member type. 687 // 688 // This is used to check the type of each variant before added to the SdkMember. Returning false 689 // will cause an error to be logged explaining that the module is not allowed in whichever sdk 690 // property it was added. 691 IsInstance(module Module) bool 692 693 // UsesSourceModuleTypeInSnapshot returns true when the AddPrebuiltModule() method returns a 694 // source module type. 695 UsesSourceModuleTypeInSnapshot() bool 696 697 // AddPrebuiltModule is called to add a prebuilt module that the sdk will populate. 698 // 699 // The sdk module code generates the snapshot as follows: 700 // 701 // * A properties struct of type SdkMemberProperties is created for each variant and 702 // populated with information from the variant by calling PopulateFromVariant(SdkAware) 703 // on the struct. 704 // 705 // * An additional properties struct is created into which the common properties will be 706 // added. 707 // 708 // * The variant property structs are analysed to find exported (capitalized) fields which 709 // have common values. Those fields are cleared and the common value added to the common 710 // properties. 711 // 712 // A field annotated with a tag of `sdk:"keep"` will be treated as if it 713 // was not capitalized, i.e. not optimized for common values. 714 // 715 // A field annotated with a tag of `android:"arch_variant"` will be allowed to have 716 // values that differ by arch, fields not tagged as such must have common values across 717 // all variants. 718 // 719 // * Additional field tags can be specified on a field that will ignore certain values 720 // for the purpose of common value optimization. A value that is ignored must have the 721 // default value for the property type. This is to ensure that significant value are not 722 // ignored by accident. The purpose of this is to allow the snapshot generation to reflect 723 // the behavior of the runtime. e.g. if a property is ignored on the host then a property 724 // that is common for android can be treated as if it was common for android and host as 725 // the setting for host is ignored anyway. 726 // * `sdk:"ignored-on-host" - this indicates the property is ignored on the host variant. 727 // 728 // * The sdk module type populates the BpModule structure, creating the arch specific 729 // structure and calls AddToPropertySet(...) on the properties struct to add the member 730 // specific properties in the correct place in the structure. 731 // 732 AddPrebuiltModule(ctx SdkMemberContext, member SdkMember) BpModule 733 734 // CreateVariantPropertiesStruct creates a structure into which variant specific properties can be 735 // added. 736 CreateVariantPropertiesStruct() SdkMemberProperties 737 738 // SupportedTraits returns the set of traits supported by this member type. 739 SupportedTraits() SdkMemberTraitSet 740} 741 742var _ sdkRegisterable = (SdkMemberType)(nil) 743 744// SdkDependencyContext provides access to information needed by the SdkMemberType.AddDependencies() 745// implementations. 746type SdkDependencyContext interface { 747 BottomUpMutatorContext 748 749 // RequiredTraits returns the set of SdkMemberTrait instances that the sdk requires the named 750 // member to provide. 751 RequiredTraits(name string) SdkMemberTraitSet 752 753 // RequiresTrait returns true if the sdk requires the member with the supplied name to provide the 754 // supplied trait. 755 RequiresTrait(name string, trait SdkMemberTrait) bool 756} 757 758// SdkMemberTypeBase is the base type for SdkMemberType implementations and must be embedded in any 759// struct that implements SdkMemberType. 760type SdkMemberTypeBase struct { 761 PropertyName string 762 763 // When set to true BpPropertyNotRequired indicates that the member type does not require the 764 // property to be specifiable in an Android.bp file. 765 BpPropertyNotRequired bool 766 767 // The name of the first targeted build release. 768 // 769 // If not specified then it is assumed to be available on all targeted build releases. 770 SupportedBuildReleaseSpecification string 771 772 SupportsSdk bool 773 HostOsDependent bool 774 775 // When set to true UseSourceModuleTypeInSnapshot indicates that the member type creates a source 776 // module type in its SdkMemberType.AddPrebuiltModule() method. That prevents the sdk snapshot 777 // code from automatically adding a prefer: true flag. 778 UseSourceModuleTypeInSnapshot bool 779 780 // The list of supported traits. 781 Traits []SdkMemberTrait 782} 783 784func (b *SdkMemberTypeBase) SdkPropertyName() string { 785 return b.PropertyName 786} 787 788func (b *SdkMemberTypeBase) RequiresBpProperty() bool { 789 return !b.BpPropertyNotRequired 790} 791 792func (b *SdkMemberTypeBase) SupportedBuildReleases() string { 793 return b.SupportedBuildReleaseSpecification 794} 795 796func (b *SdkMemberTypeBase) UsableWithSdkAndSdkSnapshot() bool { 797 return b.SupportsSdk 798} 799 800func (b *SdkMemberTypeBase) IsHostOsDependent() bool { 801 return b.HostOsDependent 802} 803 804func (b *SdkMemberTypeBase) UsesSourceModuleTypeInSnapshot() bool { 805 return b.UseSourceModuleTypeInSnapshot 806} 807 808func (b *SdkMemberTypeBase) SupportedTraits() SdkMemberTraitSet { 809 return NewSdkMemberTraitSet(b.Traits) 810} 811 812// registeredModuleExportsMemberTypes is the set of registered SdkMemberTypes for module_exports 813// modules. 814var registeredModuleExportsMemberTypes = &sdkRegistry{} 815 816// registeredSdkMemberTypes is the set of registered registeredSdkMemberTypes for sdk modules. 817var registeredSdkMemberTypes = &sdkRegistry{} 818 819// RegisteredSdkMemberTypes returns a OnceKey and a sorted list of registered types. 820// 821// If moduleExports is true then the slice of types includes all registered types that can be used 822// with the module_exports and module_exports_snapshot module types. Otherwise, the slice of types 823// only includes those registered types that can be used with the sdk and sdk_snapshot module 824// types. 825// 826// The key uniquely identifies the array of types and can be used with OncePer.Once() to cache 827// information derived from the array of types. 828func RegisteredSdkMemberTypes(moduleExports bool) (OnceKey, []SdkMemberType) { 829 var registry *sdkRegistry 830 if moduleExports { 831 registry = registeredModuleExportsMemberTypes 832 } else { 833 registry = registeredSdkMemberTypes 834 } 835 836 registerables := registry.registeredObjects() 837 types := make([]SdkMemberType, len(registerables)) 838 for i, registerable := range registerables { 839 types[i] = registerable.(SdkMemberType) 840 } 841 return registry.uniqueOnceKey(), types 842} 843 844// RegisterSdkMemberType registers an SdkMemberType object to allow them to be used in the 845// module_exports, module_exports_snapshot and (depending on the value returned from 846// SdkMemberType.UsableWithSdkAndSdkSnapshot) the sdk and sdk_snapshot module types. 847func RegisterSdkMemberType(memberType SdkMemberType) { 848 // All member types are usable with module_exports. 849 registeredModuleExportsMemberTypes = registeredModuleExportsMemberTypes.copyAndAppend(memberType) 850 851 // Only those that explicitly indicate it are usable with sdk. 852 if memberType.UsableWithSdkAndSdkSnapshot() { 853 registeredSdkMemberTypes = registeredSdkMemberTypes.copyAndAppend(memberType) 854 } 855} 856 857// SdkMemberPropertiesBase is the base structure for all implementations of SdkMemberProperties and 858// must be embedded in any struct that implements SdkMemberProperties. 859// 860// Contains common properties that apply across many different member types. 861type SdkMemberPropertiesBase struct { 862 // The number of unique os types supported by the member variants. 863 // 864 // If a member has a variant with more than one os type then it will need to differentiate 865 // the locations of any of their prebuilt files in the snapshot by os type to prevent them 866 // from colliding. See OsPrefix(). 867 // 868 // This property is the same for all variants of a member and so would be optimized away 869 // if it was not explicitly kept. 870 Os_count int `sdk:"keep"` 871 872 // The os type for which these properties refer. 873 // 874 // Provided to allow a member to differentiate between os types in the locations of their 875 // prebuilt files when it supports more than one os type. 876 // 877 // This property is the same for all os type specific variants of a member and so would be 878 // optimized away if it was not explicitly kept. 879 Os OsType `sdk:"keep"` 880 881 // The setting to use for the compile_multilib property. 882 Compile_multilib string `android:"arch_variant"` 883} 884 885// OsPrefix returns the os prefix to use for any file paths in the sdk. 886// 887// Is an empty string if the member only provides variants for a single os type, otherwise 888// is the OsType.Name. 889func (b *SdkMemberPropertiesBase) OsPrefix() string { 890 if b.Os_count == 1 { 891 return "" 892 } else { 893 return b.Os.Name 894 } 895} 896 897func (b *SdkMemberPropertiesBase) Base() *SdkMemberPropertiesBase { 898 return b 899} 900 901// SdkMemberProperties is the interface to be implemented on top of a structure that contains 902// variant specific information. 903// 904// Struct fields that are capitalized are examined for common values to extract. Fields that are not 905// capitalized are assumed to be arch specific. 906type SdkMemberProperties interface { 907 // Base returns the base structure. 908 Base() *SdkMemberPropertiesBase 909 910 // PopulateFromVariant populates this structure with information from a module variant. 911 // 912 // It will typically be called once for each variant of a member module that the SDK depends upon. 913 PopulateFromVariant(ctx SdkMemberContext, variant Module) 914 915 // AddToPropertySet adds the information from this structure to the property set. 916 // 917 // This will be called for each instance of this structure on which the PopulateFromVariant method 918 // was called and also on a number of different instances of this structure into which properties 919 // common to one or more variants have been copied. Therefore, implementations of this must handle 920 // the case when this structure is only partially populated. 921 AddToPropertySet(ctx SdkMemberContext, propertySet BpPropertySet) 922} 923 924// SdkMemberContext provides access to information common to a specific member. 925type SdkMemberContext interface { 926 927 // SdkModuleContext returns the module context of the sdk common os variant which is creating the 928 // snapshot. 929 // 930 // This is common to all members of the sdk and is not specific to the member being processed. 931 // If information about the member being processed needs to be obtained from this ModuleContext it 932 // must be obtained using one of the OtherModule... methods not the Module... methods. 933 SdkModuleContext() ModuleContext 934 935 // SnapshotBuilder the builder of the snapshot. 936 SnapshotBuilder() SnapshotBuilder 937 938 // MemberType returns the type of the member currently being processed. 939 MemberType() SdkMemberType 940 941 // Name returns the name of the member currently being processed. 942 // 943 // Provided for use by sdk members to create a member specific location within the snapshot 944 // into which to copy the prebuilt files. 945 Name() string 946 947 // RequiresTrait returns true if this member is expected to provide the specified trait. 948 RequiresTrait(trait SdkMemberTrait) bool 949 950 // IsTargetBuildBeforeTiramisu return true if the target build release for which this snapshot is 951 // being generated is before Tiramisu, i.e. S. 952 IsTargetBuildBeforeTiramisu() bool 953} 954 955// ExportedComponentsInfo contains information about the components that this module exports to an 956// sdk snapshot. 957// 958// A component of a module is a child module that the module creates and which forms an integral 959// part of the functionality that the creating module provides. A component module is essentially 960// owned by its creator and is tightly coupled to the creator and other components. 961// 962// e.g. the child modules created by prebuilt_apis are not components because they are not tightly 963// coupled to the prebuilt_apis module. Once they are created the prebuilt_apis ignores them. The 964// child impl and stub library created by java_sdk_library (and corresponding import) are components 965// because the creating module depends upon them in order to provide some of its own functionality. 966// 967// A component is exported if it is part of an sdk snapshot. e.g. The xml and impl child modules are 968// components but they are not exported as they are not part of an sdk snapshot. 969// 970// This information is used by the sdk snapshot generation code to ensure that it does not create 971// an sdk snapshot that contains a declaration of the component module and the module that creates 972// it as that would result in duplicate modules when attempting to use the snapshot. e.g. a snapshot 973// that included the java_sdk_library_import "foo" and also a java_import "foo.stubs" would fail 974// as there would be two modules called "foo.stubs". 975type ExportedComponentsInfo struct { 976 // The names of the exported components. 977 Components []string 978} 979 980var ExportedComponentsInfoProvider = blueprint.NewProvider(ExportedComponentsInfo{}) 981