Merge "Use the correct bootjars when multiple prebuilt apexes exist" into main am: 412b33a6e7 am: ec7918d041 am: 4cf8303b55

Original change: https://android-review.googlesource.com/c/platform/build/soong/+/2876756

Change-Id: Iff568b322a299f702c3cb5369149f163b493ad5f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Spandan Das
2023-12-20 20:24:15 +00:00
committed by Automerger Merge Worker
13 changed files with 282 additions and 64 deletions

View File

@@ -385,6 +385,10 @@ func (i BootclasspathFragmentApexContentInfo) DexBootJarPathForContentModule(mod
}
}
func (i BootclasspathFragmentApexContentInfo) DexBootJarPathMap() bootDexJarByModule {
return i.contentModuleDexJarPaths
}
func (i BootclasspathFragmentApexContentInfo) ProfilePathOnHost() android.Path {
return i.profilePathOnHost
}
@@ -1034,10 +1038,6 @@ func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx an
return android.PathForModuleSrc(ctx, *src)
}
// Retrieve the dex files directly from the content modules. They in turn should retrieve the
// encoded dex jars from the prebuilt .apex files.
encodedBootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, contents)
output := HiddenAPIOutput{
HiddenAPIFlagOutput: HiddenAPIFlagOutput{
AnnotationFlagsPath: pathForSrc("hidden_api.annotation_flags", module.prebuiltProperties.Hidden_api.Annotation_flags),
@@ -1048,8 +1048,6 @@ func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx an
StubFlagsPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.Stub_flags, nil),
AllFlagsPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.All_flags, nil),
},
EncodedBootDexFilesByModule: encodedBootDexJarsByModule,
}
// TODO: Temporarily fallback to stub_flags/all_flags properties until prebuilts have been updated.

View File

@@ -272,7 +272,7 @@ func (d *Dexpreopter) DexpreoptPrebuiltApexSystemServerJars(ctx android.ModuleCo
dc := dexpreopt.GetGlobalConfig(ctx)
d.installPath = android.PathForModuleInPartitionInstall(ctx, "", strings.TrimPrefix(dexpreopt.GetSystemServerDexLocation(ctx, dc, libraryName), "/"))
// generate the rules for creating the .odex and .vdex files for this system server jar
dexJarFile := di.PrebuiltExportPath(apexRootRelativePathToJavaLib(libraryName))
dexJarFile := di.PrebuiltExportPath(ApexRootRelativePathToJavaLib(libraryName))
d.dexpreopt(ctx, dexJarFile)
}

View File

@@ -699,38 +699,57 @@ func getModulesForImage(ctx android.ModuleContext, imageConfig *bootImageConfig)
// extractEncodedDexJarsFromModulesOrBootclasspathFragments gets the hidden API encoded dex jars for
// the given modules.
func extractEncodedDexJarsFromModulesOrBootclasspathFragments(ctx android.ModuleContext, apexJarModulePairs []apexJarModulePair) bootDexJarByModule {
apexNameToBcpInfoMap := getApexNameToBcpInfoMap(ctx)
encodedDexJarsByModuleName := bootDexJarByModule{}
for _, pair := range apexJarModulePairs {
var path android.Path
if android.IsConfiguredJarForPlatform(pair.apex) || android.IsModulePrebuilt(pair.jarModule) {
// This gives us the dex jar with the hidden API flags encoded from the monolithic hidden API
// files or the dex jar extracted from a prebuilt APEX. We can't use this for a boot jar for
// a source APEX because there is no guarantee that it is the same as the jar packed into the
// APEX. In practice, they are the same when we are building from a full source tree, but they
// are different when we are building from a thin manifest (e.g., master-art), where there is
// no monolithic hidden API files at all.
path = retrieveEncodedBootDexJarFromModule(ctx, pair.jarModule)
} else {
// Use exactly the same jar that is packed into the APEX.
fragment := getBootclasspathFragmentByApex(ctx, pair.apex)
if fragment == nil {
ctx.ModuleErrorf("Boot jar '%[1]s' is from APEX '%[2]s', but a bootclasspath_fragment for "+
"APEX '%[2]s' doesn't exist or is not added as a dependency of dex_bootjars",
pair.jarModule.Name(),
pair.apex)
}
bootclasspathFragmentInfo, _ := android.OtherModuleProvider(ctx, fragment, BootclasspathFragmentApexContentInfoProvider)
jar, err := bootclasspathFragmentInfo.DexBootJarPathForContentModule(pair.jarModule)
if err != nil {
ctx.ModuleErrorf("%s", err)
}
path = jar
}
encodedDexJarsByModuleName.addPath(pair.jarModule, path)
dexJarPath := getDexJarForApex(ctx, pair, apexNameToBcpInfoMap)
encodedDexJarsByModuleName.addPath(pair.jarModule, dexJarPath)
}
return encodedDexJarsByModuleName
}
// Returns the java libraries exported by the apex for hiddenapi and dexpreopt
// This information can come from two mechanisms
// 1. New: Direct deps to _selected_ apexes. The apexes return a ApexExportsInfo
// 2. Legacy: An edge to java_library or java_import (java_sdk_library) module. For prebuilt apexes, this serves as a hook and is populated by deapexers of prebuilt apxes
// TODO: b/308174306 - Once all mainline modules have been flagged, drop (2)
func getDexJarForApex(ctx android.ModuleContext, pair apexJarModulePair, apexNameToBcpInfoMap map[string]android.ApexExportsInfo) android.Path {
if info, exists := apexNameToBcpInfoMap[pair.apex]; exists {
libraryName := android.RemoveOptionalPrebuiltPrefix(pair.jarModule.Name())
if dex, exists := info.LibraryNameToDexJarPathOnHost[libraryName]; exists {
return dex
} else {
ctx.ModuleErrorf("Apex %s does not provide a dex boot jar for library %s\n", pair.apex, libraryName)
}
}
// TODO: b/308174306 - Remove the legacy mechanism
if android.IsConfiguredJarForPlatform(pair.apex) || android.IsModulePrebuilt(pair.jarModule) {
// This gives us the dex jar with the hidden API flags encoded from the monolithic hidden API
// files or the dex jar extracted from a prebuilt APEX. We can't use this for a boot jar for
// a source APEX because there is no guarantee that it is the same as the jar packed into the
// APEX. In practice, they are the same when we are building from a full source tree, but they
// are different when we are building from a thin manifest (e.g., master-art), where there is
// no monolithic hidden API files at all.
return retrieveEncodedBootDexJarFromModule(ctx, pair.jarModule)
} else {
// Use exactly the same jar that is packed into the APEX.
fragment := getBootclasspathFragmentByApex(ctx, pair.apex)
if fragment == nil {
ctx.ModuleErrorf("Boot jar '%[1]s' is from APEX '%[2]s', but a bootclasspath_fragment for "+
"APEX '%[2]s' doesn't exist or is not added as a dependency of dex_bootjars",
pair.jarModule.Name(),
pair.apex)
}
bootclasspathFragmentInfo, _ := android.OtherModuleProvider(ctx, fragment, BootclasspathFragmentApexContentInfoProvider)
jar, err := bootclasspathFragmentInfo.DexBootJarPathForContentModule(pair.jarModule)
if err != nil {
ctx.ModuleErrorf("%s", err)
}
return jar
}
return nil
}
// copyBootJarsToPredefinedLocations generates commands that will copy boot jars to predefined
// paths in the global config.
func copyBootJarsToPredefinedLocations(ctx android.ModuleContext, srcBootDexJarsByModule bootDexJarByModule, dstBootJarsByModule map[string]android.WritablePath) {
@@ -881,6 +900,16 @@ func getProfilePathForApex(ctx android.ModuleContext, apexName string, apexNameT
return fragment.(commonBootclasspathFragment).getProfilePath()
}
func getApexNameToBcpInfoMap(ctx android.ModuleContext) map[string]android.ApexExportsInfo {
apexNameToBcpInfoMap := map[string]android.ApexExportsInfo{}
ctx.VisitDirectDepsWithTag(dexpreoptBootJarDepTag, func(am android.Module) {
if info, exists := android.OtherModuleProvider(ctx, am, android.ApexExportsInfoProvider); exists {
apexNameToBcpInfoMap[info.ApexName] = info
}
})
return apexNameToBcpInfoMap
}
// Generate boot image build rules for a specific target.
func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) bootImageVariantOutputs {
@@ -923,12 +952,7 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p
invocationPath := outputPath.ReplaceExtension(ctx, "invocation")
apexNameToBcpInfoMap := map[string]android.ApexExportsInfo{}
ctx.VisitDirectDepsWithTag(dexpreoptBootJarDepTag, func(am android.Module) {
if info, exists := android.OtherModuleProvider(ctx, am, android.ApexExportsInfoProvider); exists {
apexNameToBcpInfoMap[info.ApexName] = info
}
})
apexNameToBcpInfoMap := getApexNameToBcpInfoMap(ctx)
cmd.Tool(globalSoong.Dex2oat).
Flag("--avoid-storing-invocation").

View File

@@ -947,6 +947,7 @@ type HiddenAPIOutput struct {
HiddenAPIFlagOutput
// The map from base module name to the path to the encoded boot dex file.
// This field is not available in prebuilt apexes
EncodedBootDexFilesByModule bootDexJarByModule
}

View File

@@ -2258,11 +2258,11 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.dexJarFileErr = err
return
}
dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(j.BaseModuleName())
dexJarFileApexRootRelative := ApexRootRelativePathToJavaLib(j.BaseModuleName())
if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil {
dexJarFile := makeDexJarPathFromPath(dexOutputPath)
j.dexJarFile = dexJarFile
installPath := android.PathForModuleInPartitionInstall(ctx, "apex", ai.ApexVariationName, apexRootRelativePathToJavaLib(j.BaseModuleName()))
installPath := android.PathForModuleInPartitionInstall(ctx, "apex", ai.ApexVariationName, ApexRootRelativePathToJavaLib(j.BaseModuleName()))
j.dexJarInstallFile = installPath
j.dexpreopter.installPath = j.dexpreopter.getInstallPath(ctx, installPath)
@@ -2422,7 +2422,7 @@ func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
// java_sdk_library_import with the specified base module name requires to be exported from a
// prebuilt_apex/apex_set.
func requiredFilesFromPrebuiltApexForImport(name string, d *dexpreopter) []string {
dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(name)
dexJarFileApexRootRelative := ApexRootRelativePathToJavaLib(name)
// Add the dex implementation jar to the set of exported files.
files := []string{
dexJarFileApexRootRelative,
@@ -2433,9 +2433,9 @@ func requiredFilesFromPrebuiltApexForImport(name string, d *dexpreopter) []strin
return files
}
// apexRootRelativePathToJavaLib returns the path, relative to the root of the apex's contents, for
// ApexRootRelativePathToJavaLib returns the path, relative to the root of the apex's contents, for
// the java library with the specified name.
func apexRootRelativePathToJavaLib(name string) string {
func ApexRootRelativePathToJavaLib(name string) string {
return filepath.Join("javalib", name+".jar")
}

View File

@@ -2695,7 +2695,7 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo
module.dexJarFileErr = err
return
}
dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(module.BaseModuleName())
dexJarFileApexRootRelative := ApexRootRelativePathToJavaLib(module.BaseModuleName())
if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil {
dexJarFile := makeDexJarPathFromPath(dexOutputPath)
module.dexJarFile = dexJarFile