Prevent ApexInfoMutator from creating unnecessary variants
Adds the AlwaysRequireApexVariantTag interface to enable ApexInfoMutator to differentiate between a tag that is excluded from apex contents but still requires an apex variant and a tag that is excluded from apex contents and does not require an apex variant. That is needed to support the sdkMemberVersionedDepTag which excludes the target from being added to the APEX but requires an APEX variant. A more detailed explanation is in the comments. The AlwaysRequireApexVariant() method follows the pattern used in ReplaceSourceWithPrebuilt of having a method that returns a bool to trigger the behavior and not say ExcludeFromApexContentsTag that simply relies on the tag implementing an interface to trigger. That is because the former is more flexible and allows a tag type to parameterize the behavior if necessary. The tags that this will exclude from creating an apex variant are: * PrebuiltDepTag - by the time the apex variant has been created any preferred prebuilts will have replaced the sources so there is no need to create an APEX variant if the only dependency path from the APEX to the prebuilt is via this tag. * hiddenApiAnnotationsDependencyTag - the target of which is a purely build time artifect and MUST NEVER end up in the APEX. It will also stop calling DepIsInSameApex for any dependency created by the sdkMemberVersionedDepTag. Which will fix the issue reported in the bug. Bug: 182992071 Test: m nothing Change-Id: I9569e488d6446ca45d3ea8f32a9b74524eb865df
This commit is contained in:
parent
21d1b9a52c
commit
573989d821
|
@ -257,6 +257,9 @@ type ApexProperties struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marker interface that identifies dependencies that are excluded from APEX contents.
|
// 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 {
|
type ExcludeFromApexContentsTag interface {
|
||||||
blueprint.DependencyTag
|
blueprint.DependencyTag
|
||||||
|
|
||||||
|
@ -264,6 +267,17 @@ type ExcludeFromApexContentsTag interface {
|
||||||
ExcludeFromApexContents()
|
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
|
// 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
|
// from the parent to the child. For example, stubs libraries are marked as DirectlyInAnyApex if
|
||||||
// their implementation is in an apex.
|
// their implementation is in an apex.
|
||||||
|
|
13
apex/apex.go
13
apex/apex.go
|
@ -846,6 +846,19 @@ func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) {
|
||||||
if !ok || !am.CanHaveApexVariants() {
|
if !ok || !am.CanHaveApexVariants() {
|
||||||
return false
|
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) {
|
if !parent.(android.DepIsInSameApex).DepIsInSameApex(mctx, child) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
21
sdk/sdk.go
21
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
|
// 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
|
// 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 {
|
type sdkMemberVersionedDepTag struct {
|
||||||
dependencyTag
|
dependencyTag
|
||||||
member string
|
member string
|
||||||
version string
|
version string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t sdkMemberVersionedDepTag) AlwaysRequireApexVariant() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Mark this tag so dependencies that use it are excluded from visibility enforcement.
|
// Mark this tag so dependencies that use it are excluded from visibility enforcement.
|
||||||
func (t sdkMemberVersionedDepTag) ExcludeFromVisibilityEnforcement() {}
|
func (t sdkMemberVersionedDepTag) ExcludeFromVisibilityEnforcement() {}
|
||||||
|
|
||||||
|
var _ android.AlwaysRequireApexVariantTag = sdkMemberVersionedDepTag{}
|
||||||
|
|
||||||
// Step 1: create dependencies from an SDK module to its members.
|
// Step 1: create dependencies from an SDK module to its members.
|
||||||
func memberMutator(mctx android.BottomUpMutatorContext) {
|
func memberMutator(mctx android.BottomUpMutatorContext) {
|
||||||
if s, ok := mctx.Module().(*sdk); ok {
|
if s, ok := mctx.Module().(*sdk); ok {
|
||||||
|
|
Loading…
Reference in New Issue