diff --git a/apex/prebuilt.go b/apex/prebuilt.go index 9d84281cb..3893a2bcd 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -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) {