diff options
Diffstat (limited to 'android/sdk.go')
-rw-r--r-- | android/sdk.go | 231 |
1 files changed, 205 insertions, 26 deletions
diff --git a/android/sdk.go b/android/sdk.go index e823106e8..42c8ffa32 100644 --- a/android/sdk.go +++ b/android/sdk.go @@ -34,20 +34,60 @@ type RequiredSdks interface { RequiredSdks() SdkRefs } -// SdkAware is the interface that must be supported by any module to become a member of SDK or to be -// built with SDK -type SdkAware interface { - Module +// Provided to improve code navigation with the IDE. +type sdkAwareWithoutModule interface { RequiredSdks + // SdkMemberComponentName will return the name to use for a component of this module based on the + // base name of this module. + // + // The baseName is the name returned by ModuleBase.BaseModuleName(), i.e. the name specified in + // the name property in the .bp file so will not include the prebuilt_ prefix. + // + // The componentNameCreator is a func for creating the name of a component from the base name of + // the module, e.g. it could just append ".component" to the name passed in. + // + // This is intended to be called by prebuilt modules that create component models. It is because + // prebuilt module base names come in a variety of different forms: + // * unversioned - this is the same as the source module. + // * internal to an sdk - this is the unversioned name prefixed by the base name of the sdk + // module. + // * versioned - this is the same as the internal with the addition of an "@<version>" suffix. + // + // While this can be called from a source module in that case it will behave the same way as the + // unversioned name and return the result of calling the componentNameCreator func on the supplied + // base name. + // + // e.g. Assuming the componentNameCreator func simply appends ".component" to the name passed in + // then this will work as follows: + // * An unversioned name of "foo" will return "foo.component". + // * An internal to the sdk name of "sdk_foo" will return "sdk_foo.component". + // * A versioned name of "sdk_foo@current" will return "sdk_foo.component@current". + // + // Note that in the latter case the ".component" suffix is added before the version. Adding it + // after would change the version. + SdkMemberComponentName(baseName string, componentNameCreator func(string) string) string + sdkBase() *SdkBase MakeMemberOf(sdk SdkRef) IsInAnySdk() bool + + // IsVersioned determines whether the module is versioned, i.e. has a name of the form + // <name>@<version> + IsVersioned() bool + ContainingSdk() SdkRef MemberName() string BuildWithSdks(sdks SdkRefs) } +// SdkAware is the interface that must be supported by any module to become a member of SDK or to be +// built with SDK +type SdkAware interface { + Module + sdkAwareWithoutModule +} + // SdkRef refers to a version of an SDK type SdkRef struct { Name string @@ -77,7 +117,7 @@ const SdkVersionSeparator = '@' func ParseSdkRef(ctx BaseModuleContext, str string, property string) SdkRef { tokens := strings.Split(str, string(SdkVersionSeparator)) if len(tokens) < 1 || len(tokens) > 2 { - ctx.PropertyErrorf(property, "%q does not follow name#version syntax", str) + ctx.PropertyErrorf(property, "%q does not follow name@version syntax", str) return SdkRef{Name: "invalid sdk name", Version: "invalid sdk version"} } @@ -125,6 +165,18 @@ func (s *SdkBase) sdkBase() *SdkBase { return s } +func (s *SdkBase) SdkMemberComponentName(baseName string, componentNameCreator func(string) string) string { + if s.MemberName() == "" { + return componentNameCreator(baseName) + } else { + index := strings.LastIndex(baseName, "@") + unversionedName := baseName[:index] + unversionedComponentName := componentNameCreator(unversionedName) + versionSuffix := baseName[index:] + return unversionedComponentName + versionSuffix + } +} + // MakeMemberOf sets this module to be a member of a specific SDK func (s *SdkBase) MakeMemberOf(sdk SdkRef) { s.properties.ContainingSdk = &sdk @@ -135,6 +187,11 @@ func (s *SdkBase) IsInAnySdk() bool { return s.properties.ContainingSdk != nil } +// IsVersioned returns true if this module is versioned. +func (s *SdkBase) IsVersioned() bool { + return strings.Contains(s.module.Name(), "@") +} + // ContainingSdk returns the SDK that this module is a member of func (s *SdkBase) ContainingSdk() SdkRef { if s.properties.ContainingSdk != nil { @@ -166,6 +223,16 @@ func InitSdkAwareModule(m SdkAware) { m.AddProperties(&base.properties) } +// IsModuleInVersionedSdk returns true if the module is an versioned sdk. +func IsModuleInVersionedSdk(module Module) bool { + if s, ok := module.(SdkAware); ok { + if !s.ContainingSdk().Unversioned() { + return true + } + } + return false +} + // Provide support for generating the build rules which will build the snapshot. type SnapshotBuilder interface { // Copy src to the dest (which is a snapshot relative path) and add the dest @@ -232,9 +299,25 @@ type BpPropertySet interface { // * string // * array of the above // * bool + // For these types it is an error if multiple properties with the same name + // are added. + // + // * pointer to a struct // * BpPropertySet // - // It is an error if multiple properties with the same name are added. + // A pointer to a Blueprint-style property struct is first converted into a + // BpPropertySet by traversing the fields and adding their values as + // properties in a BpPropertySet. A field with a struct value is itself + // converted into a BpPropertySet before adding. + // + // Adding a BpPropertySet is done as follows: + // * If no property with the name exists then the BpPropertySet is added + // directly to this property. Care must be taken to ensure that it does not + // introduce a cycle. + // * If a property exists with the name and the current value is a + // BpPropertySet then every property of the new BpPropertySet is added to + // the existing BpPropertySet. + // * Otherwise, if a property exists with the name then it is an error. AddProperty(name string, value interface{}) // Add a property with an associated tag @@ -243,11 +326,20 @@ type BpPropertySet interface { // Add a property set with the specified name and return so that additional // properties can be added. AddPropertySet(name string) BpPropertySet + + // Add comment for property (or property set). + AddCommentForProperty(name, text string) } // A .bp module definition. type BpModule interface { BpPropertySet + + // ModuleType returns the module type of the module + ModuleType() string + + // Name returns the name of the module or "" if no name has been specified. + Name() string } // An individual member of the SDK, includes all of the variants that the SDK @@ -260,23 +352,61 @@ type SdkMember interface { Variants() []SdkAware } +// SdkMemberTypeDependencyTag is the interface that a tag must implement in order to allow the +// dependent module to be automatically added to the sdk. type SdkMemberTypeDependencyTag interface { blueprint.DependencyTag - SdkMemberType() SdkMemberType + // SdkMemberType returns the SdkMemberType that will be used to automatically add the child module + // to the sdk. + // + // Returning nil will prevent the module being added to the sdk. + SdkMemberType(child Module) SdkMemberType + + // ExportMember determines whether a module added to the sdk through this tag will be exported + // from the sdk or not. + // + // An exported member is added to the sdk using its own name, e.g. if "foo" was exported from sdk + // "bar" then its prebuilt would be simply called "foo". A member can be added to the sdk via + // multiple tags and if any of those tags returns true from this method then the membe will be + // exported. Every module added directly to the sdk via one of the member type specific + // properties, e.g. java_libs, will automatically be exported. + // + // If a member is not exported then it is treated as an internal implementation detail of the + // sdk and so will be added with an sdk specific name. e.g. if "foo" was an internal member of sdk + // "bar" then its prebuilt would be called "bar_foo". Additionally its visibility will be set to + // "//visibility:private" so it will not be accessible from outside its Android.bp file. + ExportMember() bool } +var _ SdkMemberTypeDependencyTag = (*sdkMemberDependencyTag)(nil) +var _ ReplaceSourceWithPrebuilt = (*sdkMemberDependencyTag)(nil) + type sdkMemberDependencyTag struct { blueprint.BaseDependencyTag memberType SdkMemberType + export bool } -func (t *sdkMemberDependencyTag) SdkMemberType() SdkMemberType { +func (t *sdkMemberDependencyTag) SdkMemberType(_ Module) SdkMemberType { return t.memberType } -func DependencyTagForSdkMemberType(memberType SdkMemberType) SdkMemberTypeDependencyTag { - return &sdkMemberDependencyTag{memberType: memberType} +func (t *sdkMemberDependencyTag) ExportMember() bool { + return t.export +} + +// Prevent dependencies from the sdk/module_exports onto their members from being +// replaced with a preferred prebuilt. +func (t *sdkMemberDependencyTag) ReplaceSourceWithPrebuilt() bool { + return false +} + +// DependencyTagForSdkMemberType creates an SdkMemberTypeDependencyTag that will cause any +// dependencies added by the tag to be added to the sdk as the specified SdkMemberType and exported +// (or not) as specified by the export parameter. +func DependencyTagForSdkMemberType(memberType SdkMemberType, export bool) SdkMemberTypeDependencyTag { + return &sdkMemberDependencyTag{memberType: memberType, export: export} } // Interface that must be implemented for every type that can be a member of an @@ -303,15 +433,18 @@ type SdkMemberType interface { // The name of the member type property on an sdk module. SdkPropertyName() string + // RequiresBpProperty returns true if this member type requires its property to be usable within + // an Android.bp file. + RequiresBpProperty() bool + // True if the member type supports the sdk/sdk_snapshot, false otherwise. UsableWithSdkAndSdkSnapshot() bool - // Return true if modules of this type can have dependencies which should be - // treated as if they are sdk members. - // - // Any dependency that is to be treated as a member of the sdk needs to implement - // SdkAware and be added with an SdkMemberTypeDependencyTag tag. - HasTransitiveSdkMembers() bool + // Return true if prebuilt host artifacts may be specific to the host OS. Only + // applicable to modules where HostSupported() is true. If this is true, + // snapshots will list each host OS variant explicitly and disable all other + // host OS'es. + IsHostOsDependent() bool // Add dependencies from the SDK module to all the module variants the member // type contributes to the SDK. `names` is the list of module names given in @@ -329,6 +462,10 @@ type SdkMemberType interface { // the module is not allowed in whichever sdk property it was added. IsInstance(module Module) bool + // UsesSourceModuleTypeInSnapshot returns true when the AddPrebuiltModule() method returns a + // source module type. + UsesSourceModuleTypeInSnapshot() bool + // Add a prebuilt module that the sdk will populate. // // The sdk module code generates the snapshot as follows: @@ -372,21 +509,39 @@ type SdkMemberType interface { // Base type for SdkMemberType implementations. type SdkMemberTypeBase struct { - PropertyName string - SupportsSdk bool - TransitiveSdkMembers bool + PropertyName string + + // When set to true BpPropertyNotRequired indicates that the member type does not require the + // property to be specifiable in an Android.bp file. + BpPropertyNotRequired bool + + SupportsSdk bool + HostOsDependent bool + + // When set to true UseSourceModuleTypeInSnapshot indicates that the member type creates a source + // module type in its SdkMemberType.AddPrebuiltModule() method. That prevents the sdk snapshot + // code from automatically adding a prefer: true flag. + UseSourceModuleTypeInSnapshot bool } func (b *SdkMemberTypeBase) SdkPropertyName() string { return b.PropertyName } +func (b *SdkMemberTypeBase) RequiresBpProperty() bool { + return !b.BpPropertyNotRequired +} + func (b *SdkMemberTypeBase) UsableWithSdkAndSdkSnapshot() bool { return b.SupportsSdk } -func (b *SdkMemberTypeBase) HasTransitiveSdkMembers() bool { - return b.TransitiveSdkMembers +func (b *SdkMemberTypeBase) IsHostOsDependent() bool { + return b.HostOsDependent +} + +func (b *SdkMemberTypeBase) UsesSourceModuleTypeInSnapshot() bool { + return b.UseSourceModuleTypeInSnapshot } // Encapsulates the information about registered SdkMemberTypes. @@ -457,8 +612,7 @@ func RegisterSdkMemberType(memberType SdkMemberType) { // Base structure for all implementations of SdkMemberProperties. // -// Contains common properties that apply across many different member types. These -// are not affected by the optimization to extract common values. +// Contains common properties that apply across many different member types. type SdkMemberPropertiesBase struct { // The number of unique os types supported by the member variants. // @@ -480,9 +634,7 @@ type SdkMemberPropertiesBase struct { Os OsType `sdk:"keep"` // The setting to use for the compile_multilib property. - // - // This property is set after optimization so there is no point in trying to optimize it. - Compile_multilib string `sdk:"keep"` + Compile_multilib string `android:"arch_variant"` } // The os prefix to use for any file paths in the sdk. @@ -535,3 +687,30 @@ type SdkMemberContext interface { // into which to copy the prebuilt files. Name() string } + +// ExportedComponentsInfo contains information about the components that this module exports to an +// sdk snapshot. +// +// A component of a module is a child module that the module creates and which forms an integral +// part of the functionality that the creating module provides. A component module is essentially +// owned by its creator and is tightly coupled to the creator and other components. +// +// e.g. the child modules created by prebuilt_apis are not components because they are not tightly +// coupled to the prebuilt_apis module. Once they are created the prebuilt_apis ignores them. The +// child impl and stub library created by java_sdk_library (and corresponding import) are components +// because the creating module depends upon them in order to provide some of its own functionality. +// +// A component is exported if it is part of an sdk snapshot. e.g. The xml and impl child modules are +// components but they are not exported as they are not part of an sdk snapshot. +// +// This information is used by the sdk snapshot generation code to ensure that it does not create +// an sdk snapshot that contains a declaration of the component module and the module that creates +// it as that would result in duplicate modules when attempting to use the snapshot. e.g. a snapshot +// that included the java_sdk_library_import "foo" and also a java_import "foo.stubs" would fail +// as there would be two modules called "foo.stubs". +type ExportedComponentsInfo struct { + // The names of the exported components. + Components []string +} + +var ExportedComponentsInfoProvider = blueprint.NewProvider(ExportedComponentsInfo{}) |