diff options
Diffstat (limited to 'sdk/update.go')
-rw-r--r-- | sdk/update.go | 133 |
1 files changed, 129 insertions, 4 deletions
diff --git a/sdk/update.go b/sdk/update.go index 8e4f9d4e2..b9ef3d0f4 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -433,6 +433,9 @@ be unnecessary as every module in the sdk already has its own licenses property. traits := s.gatherTraits() for _, member := range members { memberType := member.memberType + if !memberType.ArePrebuiltsRequired() { + continue + } name := member.name requiredTraits := traits[name] @@ -1319,6 +1322,119 @@ func (m multilibUsage) String() string { } } +// TODO(187910671): BEGIN - Remove once modules do not have an APEX and default variant. +// variantCoordinate contains the coordinates used to identify a variant of an SDK member. +type variantCoordinate struct { + // osType identifies the OS target of a variant. + osType android.OsType + // archId identifies the architecture and whether it is for the native bridge. + archId archId + // image is the image variant name. + image string + // linkType is the link type name. + linkType string +} + +func getVariantCoordinate(ctx *memberContext, variant android.Module) variantCoordinate { + linkType := "" + if len(ctx.MemberType().SupportedLinkages()) > 0 { + linkType = getLinkType(variant) + } + return variantCoordinate{ + osType: variant.Target().Os, + archId: archIdFromTarget(variant.Target()), + image: variant.ImageVariation().Variation, + linkType: linkType, + } +} + +// selectApexVariantsWhereAvailable filters the input list of variants by selecting the APEX +// specific variant for a specific variantCoordinate when there is both an APEX and default variant. +// +// There is a long-standing issue where a module that is added to an APEX has both an APEX and +// default/platform variant created even when the module does not require a platform variant. As a +// result an indirect dependency onto a module via the APEX will use the APEX variant, whereas a +// direct dependency onto the module will use the default/platform variant. That would result in a +// failure while attempting to optimize the properties for a member as it would have two variants +// when only one was expected. +// +// This function mitigates that problem by detecting when there are two variants that differ only +// by apex variant, where one is the default/platform variant and one is the APEX variant. In that +// case it picks the APEX variant. It picks the APEX variant because that is the behavior that would +// be expected +func selectApexVariantsWhereAvailable(ctx *memberContext, variants []android.SdkAware) []android.SdkAware { + moduleCtx := ctx.sdkMemberContext + + // Group the variants by coordinates. + variantsByCoord := make(map[variantCoordinate][]android.SdkAware) + for _, variant := range variants { + coord := getVariantCoordinate(ctx, variant) + variantsByCoord[coord] = append(variantsByCoord[coord], variant) + } + + toDiscard := make(map[android.SdkAware]struct{}) + for coord, list := range variantsByCoord { + count := len(list) + if count == 1 { + continue + } + + variantsByApex := make(map[string]android.SdkAware) + conflictDetected := false + for _, variant := range list { + apexInfo := moduleCtx.OtherModuleProvider(variant, android.ApexInfoProvider).(android.ApexInfo) + apexVariationName := apexInfo.ApexVariationName + // If there are two variants for a specific APEX variation then there is conflict. + if _, ok := variantsByApex[apexVariationName]; ok { + conflictDetected = true + break + } + variantsByApex[apexVariationName] = variant + } + + // If there are more than 2 apex variations or one of the apex variations is not the + // default/platform variation then there is a conflict. + if len(variantsByApex) != 2 { + conflictDetected = true + } else if _, ok := variantsByApex[""]; !ok { + conflictDetected = true + } + + // If there are no conflicts then add the default/platform variation to the list to remove. + if !conflictDetected { + toDiscard[variantsByApex[""]] = struct{}{} + continue + } + + // There are duplicate variants at this coordinate and they are not the default and APEX variant + // so fail. + variantDescriptions := []string{} + for _, m := range list { + variantDescriptions = append(variantDescriptions, fmt.Sprintf(" %s", m.String())) + } + + moduleCtx.ModuleErrorf("multiple conflicting variants detected for OsType{%s}, %s, Image{%s}, Link{%s}\n%s", + coord.osType, coord.archId.String(), coord.image, coord.linkType, + strings.Join(variantDescriptions, "\n")) + } + + // If there are any variants to discard then remove them from the list of variants, while + // preserving the order. + if len(toDiscard) > 0 { + filtered := []android.SdkAware{} + for _, variant := range variants { + if _, ok := toDiscard[variant]; !ok { + filtered = append(filtered, variant) + } + } + variants = filtered + } + + return variants +} + +// TODO(187910671): END - Remove once modules do not have an APEX and default variant. + type baseInfo struct { Properties android.SdkMemberProperties } @@ -1374,7 +1490,14 @@ func newOsTypeSpecificInfo(ctx android.SdkMemberContext, osType android.OsType, if commonVariants, ok := variantsByArchId[commonArchId]; ok { if len(osTypeVariants) != 1 { - panic(fmt.Errorf("Expected to only have 1 variant when arch type is common but found %d", len(osTypeVariants))) + variants := []string{} + for _, m := range osTypeVariants { + variants = append(variants, fmt.Sprintf(" %s", m.String())) + } + panic(fmt.Errorf("expected to only have 1 variant of %q when arch type is common but found %d\n%s", + ctx.Name(), + len(osTypeVariants), + strings.Join(variants, "\n"))) } // A common arch type only has one variant and its properties should be treated @@ -1854,7 +1977,8 @@ func (s *sdk) createMemberSnapshot(ctx *memberContext, member *sdkMember, bpModu memberType := member.memberType // Do not add the prefer property if the member snapshot module is a source module type. - config := ctx.sdkMemberContext.Config() + moduleCtx := ctx.sdkMemberContext + config := moduleCtx.Config() if !memberType.UsesSourceModuleTypeInSnapshot() { // Set the prefer based on the environment variable. This is a temporary work around to allow a // snapshot to be created that sets prefer: true. @@ -1879,9 +2003,10 @@ func (s *sdk) createMemberSnapshot(ctx *memberContext, member *sdkMember, bpModu } } + variants := selectApexVariantsWhereAvailable(ctx, member.variants) + // Group the variants by os type. variantsByOsType := make(map[android.OsType][]android.Module) - variants := member.Variants() for _, variant := range variants { osType := variant.Target().Os variantsByOsType[osType] = append(variantsByOsType[osType], variant) @@ -1927,7 +2052,7 @@ func (s *sdk) createMemberSnapshot(ctx *memberContext, member *sdkMember, bpModu } // Extract properties which are common across all architectures and os types. - extractCommonProperties(ctx.sdkMemberContext, commonValueExtractor, commonProperties, osSpecificPropertiesContainers) + extractCommonProperties(moduleCtx, commonValueExtractor, commonProperties, osSpecificPropertiesContainers) // Add the common properties to the module. addSdkMemberPropertiesToSet(ctx, commonProperties, bpModule) |