diff options
Diffstat (limited to 'sdk/update.go')
-rw-r--r-- | sdk/update.go | 526 |
1 files changed, 295 insertions, 231 deletions
diff --git a/sdk/update.go b/sdk/update.go index c555ddc7a..e61ae0d0a 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -35,7 +35,7 @@ import ( // ======================================================== // // SOONG_SDK_SNAPSHOT_PREFER -// By default every module in the generated snapshot has prefer: false. Building it +// By default every unversioned module in the generated snapshot has prefer: false. Building it // with SOONG_SDK_SNAPSHOT_PREFER=true will force them to use prefer: true. // // SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR @@ -69,6 +69,20 @@ import ( // maintainable solution has been implemented. // TODO(b/174997203): Remove when no longer necessary. // +// SOONG_SDK_SNAPSHOT_VERSION +// This provides control over the version of the generated snapshot. +// +// SOONG_SDK_SNAPSHOT_VERSION=current will generate unversioned and versioned prebuilts and a +// versioned snapshot module. This is the default behavior. The zip file containing the +// generated snapshot will be <sdk-name>-current.zip. +// +// SOONG_SDK_SNAPSHOT_VERSION=unversioned will generate unversioned prebuilts only and the zip +// file containing the generated snapshot will be <sdk-name>.zip. +// +// SOONG_SDK_SNAPSHOT_VERSION=<number> will generate versioned prebuilts and a versioned +// snapshot module only. The zip file containing the generated snapshot will be +// <sdk-name>-<number>.zip. +// // SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE // This allows the target build release (i.e. the release version of the build within which // the snapshot will be used) of the snapshot to be specified. If unspecified then it defaults @@ -108,7 +122,7 @@ var ( mergeZips = pctx.AndroidStaticRule("SnapshotMergeZips", blueprint.RuleParams{ - Command: `${config.MergeZipsCmd} -s $out $in`, + Command: `${config.MergeZipsCmd} $out $in`, CommandDeps: []string{ "${config.MergeZipsCmd}", }, @@ -116,7 +130,8 @@ var ( ) const ( - soongSdkSnapshotVersionCurrent = "current" + soongSdkSnapshotVersionUnversioned = "unversioned" + soongSdkSnapshotVersionCurrent = "current" ) type generatedContents struct { @@ -148,13 +163,13 @@ func (gc *generatedContents) Dedent() { // IndentedPrintf will add spaces to indent the line to the appropriate level before printing the // arguments. func (gc *generatedContents) IndentedPrintf(format string, args ...interface{}) { - _, _ = fmt.Fprintf(&(gc.content), strings.Repeat(" ", gc.indentLevel)+format, args...) + fmt.Fprintf(&(gc.content), strings.Repeat(" ", gc.indentLevel)+format, args...) } // UnindentedPrintf does not add spaces to indent the line to the appropriate level before printing // the arguments. func (gc *generatedContents) UnindentedPrintf(format string, args ...interface{}) { - _, _ = fmt.Fprintf(&(gc.content), format, args...) + fmt.Fprintf(&(gc.content), format, args...) } func (gf *generatedFile) build(pctx android.PackageContext, ctx android.BuilderContext, implicits android.Paths) { @@ -239,7 +254,7 @@ func (s *sdk) collectMembers(ctx android.ModuleContext) { // Finally, the member type slices are concatenated together to form a single slice. The order in // which they are concatenated is the order in which the member types were registered in the // android.SdkMemberTypesRegistry. -func (s *sdk) groupMemberVariantsByMemberThenType(ctx android.ModuleContext, targetBuildRelease *buildRelease, memberVariantDeps []sdkMemberVariantDep) []*sdkMember { +func (s *sdk) groupMemberVariantsByMemberThenType(ctx android.ModuleContext, memberVariantDeps []sdkMemberVariantDep) []*sdkMember { byType := make(map[android.SdkMemberType][]*sdkMember) byName := make(map[string]*sdkMember) @@ -253,54 +268,22 @@ func (s *sdk) groupMemberVariantsByMemberThenType(ctx android.ModuleContext, tar member = &sdkMember{memberType: memberType, name: name} byName[name] = member byType[memberType] = append(byType[memberType], member) - } else if member.memberType != memberType { - // validate whether this is the same member type or and overriding member type - if memberType.Overrides(member.memberType) { - member.memberType = memberType - } else if !member.memberType.Overrides(memberType) { - ctx.ModuleErrorf("Incompatible member types %q %q", member.memberType, memberType) - } } // Only append new variants to the list. This is needed because a member can be both // exported by the sdk and also be a transitive sdk member. member.variants = appendUniqueVariants(member.variants, variant) } + var members []*sdkMember for _, memberListProperty := range s.memberTypeListProperties() { - memberType := memberListProperty.memberType - - if !isMemberTypeSupportedByTargetBuildRelease(memberType, targetBuildRelease) { - continue - } - - membersOfType := byType[memberType] + membersOfType := byType[memberListProperty.memberType] members = append(members, membersOfType...) } return members } -// isMemberTypeSupportedByTargetBuildRelease returns true if the member type is supported by the -// target build release. -func isMemberTypeSupportedByTargetBuildRelease(memberType android.SdkMemberType, targetBuildRelease *buildRelease) bool { - supportedByTargetBuildRelease := true - supportedBuildReleases := memberType.SupportedBuildReleases() - if supportedBuildReleases == "" { - supportedBuildReleases = "S+" - } - - set, err := parseBuildReleaseSet(supportedBuildReleases) - if err != nil { - panic(fmt.Errorf("member type %s has invalid supported build releases %q: %s", - memberType.SdkPropertyName(), supportedBuildReleases, err)) - } - if !set.contains(targetBuildRelease) { - supportedByTargetBuildRelease = false - } - return supportedByTargetBuildRelease -} - func appendUniqueVariants(variants []android.SdkAware, newVariant android.SdkAware) []android.SdkAware { for _, v := range variants { if v == newVariant { @@ -332,6 +315,12 @@ const BUILD_NUMBER_FILE = "snapshot-creation-build-number.txt" // <arch>/lib/ // libFoo.so : a stub library +// A name that uniquely identifies a prebuilt SDK member for a version of SDK snapshot +// This isn't visible to users, so could be changed in future. +func versionedSdkMemberName(ctx android.ModuleContext, memberName string, version string) string { + return ctx.ModuleName() + "_" + memberName + string(android.SdkVersionSeparator) + version +} + // buildSnapshot is the main function in this source file. It creates rules to copy // the contents (header files, stub libraries, etc) into the zip file. func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) { @@ -383,9 +372,20 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) { } config := ctx.Config() + version := config.GetenvWithDefault("SOONG_SDK_SNAPSHOT_VERSION", "current") + + // Generate versioned modules in the snapshot unless an unversioned snapshot has been requested. + generateVersioned := version != soongSdkSnapshotVersionUnversioned - // Always add -current to the end - snapshotFileSuffix := "-current" + // Generate unversioned modules in the snapshot unless a numbered snapshot has been requested. + // + // Unversioned modules are not required in that case because the numbered version will be a + // finalized version of the snapshot that is intended to be kept separate from the + generateUnversioned := version == soongSdkSnapshotVersionUnversioned || version == soongSdkSnapshotVersionCurrent + snapshotFileSuffix := "" + if generateVersioned { + snapshotFileSuffix = "-" + version + } currentBuildRelease := latestBuildRelease() targetBuildReleaseEnv := config.GetenvWithDefault("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE", currentBuildRelease.name) @@ -398,6 +398,7 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) { builder := &snapshotBuilder{ ctx: ctx, sdk: s, + version: version, snapshotDir: snapshotDir.OutputPath, copies: make(map[string]string), filesToZip: []android.Path{bp.path}, @@ -427,15 +428,12 @@ be unnecessary as every module in the sdk already has its own licenses property. // Group the variants for each member module together and then group the members of each member // type together. - members := s.groupMemberVariantsByMemberThenType(ctx, targetBuildRelease, memberVariantDeps) + members := s.groupMemberVariantsByMemberThenType(ctx, memberVariantDeps) // Create the prebuilt modules for each of the member modules. traits := s.gatherTraits() for _, member := range members { memberType := member.memberType - if !memberType.ArePrebuiltsRequired() { - continue - } name := member.name requiredTraits := traits[name] @@ -450,19 +448,38 @@ be unnecessary as every module in the sdk already has its own licenses property. s.createMemberSnapshot(memberCtx, member, prebuiltModule.(*bpModule)) } - // Create a transformer that will transform a module by replacing any references + // Create a transformer that will transform an unversioned module into a versioned module. + unversionedToVersionedTransformer := unversionedToVersionedTransformation{builder: builder} + + // Create a transformer that will transform an unversioned module by replacing any references // to internal members with a unique module name and setting prefer: false. - snapshotTransformer := snapshotTransformation{ + unversionedTransformer := unversionedTransformation{ builder: builder, } - for _, module := range builder.prebuiltOrder { + for _, unversioned := range builder.prebuiltOrder { // Prune any empty property sets. - module = module.transform(pruneEmptySetTransformer{}) + unversioned = unversioned.transform(pruneEmptySetTransformer{}) + + if generateVersioned { + // Copy the unversioned module so it can be modified to make it versioned. + versioned := unversioned.deepCopy() + + // Transform the unversioned module into a versioned one. + versioned.transform(unversionedToVersionedTransformer) + bpFile.AddModule(versioned) + } - // Transform the module module to make it suitable for use in the snapshot. - module.transform(snapshotTransformer) - bpFile.AddModule(module) + if generateUnversioned { + // Transform the unversioned module to make it suitable for use in the snapshot. + unversioned.transform(unversionedTransformer) + bpFile.AddModule(unversioned) + } + } + + if generateVersioned { + // Add the sdk/module_exports_snapshot module to the bp file. + s.addSnapshotModule(ctx, builder, sdkVariants, memberVariantDeps) } // generate Android.bp @@ -481,7 +498,7 @@ be unnecessary as every module in the sdk already has its own licenses property. // Copy the build number file into the snapshot. builder.CopyToSnapshot(ctx.Config().BuildNumberFile(ctx), BUILD_NUMBER_FILE) - filesToZip := android.SortedUniquePaths(builder.filesToZip) + filesToZip := builder.filesToZip // zip them all zipPath := fmt.Sprintf("%s%s.zip", ctx.ModuleName(), snapshotFileSuffix) @@ -517,7 +534,7 @@ be unnecessary as every module in the sdk already has its own licenses property. Description: outputDesc, Rule: mergeZips, Input: zipFile, - Inputs: android.SortedUniquePaths(builder.zipsToMerge), + Inputs: builder.zipsToMerge, Output: outputZipFile, }) } @@ -649,7 +666,7 @@ func (s *sdk) generateInfoData(ctx android.ModuleContext, memberVariantDeps []sd func filterOutComponents(ctx android.ModuleContext, deps []sdkMemberVariantDep) []sdkMemberVariantDep { // Collate the set of components that all the modules added to the sdk provide. components := map[string]*sdkMemberVariantDep{} - for i := range deps { + for i, _ := range deps { dep := &deps[i] for _, c := range dep.exportedComponentsInfo.Components { components[c] = dep @@ -684,6 +701,81 @@ func filterOutComponents(ctx android.ModuleContext, deps []sdkMemberVariantDep) return filtered } +// addSnapshotModule adds the sdk_snapshot/module_exports_snapshot module to the builder. +func (s *sdk) addSnapshotModule(ctx android.ModuleContext, builder *snapshotBuilder, sdkVariants []*sdk, memberVariantDeps []sdkMemberVariantDep) { + bpFile := builder.bpFile + + snapshotName := ctx.ModuleName() + string(android.SdkVersionSeparator) + builder.version + var snapshotModuleType string + if s.properties.Module_exports { + snapshotModuleType = "module_exports_snapshot" + } else { + snapshotModuleType = "sdk_snapshot" + } + snapshotModule := bpFile.newModule(snapshotModuleType) + snapshotModule.AddProperty("name", snapshotName) + + // Make sure that the snapshot has the same visibility as the sdk. + visibility := android.EffectiveVisibilityRules(ctx, s).Strings() + if len(visibility) != 0 { + snapshotModule.AddProperty("visibility", visibility) + } + + addHostDeviceSupportedProperties(s.ModuleBase.DeviceSupported(), s.ModuleBase.HostSupported(), snapshotModule) + + combinedPropertiesList := s.collateSnapshotModuleInfo(ctx, sdkVariants, memberVariantDeps) + commonCombinedProperties := s.optimizeSnapshotModuleProperties(ctx, combinedPropertiesList) + + s.addSnapshotPropertiesToPropertySet(builder, snapshotModule, commonCombinedProperties) + + targetPropertySet := snapshotModule.AddPropertySet("target") + + // Create a mapping from osType to combined properties. + osTypeToCombinedProperties := map[android.OsType]*combinedSnapshotModuleProperties{} + for _, combined := range combinedPropertiesList { + osTypeToCombinedProperties[combined.sdkVariant.Os()] = combined + } + + // Iterate over the os types in a fixed order. + for _, osType := range s.getPossibleOsTypes() { + if combined, ok := osTypeToCombinedProperties[osType]; ok { + osPropertySet := targetPropertySet.AddPropertySet(osType.Name) + + s.addSnapshotPropertiesToPropertySet(builder, osPropertySet, combined) + } + } + + // If host is supported and any member is host OS dependent then disable host + // by default, so that we can enable each host OS variant explicitly. This + // avoids problems with implicitly enabled OS variants when the snapshot is + // used, which might be different from this run (e.g. different build OS). + if s.HostSupported() { + var supportedHostTargets []string + for _, memberVariantDep := range memberVariantDeps { + if memberVariantDep.memberType.IsHostOsDependent() && memberVariantDep.variant.Target().Os.Class == android.Host { + targetString := memberVariantDep.variant.Target().Os.String() + "_" + memberVariantDep.variant.Target().Arch.ArchType.String() + if !android.InList(targetString, supportedHostTargets) { + supportedHostTargets = append(supportedHostTargets, targetString) + } + } + } + if len(supportedHostTargets) > 0 { + hostPropertySet := targetPropertySet.AddPropertySet("host") + hostPropertySet.AddProperty("enabled", false) + } + // Enable the <os>_<arch> variant explicitly when we've disabled it by default on host. + for _, hostTarget := range supportedHostTargets { + propertySet := targetPropertySet.AddPropertySet(hostTarget) + propertySet.AddProperty("enabled", true) + } + } + + // Prune any empty property sets. + snapshotModule.transform(pruneEmptySetTransformer{}) + + bpFile.AddModule(snapshotModule) +} + // Check the syntax of the generated Android.bp file contents and if they are // invalid then log an error with the contents (tagged with line numbers) and the // errors that were found so that it is easy to see where the problem lies. @@ -820,34 +912,92 @@ func (s *sdk) optimizeSnapshotModuleProperties(ctx android.ModuleContext, list [ } } +func (s *sdk) addSnapshotPropertiesToPropertySet(builder *snapshotBuilder, propertySet android.BpPropertySet, combined *combinedSnapshotModuleProperties) { + staticProperties := combined.staticProperties + multilib := staticProperties.Compile_multilib + if multilib != "" && multilib != "both" { + // Compile_multilib defaults to both so only needs to be set when it's specified and not both. + propertySet.AddProperty("compile_multilib", multilib) + } + + dynamicMemberTypeListProperties := combined.dynamicProperties + for _, memberListProperty := range s.memberTypeListProperties() { + if memberListProperty.getter == nil { + continue + } + names := memberListProperty.getter(dynamicMemberTypeListProperties) + if len(names) > 0 { + propertySet.AddProperty(memberListProperty.propertyName(), builder.versionedSdkMemberNames(names, false)) + } + } +} + type propertyTag struct { name string } var _ android.BpPropertyTag = propertyTag{} -// BpPropertyTag instances to add to a property that contains references to other sdk members. +// A BpPropertyTag to add to a property that contains references to other sdk members. // -// These will ensure that the referenced modules are available, if required. +// This will cause the references to be rewritten to a versioned reference in the version +// specific instance of a snapshot module. var requiredSdkMemberReferencePropertyTag = propertyTag{"requiredSdkMemberReferencePropertyTag"} var optionalSdkMemberReferencePropertyTag = propertyTag{"optionalSdkMemberReferencePropertyTag"} -type snapshotTransformation struct { +// A BpPropertyTag that indicates the property should only be present in the versioned +// module. +// +// This will cause the property to be removed from the unversioned instance of a +// snapshot module. +var sdkVersionedOnlyPropertyTag = propertyTag{"sdkVersionedOnlyPropertyTag"} + +type unversionedToVersionedTransformation struct { identityTransformation builder *snapshotBuilder } -func (t snapshotTransformation) transformModule(module *bpModule) *bpModule { +func (t unversionedToVersionedTransformation) transformModule(module *bpModule) *bpModule { + // Use a versioned name for the module but remember the original name for the + // snapshot. + name := module.Name() + module.setProperty("name", t.builder.versionedSdkMemberName(name, true)) + module.insertAfter("name", "sdk_member_name", name) + // Remove the prefer property if present as versioned modules never need marking with prefer. + module.removeProperty("prefer") + // Ditto for use_source_config_var + module.removeProperty("use_source_config_var") + return module +} + +func (t unversionedToVersionedTransformation) transformProperty(name string, value interface{}, tag android.BpPropertyTag) (interface{}, android.BpPropertyTag) { + if tag == requiredSdkMemberReferencePropertyTag || tag == optionalSdkMemberReferencePropertyTag { + required := tag == requiredSdkMemberReferencePropertyTag + return t.builder.versionedSdkMemberNames(value.([]string), required), tag + } else { + return value, tag + } +} + +type unversionedTransformation struct { + identityTransformation + builder *snapshotBuilder +} + +func (t unversionedTransformation) transformModule(module *bpModule) *bpModule { // If the module is an internal member then use a unique name for it. name := module.Name() - module.setProperty("name", t.builder.snapshotSdkMemberName(name, true)) + module.setProperty("name", t.builder.unversionedSdkMemberName(name, true)) return module } -func (t snapshotTransformation) transformProperty(_ string, value interface{}, tag android.BpPropertyTag) (interface{}, android.BpPropertyTag) { +func (t unversionedTransformation) transformProperty(name string, value interface{}, tag android.BpPropertyTag) (interface{}, android.BpPropertyTag) { if tag == requiredSdkMemberReferencePropertyTag || tag == optionalSdkMemberReferencePropertyTag { required := tag == requiredSdkMemberReferencePropertyTag - return t.builder.snapshotSdkMemberNames(value.([]string), required), tag + return t.builder.unversionedSdkMemberNames(value.([]string), required), tag + } else if tag == sdkVersionedOnlyPropertyTag { + // The property is not allowed in the unversioned module so remove it. + return nil, nil } else { return value, tag } @@ -859,7 +1009,7 @@ type pruneEmptySetTransformer struct { var _ bpTransformer = (*pruneEmptySetTransformer)(nil) -func (t pruneEmptySetTransformer) transformPropertySetAfterContents(_ string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) { +func (t pruneEmptySetTransformer) transformPropertySetAfterContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) { if len(propertySet.properties) == 0 { return nil, nil } else { @@ -868,12 +1018,20 @@ func (t pruneEmptySetTransformer) transformPropertySetAfterContents(_ string, pr } func generateBpContents(contents *generatedContents, bpFile *bpFile) { + generateFilteredBpContents(contents, bpFile, func(*bpModule) bool { + return true + }) +} + +func generateFilteredBpContents(contents *generatedContents, bpFile *bpFile, moduleFilter func(module *bpModule) bool) { contents.IndentedPrintf("// This is auto-generated. DO NOT EDIT.\n") for _, bpModule := range bpFile.order { - contents.IndentedPrintf("\n") - contents.IndentedPrintf("%s {\n", bpModule.moduleType) - outputPropertySet(contents, bpModule.bpPropertySet) - contents.IndentedPrintf("}\n") + if moduleFilter(bpModule) { + contents.IndentedPrintf("\n") + contents.IndentedPrintf("%s {\n", bpModule.moduleType) + outputPropertySet(contents, bpModule.bpPropertySet) + contents.IndentedPrintf("}\n") + } } } @@ -1009,10 +1167,36 @@ func (s *sdk) GetInfoContentsForTests() string { return s.builderForTests.infoContents } +func (s *sdk) GetUnversionedAndroidBpContentsForTests() string { + contents := &generatedContents{} + generateFilteredBpContents(contents, s.builderForTests.bpFile, func(module *bpModule) bool { + name := module.Name() + // Include modules that are either unversioned or have no name. + return !strings.Contains(name, "@") + }) + return contents.content.String() +} + +func (s *sdk) GetVersionedAndroidBpContentsForTests() string { + contents := &generatedContents{} + generateFilteredBpContents(contents, s.builderForTests.bpFile, func(module *bpModule) bool { + name := module.Name() + // Include modules that are either versioned or have no name. + return name == "" || strings.Contains(name, "@") + }) + return contents.content.String() +} + type snapshotBuilder struct { ctx android.ModuleContext sdk *sdk + // The version of the generated snapshot. + // + // See the documentation of SOONG_SDK_SNAPSHOT_VERSION above for details of the valid values of + // this field. + version string + snapshotDir android.OutputPath bpFile *bpFile @@ -1166,6 +1350,13 @@ func (s *snapshotBuilder) AddPrebuiltModule(member android.SdkMember, moduleType addHostDeviceSupportedProperties(deviceSupported, hostSupported, m) + // Disable installation in the versioned module of those modules that are ever installable. + if installable, ok := variant.(interface{ EverInstallable() bool }); ok { + if installable.EverInstallable() { + m.AddPropertyWithTag("installable", false, sdkVersionedOnlyPropertyTag) + } + } + s.prebuiltModules[name] = m s.prebuiltOrder = append(s.prebuiltOrder, m) return m @@ -1198,28 +1389,45 @@ func (s *snapshotBuilder) OptionalSdkMemberReferencePropertyTag() android.BpProp return optionalSdkMemberReferencePropertyTag } -// Get a name for sdk snapshot member. If the member is private then generate a snapshot specific -// name. As part of the processing this checks to make sure that any required members are part of -// the snapshot. -func (s *snapshotBuilder) snapshotSdkMemberName(name string, required bool) string { - if _, ok := s.allMembersByName[name]; !ok { +// Get a versioned name appropriate for the SDK snapshot version being taken. +func (s *snapshotBuilder) versionedSdkMemberName(unversionedName string, required bool) string { + if _, ok := s.allMembersByName[unversionedName]; !ok { if required { - s.ctx.ModuleErrorf("Required member reference %s is not a member of the sdk", name) + s.ctx.ModuleErrorf("Required member reference %s is not a member of the sdk", unversionedName) } - return name + return unversionedName } + return versionedSdkMemberName(s.ctx, unversionedName, s.version) +} - if s.isInternalMember(name) { - return s.ctx.ModuleName() + "_" + name +func (s *snapshotBuilder) versionedSdkMemberNames(members []string, required bool) []string { + var references []string = nil + for _, m := range members { + references = append(references, s.versionedSdkMemberName(m, required)) + } + return references +} + +// Get an internal name unique to the sdk. +func (s *snapshotBuilder) unversionedSdkMemberName(unversionedName string, required bool) string { + if _, ok := s.allMembersByName[unversionedName]; !ok { + if required { + s.ctx.ModuleErrorf("Required member reference %s is not a member of the sdk", unversionedName) + } + return unversionedName + } + + if s.isInternalMember(unversionedName) { + return s.ctx.ModuleName() + "_" + unversionedName } else { - return name + return unversionedName } } -func (s *snapshotBuilder) snapshotSdkMemberNames(members []string, required bool) []string { +func (s *snapshotBuilder) unversionedSdkMemberNames(members []string, required bool) []string { var references []string = nil for _, m := range members { - references = append(references, s.snapshotSdkMemberName(m, required)) + references = append(references, s.unversionedSdkMemberName(m, required)) } return references } @@ -1322,119 +1530,6 @@ 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 } @@ -1490,14 +1585,7 @@ func newOsTypeSpecificInfo(ctx android.SdkMemberContext, osType android.OsType, if commonVariants, ok := variantsByArchId[commonArchId]; ok { if len(osTypeVariants) != 1 { - 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"))) + panic(fmt.Errorf("Expected to only have 1 variant when arch type is common but found %d", len(osTypeVariants))) } // A common arch type only has one variant and its properties should be treated @@ -1695,9 +1783,7 @@ func newArchSpecificInfo(ctx android.SdkMemberContext, archId archId, osType and // added. archInfo.Properties = variantPropertiesFactory() - // if there are multiple supported link variants, we want to nest based on linkage even if there - // is only one variant, otherwise, if there is only one variant we can populate based on the arch - if len(archVariants) == 1 && len(ctx.MemberType().SupportedLinkages()) <= 1 { + if len(archVariants) == 1 { archInfo.Properties.PopulateFromVariant(ctx, archVariants[0]) } else { // Group the variants by image type. @@ -1824,13 +1910,11 @@ func newImageVariantSpecificInfo(ctx android.SdkMemberContext, imageVariant stri // Create the properties into which the image variant specific properties will be added. imageInfo.Properties = variantPropertiesFactory() - // if there are multiple supported link variants, we want to nest even if there is only one - // variant, otherwise, if there is only one variant we can populate based on the image - if len(imageVariants) == 1 && len(ctx.MemberType().SupportedLinkages()) <= 1 { + if len(imageVariants) == 1 { imageInfo.Properties.PopulateFromVariant(ctx, imageVariants[0]) } else { // There is more than one variant for this image variant which must be differentiated by link - // type. Or there are multiple supported linkages and we need to nest based on link type. + // type. for _, linkVariant := range imageVariants { linkType := getLinkType(linkVariant) if linkType == "" { @@ -1874,22 +1958,10 @@ func (imageInfo *imageVariantSpecificInfo) addToPropertySet(ctx *memberContext, addSdkMemberPropertiesToSet(ctx, imageInfo.Properties, propertySet) - usedLinkages := make(map[string]bool, len(imageInfo.linkInfos)) for _, linkInfo := range imageInfo.linkInfos { - usedLinkages[linkInfo.linkType] = true linkInfo.addToPropertySet(ctx, propertySet) } - // If not all supported linkages had existing variants, we need to disable the unsupported variant - if len(imageInfo.linkInfos) < len(ctx.MemberType().SupportedLinkages()) { - for _, l := range ctx.MemberType().SupportedLinkages() { - if _, ok := usedLinkages[l]; !ok { - otherLinkagePropertySet := propertySet.AddPropertySet(l) - otherLinkagePropertySet.AddProperty("enabled", false) - } - } - } - // If this is for a non-core image variant then make sure that the property set does not contain // any properties as providing non-core image variant specific properties for prebuilts is not // currently supported. @@ -1972,19 +2044,12 @@ func (m *memberContext) RequiresTrait(trait android.SdkMemberTrait) bool { return m.requiredTraits.Contains(trait) } -func (m *memberContext) IsTargetBuildBeforeTiramisu() bool { - return m.builder.targetBuildRelease.EarlierThan(buildReleaseT) -} - -var _ android.SdkMemberContext = (*memberContext)(nil) - func (s *sdk) createMemberSnapshot(ctx *memberContext, member *sdkMember, bpModule *bpModule) { memberType := member.memberType // Do not add the prefer property if the member snapshot module is a source module type. - moduleCtx := ctx.sdkMemberContext - config := moduleCtx.Config() + config := ctx.sdkMemberContext.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. @@ -2009,10 +2074,9 @@ 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) @@ -2058,7 +2122,7 @@ func (s *sdk) createMemberSnapshot(ctx *memberContext, member *sdkMember, bpModu } // Extract properties which are common across all architectures and os types. - extractCommonProperties(moduleCtx, commonValueExtractor, commonProperties, osSpecificPropertiesContainers) + extractCommonProperties(ctx.sdkMemberContext, commonValueExtractor, commonProperties, osSpecificPropertiesContainers) // Add the common properties to the module. addSdkMemberPropertiesToSet(ctx, commonProperties, bpModule) |