Simplify deapexer support

Uses the apex relative path to the file as the identifier that is used
to obtain the path to the corresponding file extracted from the apex.
That is instead of a special constructed string id.

Bug: 177892522
Test: m nothing
Merged-In: I5dc77c8fb272bac289b8891d1eac801e541af1f5
Change-Id: I5dc77c8fb272bac289b8891d1eac801e541af1f5
(cherry picked from commit b4bbf2ca10cc8509e3ae0ab104e9e3b55861831b)
This commit is contained in:
Paul Duffin 2021-06-17 15:59:07 +01:00
parent 7db57e0a77
commit 034196d9fe
6 changed files with 48 additions and 74 deletions

View File

@ -55,9 +55,9 @@ import (
// //
// The files that are passed to `deapexer` and those that are passed back have a unique identifier // The files that are passed to `deapexer` and those that are passed back have a unique identifier
// that links them together. e.g. If the `deapexer` is passed something like this: // that links them together. e.g. If the `deapexer` is passed something like this:
// core-libart{.dexjar} -> javalib/core-libart.jar // javalib/core-libart.jar -> javalib/core-libart.jar
// it will return something like this: // it will return something like this:
// core-libart{.dexjar} -> out/soong/.....deapexer.../javalib/core-libart.jar // javalib/core-libart.jar -> out/soong/.....deapexer.../javalib/core-libart.jar
// //
// The reason why the `deapexer` module is separate from the prebuilt_apex/apex_set is to avoid // The reason why the `deapexer` module is separate from the prebuilt_apex/apex_set is to avoid
// cycles. e.g. // cycles. e.g.
@ -70,7 +70,7 @@ import (
// The information exported by the `deapexer` module, access it using `DeapxerInfoProvider`. // The information exported by the `deapexer` module, access it using `DeapxerInfoProvider`.
type DeapexerInfo struct { type DeapexerInfo struct {
// map from the name of an exported file from a prebuilt_apex to the path to that file. The // map from the name of an exported file from a prebuilt_apex to the path to that file. The
// exported file name is of the form <module>{<tag>}. // exported file name is the apex relative path, e.g. javalib/core-libart.jar.
// //
// See Prebuilt.ApexInfoMutator for more information. // See Prebuilt.ApexInfoMutator for more information.
exports map[string]Path exports map[string]Path
@ -79,15 +79,11 @@ type DeapexerInfo struct {
// PrebuiltExportPath provides the path, or nil if not available, of a file exported from the // PrebuiltExportPath provides the path, or nil if not available, of a file exported from the
// prebuilt_apex that created this ApexInfo. // prebuilt_apex that created this ApexInfo.
// //
// The exported file is identified by the module name and the tag: // The exported file is identified by the apex relative path, e.g. "javalib/core-libart.jar".
// * The module name is the name of the module that contributed the file when the .apex file
// referenced by the prebuilt_apex was built. It must be specified in one of the exported_...
// properties on the prebuilt_apex module.
// * The tag identifies the type of file and is dependent on the module type.
// //
// See apex/deapexer.go for more information. // See apex/deapexer.go for more information.
func (i DeapexerInfo) PrebuiltExportPath(name, tag string) Path { func (i DeapexerInfo) PrebuiltExportPath(apexRelativePath string) Path {
path := i.exports[name+"{"+tag+"}"] path := i.exports[apexRelativePath]
return path return path
} }
@ -120,13 +116,13 @@ var DeapexerTag = deapexerTagStruct{}
// RequiredFilesFromPrebuiltApex must be implemented by modules that require files to be exported // RequiredFilesFromPrebuiltApex must be implemented by modules that require files to be exported
// from a prebuilt_apex/apex_set. // from a prebuilt_apex/apex_set.
type RequiredFilesFromPrebuiltApex interface { type RequiredFilesFromPrebuiltApex interface {
// RequiredFilesFromPrebuiltApex returns a map from the key (module name plus tag) to the required // RequiredFilesFromPrebuiltApex returns a list of the file paths (relative to the root of the
// path of the file within the prebuilt .apex file. // APEX's contents) that the implementing module requires from within a prebuilt .apex file.
// //
// For each key/file pair this will cause the file to be extracted out of the prebuilt .apex file, // For each file path this will cause the file to be extracted out of the prebuilt .apex file, and
// and the path to the extracted file will be stored in the DeapexerInfo using that key, The path // the path to the extracted file will be stored in the DeapexerInfo using the APEX relative file
// can then be retrieved using the PrebuiltExportPath(name, tag) method. // path as the key, The path can then be retrieved using the PrebuiltExportPath(key) method.
RequiredFilesFromPrebuiltApex(ctx BaseModuleContext) map[string]string RequiredFilesFromPrebuiltApex(ctx BaseModuleContext) []string
} }
// Marker interface that identifies dependencies on modules that may require files from a prebuilt // Marker interface that identifies dependencies on modules that may require files from a prebuilt

View File

@ -40,16 +40,6 @@ import (
// This is intentionally not registered by name as it is not intended to be used from within an // This is intentionally not registered by name as it is not intended to be used from within an
// `Android.bp` file. // `Android.bp` file.
// DeapexerExportedFile defines the properties needed to expose a file from the deapexer module.
type DeapexerExportedFile struct {
// The tag parameter which must be passed to android.DeapexerInfo's PrebuiltExportPath(name, tag)
// method to retrieve the path to the unpacked file.
Tag string
// The path within the APEX that needs to be exported.
Path string `android:"path"`
}
// DeapexerProperties specifies the properties supported by the deapexer module. // DeapexerProperties specifies the properties supported by the deapexer module.
// //
// As these are never intended to be supplied in a .bp file they use a different naming convention // As these are never intended to be supplied in a .bp file they use a different naming convention
@ -62,7 +52,9 @@ type DeapexerProperties struct {
CommonModules []string CommonModules []string
// List of files exported from the .apex file by this module // List of files exported from the .apex file by this module
ExportedFiles []DeapexerExportedFile //
// Each entry is a path from the apex root, e.g. javalib/core-libart.jar.
ExportedFiles []string
} }
type SelectedApexProperties struct { type SelectedApexProperties struct {
@ -107,27 +99,23 @@ func (p *Deapexer) GenerateAndroidBuildActions(ctx android.ModuleContext) {
exports := make(map[string]android.Path) exports := make(map[string]android.Path)
// Create mappings from name+tag to all the required exported paths. // Create mappings from apex relative path to the extracted file's path.
for _, e := range p.properties.ExportedFiles { exportedPaths := make(android.Paths, 0, len(exports))
tag := e.Tag for _, path := range p.properties.ExportedFiles {
path := e.Path
// Populate the exports that this makes available. // Populate the exports that this makes available.
exports[tag] = deapexerOutput.Join(ctx, path) extractedPath := deapexerOutput.Join(ctx, path)
exports[path] = extractedPath
exportedPaths = append(exportedPaths, extractedPath)
} }
// If the prebuilt_apex exports any files then create a build rule that unpacks the apex using // If the prebuilt_apex exports any files then create a build rule that unpacks the apex using
// deapexer and verifies that all the required files were created. Also, make the mapping from // deapexer and verifies that all the required files were created. Also, make the mapping from
// name+tag to path available for other modules. // apex relative path to extracted file path available for other modules.
if len(exports) > 0 { if len(exports) > 0 {
// Make the information available for other modules. // Make the information available for other modules.
ctx.SetProvider(android.DeapexerProvider, android.NewDeapexerInfo(exports)) ctx.SetProvider(android.DeapexerProvider, android.NewDeapexerInfo(exports))
// Create a sorted list of the files that this exports. // Create a sorted list of the files that this exports.
exportedPaths := make(android.Paths, 0, len(exports))
for _, p := range exports {
exportedPaths = append(exportedPaths, p)
}
exportedPaths = android.SortedUniquePaths(exportedPaths) exportedPaths = android.SortedUniquePaths(exportedPaths)
// The apex needs to export some files so create a ninja rule to unpack the apex and check that // The apex needs to export some files so create a ninja rule to unpack the apex and check that

View File

@ -553,8 +553,7 @@ func createDeapexerModuleIfNeeded(ctx android.TopDownMutatorContext, deapexerNam
// Compute the deapexer properties from the transitive dependencies of this module. // Compute the deapexer properties from the transitive dependencies of this module.
commonModules := []string{} commonModules := []string{}
exportedFilesByKey := map[string]string{} exportedFiles := []string{}
requiringModulesByKey := map[string]android.Module{}
ctx.WalkDeps(func(child, parent android.Module) bool { ctx.WalkDeps(func(child, parent android.Module) bool {
tag := ctx.OtherModuleDependencyTag(child) tag := ctx.OtherModuleDependencyTag(child)
@ -568,16 +567,7 @@ func createDeapexerModuleIfNeeded(ctx android.TopDownMutatorContext, deapexerNam
commonModules = append(commonModules, name) commonModules = append(commonModules, name)
requiredFiles := child.(android.RequiredFilesFromPrebuiltApex).RequiredFilesFromPrebuiltApex(ctx) requiredFiles := child.(android.RequiredFilesFromPrebuiltApex).RequiredFilesFromPrebuiltApex(ctx)
for k, v := range requiredFiles { exportedFiles = append(exportedFiles, requiredFiles...)
if f, ok := exportedFilesByKey[k]; ok && f != v {
otherModule := requiringModulesByKey[k]
ctx.ModuleErrorf("inconsistent paths have been requested for key %q, %s requires path %s while %s requires path %s",
k, child, v, otherModule, f)
continue
}
exportedFilesByKey[k] = v
requiringModulesByKey[k] = child
}
// Visit the dependencies of this module just in case they also require files from the // Visit the dependencies of this module just in case they also require files from the
// prebuilt apex. // prebuilt apex.
@ -595,12 +585,7 @@ func createDeapexerModuleIfNeeded(ctx android.TopDownMutatorContext, deapexerNam
} }
// Populate the exported files property in a fixed order. // Populate the exported files property in a fixed order.
for _, tag := range android.SortedStringKeys(exportedFilesByKey) { deapexerProperties.ExportedFiles = android.SortedUniqueStrings(exportedFiles)
deapexerProperties.ExportedFiles = append(deapexerProperties.ExportedFiles, DeapexerExportedFile{
Tag: tag,
Path: exportedFilesByKey[tag],
})
}
props := struct { props := struct {
Name *string Name *string

View File

@ -930,13 +930,12 @@ func (module *prebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx and
} }
di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo) di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo)
name := module.BaseModuleName()
for _, variant := range imageConfig.apexVariants() { for _, variant := range imageConfig.apexVariants() {
arch := variant.target.Arch.ArchType arch := variant.target.Arch.ArchType
for _, toPath := range variant.imagesDeps { for _, toPath := range variant.imagesDeps {
apexRelativePath := apexRootRelativePathToBootImageFile(arch, toPath.Base())
// Get the path to the file that the deapexer extracted from the prebuilt apex file. // Get the path to the file that the deapexer extracted from the prebuilt apex file.
tag := createBootImageTag(arch, toPath.Base()) fromPath := di.PrebuiltExportPath(apexRelativePath)
fromPath := di.PrebuiltExportPath(name, tag)
// Copy the file to the predefined location. // Copy the file to the predefined location.
ctx.Build(pctx, android.BuildParams{ ctx.Build(pctx, android.BuildParams{
@ -967,19 +966,16 @@ func createBootImageTag(arch android.ArchType, baseName string) string {
// //
// If there is no image config associated with this fragment then it returns nil. Otherwise, it // If there is no image config associated with this fragment then it returns nil. Otherwise, it
// returns the files that are listed in the image config. // returns the files that are listed in the image config.
func (module *prebuiltBootclasspathFragmentModule) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) map[string]string { func (module *prebuiltBootclasspathFragmentModule) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string {
imageConfig := module.getImageConfig(ctx) imageConfig := module.getImageConfig(ctx)
if imageConfig != nil { if imageConfig != nil {
// Add the boot image files, e.g. .art, .oat and .vdex files. // Add the boot image files, e.g. .art, .oat and .vdex files.
files := map[string]string{} files := []string{}
name := module.BaseModuleName()
for _, variant := range imageConfig.apexVariants() { for _, variant := range imageConfig.apexVariants() {
arch := variant.target.Arch.ArchType arch := variant.target.Arch.ArchType
for _, path := range variant.imagesDeps.Paths() { for _, path := range variant.imagesDeps.Paths() {
base := path.Base() base := path.Base()
tag := createBootImageTag(arch, base) files = append(files, apexRootRelativePathToBootImageFile(arch, base))
key := fmt.Sprintf("%s{%s}", name, tag)
files[key] = filepath.Join("javalib", arch.String(), base)
} }
} }
return files return files
@ -987,6 +983,10 @@ func (module *prebuiltBootclasspathFragmentModule) RequiredFilesFromPrebuiltApex
return nil return nil
} }
func apexRootRelativePathToBootImageFile(arch android.ArchType, base string) string {
return filepath.Join("javalib", arch.String(), base)
}
var _ android.RequiredFilesFromPrebuiltApex = (*prebuiltBootclasspathFragmentModule)(nil) var _ android.RequiredFilesFromPrebuiltApex = (*prebuiltBootclasspathFragmentModule)(nil)
func prebuiltBootclasspathFragmentFactory() android.Module { func prebuiltBootclasspathFragmentFactory() android.Module {

View File

@ -1309,7 +1309,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Get the path of the dex implementation jar from the `deapexer` module. // Get the path of the dex implementation jar from the `deapexer` module.
di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo) di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo)
if dexOutputPath := di.PrebuiltExportPath(j.BaseModuleName(), ".dexjar"); dexOutputPath != nil { if dexOutputPath := di.PrebuiltExportPath(apexRootRelativePathToJavaLib(j.BaseModuleName())); dexOutputPath != nil {
j.dexJarFile = dexOutputPath j.dexJarFile = dexOutputPath
// Initialize the hiddenapi structure. // Initialize the hiddenapi structure.
@ -1429,17 +1429,22 @@ func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
// requiredFilesFromPrebuiltApexForImport returns information about the files that a java_import or // requiredFilesFromPrebuiltApexForImport returns information about the files that a java_import or
// java_sdk_library_import with the specified base module name requires to be exported from a // java_sdk_library_import with the specified base module name requires to be exported from a
// prebuilt_apex/apex_set. // prebuilt_apex/apex_set.
func requiredFilesFromPrebuiltApexForImport(name string) map[string]string { func requiredFilesFromPrebuiltApexForImport(name string) []string {
// Add the dex implementation jar to the set of exported files. The path here must match the // Add the dex implementation jar to the set of exported files.
// path of the file in the APEX created by apexFileForJavaModule(...). return []string{
return map[string]string{ apexRootRelativePathToJavaLib(name),
name + "{.dexjar}": filepath.Join("javalib", name+".jar"),
} }
} }
// 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 {
return filepath.Join("javalib", name+".jar")
}
var _ android.RequiredFilesFromPrebuiltApex = (*Import)(nil) var _ android.RequiredFilesFromPrebuiltApex = (*Import)(nil)
func (j *Import) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) map[string]string { func (j *Import) RequiredFilesFromPrebuiltApex(_ android.BaseModuleContext) []string {
name := j.BaseModuleName() name := j.BaseModuleName()
return requiredFilesFromPrebuiltApexForImport(name) return requiredFilesFromPrebuiltApexForImport(name)
} }

View File

@ -2140,7 +2140,7 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo
// Get the path of the dex implementation jar from the `deapexer` module. // Get the path of the dex implementation jar from the `deapexer` module.
di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo) di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo)
if dexOutputPath := di.PrebuiltExportPath(module.BaseModuleName(), ".dexjar"); dexOutputPath != nil { if dexOutputPath := di.PrebuiltExportPath(apexRootRelativePathToJavaLib(module.BaseModuleName())); dexOutputPath != nil {
module.dexJarFile = dexOutputPath module.dexJarFile = dexOutputPath
module.initHiddenAPI(ctx, dexOutputPath, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil) module.initHiddenAPI(ctx, dexOutputPath, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil)
} else { } else {
@ -2267,7 +2267,7 @@ func (module *SdkLibraryImport) ImplementationAndResourcesJars() android.Paths {
var _ android.RequiredFilesFromPrebuiltApex = (*SdkLibraryImport)(nil) var _ android.RequiredFilesFromPrebuiltApex = (*SdkLibraryImport)(nil)
func (module *SdkLibraryImport) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) map[string]string { func (module *SdkLibraryImport) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string {
name := module.BaseModuleName() name := module.BaseModuleName()
return requiredFilesFromPrebuiltApexForImport(name) return requiredFilesFromPrebuiltApexForImport(name)
} }