Move deapexer related functionality to prebuiltCommon

Refactoring in preparation for adding deapexer support to apex_set.

Bug: 181267622
Test: m droid
Change-Id: I8e7661ff4cfbe68f62e14d3bdf20d9356934e351
This commit is contained in:
Paul Duffin 2021-04-06 17:02:08 +01:00
parent 440b234081
commit dfd3326b65
1 changed files with 98 additions and 88 deletions

View File

@ -48,6 +48,9 @@ type prebuilt interface {
type prebuiltCommon struct {
prebuilt android.Prebuilt
properties prebuiltCommonProperties
deapexerProperties DeapexerProperties
selectedApexProperties SelectedApexProperties
}
type sanitizedPrebuilt interface {
@ -91,6 +94,96 @@ func (p *prebuiltCommon) checkForceDisable(ctx android.ModuleContext) bool {
return false
}
func (p *prebuiltCommon) deapexerDeps(ctx android.BottomUpMutatorContext) {
// Add dependencies onto the java modules that represent the java libraries that are provided by
// and exported from this prebuilt apex.
for _, lib := range p.deapexerProperties.Exported_java_libs {
dep := prebuiltApexExportedModuleName(ctx, lib)
ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), exportedJavaLibTag, dep)
}
}
// apexInfoMutator marks any modules for which this apex exports a file as requiring an apex
// specific variant and checks that they are supported.
//
// The apexMutator will ensure that the ApexInfo objects passed to BuildForApex(ApexInfo) are
// associated with the apex specific variant using the ApexInfoProvider for later retrieval.
//
// Unlike the source apex module type the prebuilt_apex module type cannot share compatible variants
// across prebuilt_apex modules. That is because there is no way to determine whether two
// prebuilt_apex modules that export files for the same module are compatible. e.g. they could have
// been built from different source at different times or they could have been built with different
// build options that affect the libraries.
//
// While it may be possible to provide sufficient information to determine whether two prebuilt_apex
// modules were compatible it would be a lot of work and would not provide much benefit for a couple
// of reasons:
// * The number of prebuilt_apex modules that will be exporting files for the same module will be
// low as the prebuilt_apex only exports files for the direct dependencies that require it and
// very few modules are direct dependencies of multiple prebuilt_apex modules, e.g. there are a
// few com.android.art* apex files that contain the same contents and could export files for the
// same modules but only one of them needs to do so. Contrast that with source apex modules which
// need apex specific variants for every module that contributes code to the apex, whether direct
// or indirect.
// * The build cost of a prebuilt_apex variant is generally low as at worst it will involve some
// extra copying of files. Contrast that with source apex modules that has to build each variant
// from source.
func (p *prebuiltCommon) apexInfoMutator(mctx android.TopDownMutatorContext) {
// Collect direct dependencies into contents.
contents := make(map[string]android.ApexMembership)
// Collect the list of dependencies.
var dependencies []android.ApexModule
mctx.VisitDirectDeps(func(m android.Module) {
tag := mctx.OtherModuleDependencyTag(m)
if tag == exportedJavaLibTag {
depName := mctx.OtherModuleName(m)
// It is an error if the other module is not a prebuilt.
if _, ok := m.(android.PrebuiltInterface); !ok {
mctx.PropertyErrorf("exported_java_libs", "%q is not a prebuilt module", depName)
return
}
// It is an error if the other module is not an ApexModule.
if _, ok := m.(android.ApexModule); !ok {
mctx.PropertyErrorf("exported_java_libs", "%q is not usable within an apex", depName)
return
}
// Strip off the prebuilt_ prefix if present before storing content to ensure consistent
// behavior whether there is a corresponding source module present or not.
depName = android.RemoveOptionalPrebuiltPrefix(depName)
// Remember that this module was added as a direct dependency.
contents[depName] = contents[depName].Add(true)
// Add the module to the list of dependencies that need to have an APEX variant.
dependencies = append(dependencies, m.(android.ApexModule))
}
})
// Create contents for the prebuilt_apex and store it away for later use.
apexContents := android.NewApexContents(contents)
mctx.SetProvider(ApexBundleInfoProvider, ApexBundleInfo{
Contents: apexContents,
})
// Create an ApexInfo for the prebuilt_apex.
apexInfo := android.ApexInfo{
ApexVariationName: mctx.ModuleName(),
InApexes: []string{mctx.ModuleName()},
ApexContents: []*android.ApexContents{apexContents},
ForPrebuiltApex: true,
}
// Mark the dependencies of this module as requiring a variant for this module.
for _, am := range dependencies {
am.BuildForApex(apexInfo)
}
}
// prebuiltApexSelectorModule is a private module type that is only created by the prebuilt_apex
// module. It selects the apex to use and makes it available for use by prebuilt_apex and the
// deapexer.
@ -197,7 +290,6 @@ func (p *ApexFileProperties) prebuiltApexSelector(ctx android.BaseModuleContext,
type PrebuiltProperties struct {
ApexFileProperties
DeapexerProperties
Installable *bool
// Optional name for the installed apex. If unspecified, name of the
@ -267,7 +359,7 @@ func (p *Prebuilt) Name() string {
//
func PrebuiltFactory() android.Module {
module := &Prebuilt{}
module.AddProperties(&module.properties, &module.selectedApexProperties)
module.AddProperties(&module.properties, &module.deapexerProperties, &module.selectedApexProperties)
android.InitSingleSourcePrebuiltModule(module, &module.selectedApexProperties, "Selected_apex")
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
@ -278,8 +370,8 @@ func PrebuiltFactory() android.Module {
createApexSelectorModule(ctx, apexSelectorModuleName, &module.properties.ApexFileProperties)
apexFileSource := ":" + apexSelectorModuleName
if len(module.properties.Exported_java_libs) != 0 {
createDeapexerModule(ctx, deapexerModuleName(baseModuleName), apexFileSource, &module.properties.DeapexerProperties)
if len(module.deapexerProperties.Exported_java_libs) != 0 {
createDeapexerModule(ctx, deapexerModuleName(baseModuleName), apexFileSource, &module.deapexerProperties)
}
// Add a source reference to retrieve the selected apex from the selector module.
@ -363,95 +455,13 @@ var (
)
func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {
// Add dependencies onto the java modules that represent the java libraries that are provided by
// and exported from this prebuilt apex.
for _, lib := range p.properties.Exported_java_libs {
dep := prebuiltApexExportedModuleName(ctx, lib)
ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), exportedJavaLibTag, dep)
}
p.deapexerDeps(ctx)
}
var _ ApexInfoMutator = (*Prebuilt)(nil)
// ApexInfoMutator marks any modules for which this apex exports a file as requiring an apex
// specific variant and checks that they are supported.
//
// The apexMutator will ensure that the ApexInfo objects passed to BuildForApex(ApexInfo) are
// associated with the apex specific variant using the ApexInfoProvider for later retrieval.
//
// Unlike the source apex module type the prebuilt_apex module type cannot share compatible variants
// across prebuilt_apex modules. That is because there is no way to determine whether two
// prebuilt_apex modules that export files for the same module are compatible. e.g. they could have
// been built from different source at different times or they could have been built with different
// build options that affect the libraries.
//
// While it may be possible to provide sufficient information to determine whether two prebuilt_apex
// modules were compatible it would be a lot of work and would not provide much benefit for a couple
// of reasons:
// * The number of prebuilt_apex modules that will be exporting files for the same module will be
// low as the prebuilt_apex only exports files for the direct dependencies that require it and
// very few modules are direct dependencies of multiple prebuilt_apex modules, e.g. there are a
// few com.android.art* apex files that contain the same contents and could export files for the
// same modules but only one of them needs to do so. Contrast that with source apex modules which
// need apex specific variants for every module that contributes code to the apex, whether direct
// or indirect.
// * The build cost of a prebuilt_apex variant is generally low as at worst it will involve some
// extra copying of files. Contrast that with source apex modules that has to build each variant
// from source.
func (p *Prebuilt) ApexInfoMutator(mctx android.TopDownMutatorContext) {
// Collect direct dependencies into contents.
contents := make(map[string]android.ApexMembership)
// Collect the list of dependencies.
var dependencies []android.ApexModule
mctx.VisitDirectDeps(func(m android.Module) {
tag := mctx.OtherModuleDependencyTag(m)
if tag == exportedJavaLibTag {
depName := mctx.OtherModuleName(m)
// It is an error if the other module is not a prebuilt.
if _, ok := m.(android.PrebuiltInterface); !ok {
mctx.PropertyErrorf("exported_java_libs", "%q is not a prebuilt module", depName)
return
}
// It is an error if the other module is not an ApexModule.
if _, ok := m.(android.ApexModule); !ok {
mctx.PropertyErrorf("exported_java_libs", "%q is not usable within an apex", depName)
return
}
// Strip off the prebuilt_ prefix if present before storing content to ensure consistent
// behavior whether there is a corresponding source module present or not.
depName = android.RemoveOptionalPrebuiltPrefix(depName)
// Remember that this module was added as a direct dependency.
contents[depName] = contents[depName].Add(true)
// Add the module to the list of dependencies that need to have an APEX variant.
dependencies = append(dependencies, m.(android.ApexModule))
}
})
// Create contents for the prebuilt_apex and store it away for later use.
apexContents := android.NewApexContents(contents)
mctx.SetProvider(ApexBundleInfoProvider, ApexBundleInfo{
Contents: apexContents,
})
// Create an ApexInfo for the prebuilt_apex.
apexInfo := android.ApexInfo{
ApexVariationName: mctx.ModuleName(),
InApexes: []string{mctx.ModuleName()},
ApexContents: []*android.ApexContents{apexContents},
ForPrebuiltApex: true,
}
// Mark the dependencies of this module as requiring a variant for this module.
for _, am := range dependencies {
am.BuildForApex(apexInfo)
}
p.apexInfoMutator(mctx)
}
func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {