From 39abf8f387b92b454a0fd856af43a197ceabbd85 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Fri, 24 Sep 2021 14:58:27 +0100 Subject: [PATCH] Retry: Support generating sdk snapshot for specific build release This was reverted unnecessarily along with the change that actually broke the build. Previously, the sdk snapshot was assumed to be generated for the current build system. This change adds support for the SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE environment variable which can be used to select the target build release in which the generated snapshot will be used. At the moment this will only affect the properties that are output but if/when it becomes necessary it can also be used to control more aspects of the snapshots such as supported member types or even members. This change does not modify any properties that are build release specific. That will come in following changes. However, it does add a test that targets build release S which defines a baseline for properties that will be affected in following changes. That baseline makes it easier to see the effect of those follow up changes. Bug: 197842263 Test: m nothing Change-Id: If4b452237f105382550d2842c8010249afbc7432 --- sdk/sdk_test.go | 85 ++++++++++++++++++++++++++++++++++++++++++++ sdk/testing.go | 11 ++++++ sdk/update.go | 74 ++++++++++++++++++++++++++++++++++++-- ui/build/dumpvars.go | 1 + 4 files changed, 169 insertions(+), 2 deletions(-) diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go index 85e3d875e..f5f6898a7 100644 --- a/sdk/sdk_test.go +++ b/sdk/sdk_test.go @@ -21,6 +21,7 @@ import ( "testing" "android/soong/android" + "android/soong/java" "github.com/google/blueprint/proptools" ) @@ -706,4 +707,88 @@ sdk_snapshot { snapshotTestPreparer(checkSnapshotWithoutSource, android.FixtureWithRootAndroidBp(bp)), ) }) + + t.Run("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE=S", func(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForSdkTestWithJava, + java.PrepareForTestWithJavaDefaultModules, + java.PrepareForTestWithJavaSdkLibraryFiles, + java.FixtureWithLastReleaseApis("mysdklibrary"), + android.FixtureWithRootAndroidBp(` + sdk { + name: "mysdk", + bootclasspath_fragments: ["mybootclasspathfragment"], + } + + bootclasspath_fragment { + name: "mybootclasspathfragment", + apex_available: ["myapex"], + contents: ["mysdklibrary"], + } + + java_sdk_library { + name: "mysdklibrary", + srcs: ["Test.java"], + compile_dex: true, + public: {enabled: true}, + permitted_packages: ["mysdklibrary"], + } + `), + android.FixtureMergeEnv(map[string]string{ + "SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": "S", + }), + ).RunTest(t) + + CheckSnapshot(t, result, "mysdk", "", + checkUnversionedAndroidBpContents(` +// This is auto-generated. DO NOT EDIT. + +prebuilt_bootclasspath_fragment { + name: "mybootclasspathfragment", + prefer: false, + visibility: ["//visibility:public"], + apex_available: ["myapex"], + contents: ["mysdklibrary"], + hidden_api: { + annotation_flags: "hiddenapi/annotation-flags.csv", + metadata: "hiddenapi/metadata.csv", + index: "hiddenapi/index.csv", + signature_patterns: "hiddenapi/signature-patterns.csv", + stub_flags: "hiddenapi/filtered-stub-flags.csv", + all_flags: "hiddenapi/filtered-flags.csv", + }, +} + +java_sdk_library_import { + name: "mysdklibrary", + prefer: false, + visibility: ["//visibility:public"], + apex_available: ["//apex_available:platform"], + shared_library: true, + compile_dex: true, + permitted_packages: ["mysdklibrary"], + public: { + jars: ["sdk_library/public/mysdklibrary-stubs.jar"], + stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"], + current_api: "sdk_library/public/mysdklibrary.txt", + removed_api: "sdk_library/public/mysdklibrary-removed.txt", + sdk_version: "current", + }, +} +`), + + checkAllCopyRules(` +.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv +.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/metadata.csv -> hiddenapi/metadata.csv +.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/index.csv -> hiddenapi/index.csv +.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/signature-patterns.csv -> hiddenapi/signature-patterns.csv +.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv +.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv +.intermediates/mysdklibrary.stubs/android_common/javac/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar +.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt +.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt +`), + ) + }) + } diff --git a/sdk/testing.go b/sdk/testing.go index 3254cf9f3..294f1a57d 100644 --- a/sdk/testing.go +++ b/sdk/testing.go @@ -136,6 +136,7 @@ func getSdkSnapshotBuildInfo(t *testing.T, result *android.TestResult, sdk *sdk) androidUnversionedBpContents: sdk.GetUnversionedAndroidBpContentsForTests(), androidVersionedBpContents: sdk.GetVersionedAndroidBpContentsForTests(), snapshotTestCustomizations: map[snapshotTest]*snapshotTestCustomization{}, + targetBuildRelease: sdk.builderForTests.targetBuildRelease, } buildParams := sdk.BuildParamsForTests() @@ -253,6 +254,13 @@ func CheckSnapshot(t *testing.T, result *android.TestResult, name string, dir st } fs[filepath.Join(snapshotSubDir, "Android.bp")] = []byte(snapshotBuildInfo.androidBpContents) + // If the generated snapshot builders not for the current release then it cannot be loaded by + // the current release. + currentBuildRelease := latestBuildRelease() + if snapshotBuildInfo.targetBuildRelease != currentBuildRelease { + return + } + // The preparers from the original source fixture. sourcePreparers := result.Preparer() @@ -476,6 +484,9 @@ type snapshotBuildInfo struct { // The final output zip. outputZip string + // The target build release. + targetBuildRelease *buildRelease + // The test specific customizations for each snapshot test. snapshotTestCustomizations map[snapshotTest]*snapshotTestCustomization } diff --git a/sdk/update.go b/sdk/update.go index 3246832d4..389e845e7 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -81,6 +81,19 @@ import ( // snapshot module only. The zip file containing the generated snapshot will be // -.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 +// to the current build release version. Otherwise, it must be the name of one of the build +// releases defined in nameToBuildRelease, e.g. S, T, etc.. +// +// The generated snapshot must only be used in the specified target release. If the target +// build release is not the current build release then the generated Android.bp file not be +// checked for compatibility. +// +// e.g. if setting SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE=S will cause the generated snapshot +// to be compatible with S. +// var pctx = android.NewPackageContext("android/soong/sdk") @@ -358,6 +371,14 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) andro snapshotZipFileSuffix = "-" + version } + currentBuildRelease := latestBuildRelease() + targetBuildReleaseEnv := config.GetenvWithDefault("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE", currentBuildRelease.name) + targetBuildRelease, err := nameToRelease(targetBuildReleaseEnv) + if err != nil { + ctx.ModuleErrorf("invalid SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE: %s", err) + targetBuildRelease = currentBuildRelease + } + builder := &snapshotBuilder{ ctx: ctx, sdk: s, @@ -369,6 +390,7 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) andro prebuiltModules: make(map[string]*bpModule), allMembersByName: allMembersByName, exportedMembersByName: exportedMembersByName, + targetBuildRelease: targetBuildRelease, } s.builderForTests = builder @@ -449,7 +471,11 @@ be unnecessary as every module in the sdk already has its own licenses property. generateBpContents(&bp.generatedContents, bpFile) contents := bp.content.String() - syntaxCheckSnapshotBpFile(ctx, contents) + // If the snapshot is being generated for the current build release then check the syntax to make + // sure that it is compatible. + if targetBuildRelease == currentBuildRelease { + syntaxCheckSnapshotBpFile(ctx, contents) + } bp.build(pctx, ctx, nil) @@ -1051,6 +1077,9 @@ type snapshotBuilder struct { // The set of exported members by name. exportedMembersByName map[string]struct{} + + // The target build release for which the snapshot is to be generated. + targetBuildRelease *buildRelease } func (s *snapshotBuilder) CopyToSnapshot(src android.Path, dest string) { @@ -1426,6 +1455,16 @@ func newOsTypeSpecificInfo(ctx android.SdkMemberContext, osType android.OsType, return osInfo } +func (osInfo *osTypeSpecificInfo) pruneUnsupportedProperties(pruner *propertyPruner) { + if len(osInfo.archInfos) == 0 { + pruner.pruneProperties(osInfo.Properties) + } else { + for _, archInfo := range osInfo.archInfos { + archInfo.pruneUnsupportedProperties(pruner) + } + } +} + // Optimize the properties by extracting common properties from arch type specific // properties into os type specific properties. func (osInfo *osTypeSpecificInfo) optimizeProperties(ctx *memberContext, commonValueExtractor *commonValueExtractor) { @@ -1635,6 +1674,16 @@ func getLinkType(variant android.Module) string { return linkType } +func (archInfo *archTypeSpecificInfo) pruneUnsupportedProperties(pruner *propertyPruner) { + if len(archInfo.imageVariantInfos) == 0 { + pruner.pruneProperties(archInfo.Properties) + } else { + for _, imageVariantInfo := range archInfo.imageVariantInfos { + imageVariantInfo.pruneUnsupportedProperties(pruner) + } + } +} + // Optimize the properties by extracting common properties from link type specific // properties into arch type specific properties. func (archInfo *archTypeSpecificInfo) optimizeProperties(ctx *memberContext, commonValueExtractor *commonValueExtractor) { @@ -1732,6 +1781,16 @@ func newImageVariantSpecificInfo(ctx android.SdkMemberContext, imageVariant stri return imageInfo } +func (imageInfo *imageVariantSpecificInfo) pruneUnsupportedProperties(pruner *propertyPruner) { + if len(imageInfo.linkInfos) == 0 { + pruner.pruneProperties(imageInfo.Properties) + } else { + for _, linkInfo := range imageInfo.linkInfos { + linkInfo.pruneUnsupportedProperties(pruner) + } + } +} + // Optimize the properties by extracting common properties from link type specific // properties into arch type specific properties. func (imageInfo *imageVariantSpecificInfo) optimizeProperties(ctx *memberContext, commonValueExtractor *commonValueExtractor) { @@ -1798,6 +1857,10 @@ func (l *linkTypeSpecificInfo) addToPropertySet(ctx *memberContext, propertySet addSdkMemberPropertiesToSet(ctx, l.Properties, linkPropertySet) } +func (l *linkTypeSpecificInfo) pruneUnsupportedProperties(pruner *propertyPruner) { + pruner.pruneProperties(l.Properties) +} + func (l *linkTypeSpecificInfo) String() string { return fmt.Sprintf("LinkType{%s}", l.linkType) } @@ -1837,12 +1900,12 @@ 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() 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. // TODO(b/174997203): Remove once the ability to select the modules to prefer can be done // dynamically at build time not at snapshot generation time. - config := ctx.sdkMemberContext.Config() prefer := config.IsEnvTrue("SOONG_SDK_SNAPSHOT_PREFER") // Set prefer. Setting this to false is not strictly required as that is the default but it does @@ -1884,6 +1947,11 @@ func (s *sdk) createMemberSnapshot(ctx *memberContext, member *sdkMember, bpModu commonProperties := variantPropertiesFactory() commonProperties.Base().Os = android.CommonOS + // Create a property pruner that will prune any properties unsupported by the target build + // release. + targetBuildRelease := ctx.builder.targetBuildRelease + unsupportedPropertyPruner := newPropertyPrunerByBuildRelease(commonProperties, targetBuildRelease) + // Create common value extractor that can be used to optimize the properties. commonValueExtractor := newCommonValueExtractor(commonProperties) @@ -1898,6 +1966,8 @@ func (s *sdk) createMemberSnapshot(ctx *memberContext, member *sdkMember, bpModu // independent properties structs. osSpecificPropertiesContainers = append(osSpecificPropertiesContainers, osInfo) + osInfo.pruneUnsupportedProperties(unsupportedPropertyPruner) + // Optimize the properties across all the variants for a specific os type. osInfo.optimizeProperties(ctx, commonValueExtractor) } diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go index 3d160730a..afec8293c 100644 --- a/ui/build/dumpvars.go +++ b/ui/build/dumpvars.go @@ -163,6 +163,7 @@ var BannerVars = []string{ "AUX_OS_VARIANT_LIST", "PRODUCT_SOONG_NAMESPACES", "SOONG_SDK_SNAPSHOT_PREFER", + "SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE", "SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR", "SOONG_SDK_SNAPSHOT_VERSION", }