diff options
Diffstat (limited to 'sdk/update.go')
| -rw-r--r-- | sdk/update.go | 348 |
1 files changed, 168 insertions, 180 deletions
diff --git a/sdk/update.go b/sdk/update.go index d98ab683d..198c8d4a8 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -24,6 +24,7 @@ import ( "android/soong/apex" "android/soong/cc" + "android/soong/java" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -89,19 +90,6 @@ type generatedContents struct { indentLevel int } -// generatedFile abstracts operations for writing contents into a file and emit a build rule -// for the file. -type generatedFile struct { - generatedContents - path android.OutputPath -} - -func newGeneratedFile(ctx android.ModuleContext, path ...string) *generatedFile { - return &generatedFile{ - path: android.PathForModuleOut(ctx, path...).OutputPath, - } -} - func (gc *generatedContents) Indent() { gc.indentLevel++ } @@ -122,26 +110,6 @@ func (gc *generatedContents) UnindentedPrintf(format string, args ...interface{} _, _ = fmt.Fprintf(&(gc.content), format, args...) } -func (gf *generatedFile) build(pctx android.PackageContext, ctx android.BuilderContext, implicits android.Paths) { - rb := android.NewRuleBuilder(pctx, ctx) - - content := gf.content.String() - - // ninja consumes newline characters in rspfile_content. Prevent it by - // escaping the backslash in the newline character. The extra backslash - // is removed when the rspfile is written to the actual script file - content = strings.ReplaceAll(content, "\n", "\\n") - - rb.Command(). - Implicits(implicits). - Text("echo -n").Text(proptools.ShellEscape(content)). - // convert \\n to \n - Text("| sed 's/\\\\n/\\n/g' >").Output(gf.path) - rb.Command(). - Text("chmod a+x").Output(gf.path) - rb.Build(gf.path.Base(), "Build "+gf.path.Base()) -} - // Collect all the members. // // Updates the sdk module with a list of sdkMemberVariantDep instances and details as to which @@ -166,14 +134,11 @@ func (s *sdk) collectMembers(ctx android.ModuleContext) { // Keep track of which multilib variants are used by the sdk. s.multilibUsages = s.multilibUsages.addArchType(child.Target().Arch.ArchType) - var exportedComponentsInfo android.ExportedComponentsInfo - if ctx.OtherModuleHasProvider(child, android.ExportedComponentsInfoProvider) { - exportedComponentsInfo = ctx.OtherModuleProvider(child, android.ExportedComponentsInfoProvider).(android.ExportedComponentsInfo) - } + exportedComponentsInfo, _ := android.OtherModuleProvider(ctx, child, android.ExportedComponentsInfoProvider) var container android.Module if parent != ctx.Module() { - container = parent.(android.Module) + container = parent } minApiLevel := android.MinApiLevelForSdkSnapshot(ctx, child) @@ -182,7 +147,7 @@ func (s *sdk) collectMembers(ctx android.ModuleContext) { s.memberVariantDeps = append(s.memberVariantDeps, sdkMemberVariantDep{ sdkVariant: s, memberType: memberType, - variant: child.(android.Module), + variant: child, minApiLevel: minApiLevel, container: container, export: export, @@ -198,6 +163,20 @@ func (s *sdk) collectMembers(ctx android.ModuleContext) { }) } +// A denylist of modules whose host variants will be removed from the generated snapshots above the ApiLevel +// even if they are listed in the corresponding `sdk`. +// The key is the module name +// The value is the _last_ dessert where the host variant of the module will be present +// This is a workaround to ensure that these modules are generated in <=$ApiLevel, but not in in >=$ApiLevel +var ignoreHostModuleVariantsAboveDessert = map[string]android.ApiLevel{ + // ignore host variant of libdexfile and its transitive dependencies. + // The platform test that depends on them (`libunwindstack_unit_test` at the time of writing) + // no longer requires a prebuilt variant of libdexfile. + "libdexfile": android.ApiLevelUpsideDownCake, + "libartpalette": android.ApiLevelUpsideDownCake, + "libartbase": android.ApiLevelUpsideDownCake, +} + // groupMemberVariantsByMemberThenType groups the member variant dependencies so that all the // variants of each member are grouped together within an sdkMember instance. // @@ -216,6 +195,14 @@ func (s *sdk) groupMemberVariantsByMemberThenType(ctx android.ModuleContext, tar variant := memberVariantDep.variant name := ctx.OtherModuleName(variant) + targetApiLevel, err := android.ApiLevelFromUser(ctx, targetBuildRelease.name) + if err != nil { + targetApiLevel = android.FutureApiLevel + } + if lastApiLevel, exists := ignoreHostModuleVariantsAboveDessert[name]; exists && targetApiLevel.GreaterThan(lastApiLevel) && memberVariantDep.Host() { + // ignore host variant of this module if the targetApiLevel is V and above. + continue + } member := byName[name] if member == nil { member = &sdkMember{memberType: memberType, name: name} @@ -378,7 +365,7 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) { snapshotDir := android.PathForModuleOut(ctx, "snapshot") - bp := newGeneratedFile(ctx, "snapshot", "Android.bp") + bp := android.PathForModuleOut(ctx, "snapshot", "Android.bp") bpFile := &bpFile{ modules: make(map[string]*bpModule), @@ -392,7 +379,7 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) { sdk: s, snapshotDir: snapshotDir.OutputPath, copies: make(map[string]string), - filesToZip: []android.Path{bp.path}, + filesToZip: []android.Path{bp}, bpFile: bpFile, prebuiltModules: make(map[string]*bpModule), allMembersByName: allMembersByName, @@ -424,6 +411,7 @@ be unnecessary as every module in the sdk already has its own licenses property. // Create the prebuilt modules for each of the member modules. traits := s.gatherTraits() + memberNames := []string{} // soong module names of the members. contains the prebuilt_ prefix. for _, member := range members { memberType := member.memberType if !memberType.ArePrebuiltsRequired() { @@ -445,6 +433,46 @@ be unnecessary as every module in the sdk already has its own licenses property. prebuiltModule := memberType.AddPrebuiltModule(memberCtx, member) s.createMemberSnapshot(memberCtx, member, prebuiltModule.(*bpModule)) + + // Set stripper to none to skip stripping for generated snapshots. + // Mainline prebuilts (cc_prebuilt_library_shared) are not strippable in older platforms. + // Thus, stripping should be skipped when being used as prebuilts. + if memberType.DisablesStrip() { + stripPropertySet := prebuiltModule.(*bpModule).AddPropertySet("strip") + stripPropertySet.AddProperty("none", true) + } + + if member.memberType != android.LicenseModuleSdkMemberType && !builder.isInternalMember(member.name) { + // More exceptions + // 1. Skip BCP and SCCP fragments + // 2. Skip non-sdk contents of BCP and SCCP fragments + // + // The non-sdk contents of BCP/SSCP fragments should only be used for dexpreopt and hiddenapi, + // and are not available to the rest of the build. + if android.InList(member.memberType, + []android.SdkMemberType{ + // bcp + java.BootclasspathFragmentSdkMemberType, + java.JavaBootLibsSdkMemberType, + // sscp + java.SystemServerClasspathFragmentSdkMemberType, + java.JavaSystemserverLibsSdkMemberType, + }, + ) { + continue + } + + memberNames = append(memberNames, android.PrebuiltNameFromSource(member.name)) + } + } + + // create an apex_contributions_defaults for this module's sdk. + // this module type is supported in V and above. + if targetApiLevel.GreaterThan(android.ApiLevelUpsideDownCake) { + ac := newModule("apex_contributions_defaults") + ac.AddProperty("name", s.Name()+".contributions") + ac.AddProperty("contents", memberNames) + bpFile.AddModule(ac) } // Create a transformer that will transform a module by replacing any references @@ -455,25 +483,31 @@ be unnecessary as every module in the sdk already has its own licenses property. for _, module := range builder.prebuiltOrder { // Prune any empty property sets. - module = module.transform(pruneEmptySetTransformer{}) + module = transformModule(module, pruneEmptySetTransformer{}) // Transform the module module to make it suitable for use in the snapshot. - module.transform(snapshotTransformer) - bpFile.AddModule(module) + module = transformModule(module, snapshotTransformer) + module = transformModule(module, emptyClasspathContentsTransformation{}) + + targetApiLevel, err := android.ApiLevelFromUserWithConfig(ctx.Config(), s.targetBuildRelease(ctx).name) + if err == nil && targetApiLevel.LessThan(android.ApiLevelVanillaIceCream) { + module = transformModule(module, replaceExportablePropertiesTransformer{}) + } + + if module != nil { + bpFile.AddModule(module) + } } // generate Android.bp - bp = newGeneratedFile(ctx, "snapshot", "Android.bp") - generateBpContents(&bp.generatedContents, bpFile) - - contents := bp.content.String() + contents := generateBpContents(bpFile) // If the snapshot is being generated for the current build release then check the syntax to make // sure that it is compatible. if targetBuildRelease == buildReleaseCurrent { syntaxCheckSnapshotBpFile(ctx, contents) } - bp.build(pctx, ctx, nil) + android.WriteFileRuleVerbatim(ctx, bp, contents) // Copy the build number file into the snapshot. builder.CopyToSnapshot(ctx.Config().BuildNumberFile(ctx), BUILD_NUMBER_FILE) @@ -522,16 +556,14 @@ be unnecessary as every module in the sdk already has its own licenses property. modules := s.generateInfoData(ctx, memberVariantDeps) // Output the modules information as pretty printed JSON. - info := newGeneratedFile(ctx, fmt.Sprintf("%s%s.info", ctx.ModuleName(), snapshotFileSuffix)) + info := android.PathForModuleOut(ctx, fmt.Sprintf("%s%s.info", ctx.ModuleName(), snapshotFileSuffix)) output, err := json.MarshalIndent(modules, "", " ") if err != nil { ctx.ModuleErrorf("error generating %q: %s", info, err) } builder.infoContents = string(output) - info.generatedContents.UnindentedPrintf("%s", output) - info.build(pctx, ctx, nil) - infoPath := info.path - installedInfo := ctx.InstallFile(android.PathForMainlineSdksInstall(ctx), infoPath.Base(), infoPath) + android.WriteFileRuleVerbatim(ctx, info, builder.infoContents) + installedInfo := ctx.InstallFile(android.PathForMainlineSdksInstall(ctx), info.Base(), info) s.infoFile = android.OptionalPathForPath(installedInfo) // Install the zip, making sure that the info file has been installed as well. @@ -604,7 +636,7 @@ func (s *sdk) generateInfoData(ctx android.ModuleContext, memberVariantDeps []sd name: name, } - additionalSdkInfo := ctx.OtherModuleProvider(module, android.AdditionalSdkInfoProvider).(android.AdditionalSdkInfo) + additionalSdkInfo, _ := android.OtherModuleProvider(ctx, module, android.AdditionalSdkInfoProvider) info.memberSpecific = additionalSdkInfo.Properties name2Info[name] = info @@ -718,105 +750,6 @@ func extractCommonProperties(ctx android.ModuleContext, extractor *commonValueEx } } -// snapshotModuleStaticProperties contains snapshot static (i.e. not dynamically generated) properties. -type snapshotModuleStaticProperties struct { - Compile_multilib string `android:"arch_variant"` -} - -// combinedSnapshotModuleProperties are the properties that are associated with the snapshot module. -type combinedSnapshotModuleProperties struct { - // The sdk variant from which this information was collected. - sdkVariant *sdk - - // Static snapshot module properties. - staticProperties *snapshotModuleStaticProperties - - // The dynamically generated member list properties. - dynamicProperties interface{} -} - -// collateSnapshotModuleInfo collates all the snapshot module info from supplied sdk variants. -func (s *sdk) collateSnapshotModuleInfo(ctx android.BaseModuleContext, sdkVariants []*sdk, memberVariantDeps []sdkMemberVariantDep) []*combinedSnapshotModuleProperties { - sdkVariantToCombinedProperties := map[*sdk]*combinedSnapshotModuleProperties{} - var list []*combinedSnapshotModuleProperties - for _, sdkVariant := range sdkVariants { - staticProperties := &snapshotModuleStaticProperties{ - Compile_multilib: sdkVariant.multilibUsages.String(), - } - dynamicProperties := s.dynamicSdkMemberTypes.createMemberTypeListProperties() - - combinedProperties := &combinedSnapshotModuleProperties{ - sdkVariant: sdkVariant, - staticProperties: staticProperties, - dynamicProperties: dynamicProperties, - } - sdkVariantToCombinedProperties[sdkVariant] = combinedProperties - - list = append(list, combinedProperties) - } - - for _, memberVariantDep := range memberVariantDeps { - // If the member dependency is internal then do not add the dependency to the snapshot member - // list properties. - if !memberVariantDep.export { - continue - } - - combined := sdkVariantToCombinedProperties[memberVariantDep.sdkVariant] - memberListProperty := s.memberTypeListProperty(memberVariantDep.memberType) - memberName := ctx.OtherModuleName(memberVariantDep.variant) - - if memberListProperty.getter == nil { - continue - } - - // Append the member to the appropriate list, if it is not already present in the list. - memberList := memberListProperty.getter(combined.dynamicProperties) - if !android.InList(memberName, memberList) { - memberList = append(memberList, memberName) - } - memberListProperty.setter(combined.dynamicProperties, memberList) - } - - return list -} - -func (s *sdk) optimizeSnapshotModuleProperties(ctx android.ModuleContext, list []*combinedSnapshotModuleProperties) *combinedSnapshotModuleProperties { - - // Extract the dynamic properties and add them to a list of propertiesContainer. - propertyContainers := []propertiesContainer{} - for _, i := range list { - propertyContainers = append(propertyContainers, sdkVariantPropertiesContainer{ - sdkVariant: i.sdkVariant, - properties: i.dynamicProperties, - }) - } - - // Extract the common members, removing them from the original properties. - commonDynamicProperties := s.dynamicSdkMemberTypes.createMemberTypeListProperties() - extractor := newCommonValueExtractor(commonDynamicProperties) - extractCommonProperties(ctx, extractor, commonDynamicProperties, propertyContainers) - - // Extract the static properties and add them to a list of propertiesContainer. - propertyContainers = []propertiesContainer{} - for _, i := range list { - propertyContainers = append(propertyContainers, sdkVariantPropertiesContainer{ - sdkVariant: i.sdkVariant, - properties: i.staticProperties, - }) - } - - commonStaticProperties := &snapshotModuleStaticProperties{} - extractor = newCommonValueExtractor(commonStaticProperties) - extractCommonProperties(ctx, extractor, &commonStaticProperties, propertyContainers) - - return &combinedSnapshotModuleProperties{ - sdkVariant: nil, - staticProperties: commonStaticProperties, - dynamicProperties: commonDynamicProperties, - } -} - type propertyTag struct { name string } @@ -835,9 +768,11 @@ type snapshotTransformation struct { } func (t snapshotTransformation) 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)) + if module != nil { + // 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)) + } return module } @@ -850,6 +785,25 @@ func (t snapshotTransformation) transformProperty(_ string, value interface{}, t } } +type emptyClasspathContentsTransformation struct { + identityTransformation +} + +func (t emptyClasspathContentsTransformation) transformModule(module *bpModule) *bpModule { + classpathModuleTypes := []string{ + "prebuilt_bootclasspath_fragment", + "prebuilt_systemserverclasspath_fragment", + } + if module != nil && android.InList(module.moduleType, classpathModuleTypes) { + if contents, ok := module.bpPropertySet.properties["contents"].([]string); ok { + if len(contents) == 0 { + return nil + } + } + } + return module +} + type pruneEmptySetTransformer struct { identityTransformation } @@ -864,7 +818,52 @@ func (t pruneEmptySetTransformer) transformPropertySetAfterContents(_ string, pr } } -func generateBpContents(contents *generatedContents, bpFile *bpFile) { +type replaceExportablePropertiesTransformer struct { + identityTransformation +} + +var _ bpTransformer = (*replaceExportablePropertiesTransformer)(nil) + +func handleExportableProperties[T any](value T) any { + switch v := any(value).(type) { + case string: + return java.AllApiScopes.ConvertStubsLibraryExportableToEverything(v) + case *bpPropertySet: + v.properties = handleExportableProperties(v.properties).(map[string]interface{}) + return v + case []string: + result := make([]string, len(v)) + for i, elem := range v { + result[i] = handleExportableProperties(elem).(string) + } + return result + case []any: + result := make([]any, len(v)) + for i, elem := range v { + result[i] = handleExportableProperties(elem) + } + return result + case map[string]any: + result := make(map[string]any) + for k, val := range v { + result[k] = handleExportableProperties(val) + } + return result + default: + return value + } +} + +func (t replaceExportablePropertiesTransformer) transformPropertySetAfterContents(name string, propertySet *bpPropertySet, tag android.BpPropertyTag) (*bpPropertySet, android.BpPropertyTag) { + if name == "name" { + return propertySet, tag + } + propertySet.properties = handleExportableProperties(propertySet.properties).(map[string]interface{}) + return propertySet, tag +} + +func generateBpContents(bpFile *bpFile) string { + contents := &generatedContents{} contents.IndentedPrintf("// This is auto-generated. DO NOT EDIT.\n") for _, bpModule := range bpFile.order { contents.IndentedPrintf("\n") @@ -872,6 +871,7 @@ func generateBpContents(contents *generatedContents, bpFile *bpFile) { outputPropertySet(contents, bpModule.bpPropertySet) contents.IndentedPrintf("}\n") } + return contents.content.String() } func outputPropertySet(contents *generatedContents, set *bpPropertySet) { @@ -986,7 +986,7 @@ func outputUnnamedValue(contents *generatedContents, value reflect.Value) { contents.IndentedPrintf("}") default: - panic(fmt.Errorf("Unknown type: %T of value %#v", value, value)) + panic(fmt.Errorf("unknown type: %T of value %#v", value, value)) } } @@ -997,9 +997,7 @@ func multiLineValue(value reflect.Value) bool { } func (s *sdk) GetAndroidBpContentsForTests() string { - contents := &generatedContents{} - generateBpContents(contents, s.builderForTests.bpFile) - return contents.content.String() + return generateBpContents(s.builderForTests.bpFile) } func (s *sdk) GetInfoContentsForTests() string { @@ -1147,7 +1145,7 @@ func (s *snapshotBuilder) AddPrebuiltModule(member android.SdkMember, moduleType // The licenses are the same for all variants. mctx := s.ctx - licenseInfo := mctx.OtherModuleProvider(variant, android.LicenseInfoProvider).(android.LicenseInfo) + licenseInfo, _ := android.OtherModuleProvider(mctx, variant, android.LicenseInfoProvider) if len(licenseInfo.Licenses) > 0 { m.AddPropertyWithTag("licenses", licenseInfo.Licenses, s.OptionalSdkMemberReferencePropertyTag()) } @@ -1313,7 +1311,7 @@ func (m multilibUsage) addArchType(archType android.ArchType) multilibUsage { case "lib64": return m | multilib64 default: - panic(fmt.Errorf("Unknown Multilib field in ArchType, expected 'lib32' or 'lib64', found %q", multilib)) + panic(fmt.Errorf("unknown Multilib field in ArchType, expected 'lib32' or 'lib64', found %q", multilib)) } } @@ -1328,7 +1326,7 @@ func (m multilibUsage) String() string { case multilibBoth: return "both" default: - panic(fmt.Errorf("Unknown multilib value, found %b, expected one of %b, %b, %b or %b", + panic(fmt.Errorf("unknown multilib value, found %b, expected one of %b, %b, %b or %b", m, multilibNone, multilib32, multilib64, multilibBoth)) } } @@ -1393,7 +1391,7 @@ func selectApexVariantsWhereAvailable(ctx *memberContext, variants []android.Mod variantsByApex := make(map[string]android.Module) conflictDetected := false for _, variant := range list { - apexInfo := moduleCtx.OtherModuleProvider(variant, android.ApexInfoProvider).(android.ApexInfo) + apexInfo, _ := android.OtherModuleProvider(moduleCtx, variant, android.ApexInfoProvider) apexVariationName := apexInfo.ApexVariationName // If there are two variants for a specific APEX variation then there is conflict. if _, ok := variantsByApex[apexVariationName]; ok { @@ -1963,6 +1961,10 @@ type memberContext struct { requiredTraits android.SdkMemberTraitSet } +func (m *memberContext) ModuleErrorf(fmt string, args ...interface{}) { + m.sdkMemberContext.ModuleErrorf(fmt, args...) +} + func (m *memberContext) SdkModuleContext() android.ModuleContext { return m.sdkMemberContext } @@ -2277,20 +2279,6 @@ type propertiesContainer interface { optimizableProperties() interface{} } -// A wrapper for sdk variant related properties to allow them to be optimized. -type sdkVariantPropertiesContainer struct { - sdkVariant *sdk - properties interface{} -} - -func (c sdkVariantPropertiesContainer) optimizableProperties() interface{} { - return c.properties -} - -func (c sdkVariantPropertiesContainer) String() string { - return c.sdkVariant.String() -} - // Extract common properties from a slice of property structures of the same type. // // All the property structures must be of the same type. |