diff --git a/android/apex.go b/android/apex.go index 79d8cdda3..0d5cac812 100644 --- a/android/apex.go +++ b/android/apex.go @@ -257,6 +257,9 @@ type ApexProperties struct { } // Marker interface that identifies dependencies that are excluded from APEX contents. +// +// Unless the tag also implements the AlwaysRequireApexVariantTag this will prevent an apex variant +// from being created for the module. type ExcludeFromApexContentsTag interface { blueprint.DependencyTag @@ -264,6 +267,17 @@ type ExcludeFromApexContentsTag interface { ExcludeFromApexContents() } +// Marker interface that identifies dependencies that always requires an APEX variant to be created. +// +// It is possible for a dependency to require an apex variant but exclude the module from the APEX +// contents. See sdk.sdkMemberDependencyTag. +type AlwaysRequireApexVariantTag interface { + blueprint.DependencyTag + + // Return true if this tag requires that the target dependency has an apex variant. + AlwaysRequireApexVariant() bool +} + // Marker interface that identifies dependencies that should inherit the DirectlyInAnyApex state // from the parent to the child. For example, stubs libraries are marked as DirectlyInAnyApex if // their implementation is in an apex. diff --git a/apex/apex.go b/apex/apex.go index c0561ef8f..429465d80 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -846,6 +846,19 @@ func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) { if !ok || !am.CanHaveApexVariants() { return false } + depTag := mctx.OtherModuleDependencyTag(child) + + // Check to see if the tag always requires that the child module has an apex variant for every + // apex variant of the parent module. If it does not then it is still possible for something + // else, e.g. the DepIsInSameApex(...) method to decide that a variant is required. + if required, ok := depTag.(android.AlwaysRequireApexVariantTag); ok && required.AlwaysRequireApexVariant() { + return true + } + if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok { + // The tag defines a dependency that never requires the child module to be part of the same + // apex as the parent so it does not need an apex variant created. + return false + } if !parent.(android.DepIsInSameApex).DepIsInSameApex(mctx, child) { return false } diff --git a/sdk/sdk.go b/sdk/sdk.go index 2c84a2e88..6ca851217 100644 --- a/sdk/sdk.go +++ b/sdk/sdk.go @@ -358,15 +358,36 @@ var _ android.ExcludeFromApexContentsTag = dependencyTag{} // For dependencies from an in-development version of an SDK member to frozen versions of the same member // e.g. libfoo -> libfoo.mysdk.11 and libfoo.mysdk.12 +// +// The dependency represented by this tag requires that for every APEX variant created for the +// `from` module that an equivalent APEX variant is created for the 'to' module. This is because an +// APEX that requires a specific version of an sdk (via the `uses_sdks` property will replace +// dependencies on the unversioned sdk member with a dependency on the appropriate versioned sdk +// member. In order for that to work the versioned sdk member needs to have a variant for that APEX. +// As it is not known at the time that the APEX variants are created which specific APEX variants of +// a versioned sdk members will be required it is necessary for the versioned sdk members to have +// variants for any APEX that it could be used within. +// +// If the APEX selects a versioned sdk member then it will not have a dependency on the `from` +// module at all so any dependencies of that module will not affect the APEX. However, if the APEX +// selects the unversioned sdk member then it must exclude all the versioned sdk members. In no +// situation would this dependency cause the `to` module to be added to the APEX hence why this tag +// also excludes the `to` module from being added to the APEX contents. type sdkMemberVersionedDepTag struct { dependencyTag member string version string } +func (t sdkMemberVersionedDepTag) AlwaysRequireApexVariant() bool { + return true +} + // Mark this tag so dependencies that use it are excluded from visibility enforcement. func (t sdkMemberVersionedDepTag) ExcludeFromVisibilityEnforcement() {} +var _ android.AlwaysRequireApexVariantTag = sdkMemberVersionedDepTag{} + // Step 1: create dependencies from an SDK module to its members. func memberMutator(mctx android.BottomUpMutatorContext) { if s, ok := mctx.Module().(*sdk); ok {