Create a singleton all_apex_contributions module type
This will be a container for the the apex_contributions
selected using build flags. This module will be used to query the state of
selected apex contributions instead of a global that can be mutated by
anyone.
It will set a provider containing metadata for source vs prebuilts
selection. To reduce the overhead of a new mutator, this will be done in
the existing `prebuilt_select` mutator.
It will validate that there are no dups (`foo` and `prebuilt_foo` cannot
be both selected)
Bug: 308174923
Test: go test ./android
Change-Id: Ie42999a71f35d70e0e977f5ab07ce451608d9f35
diff --git a/android/apex_contributions.go b/android/apex_contributions.go
index a28ac31..6eaca8b 100644
--- a/android/apex_contributions.go
+++ b/android/apex_contributions.go
@@ -15,6 +15,7 @@
package android
import (
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -24,6 +25,7 @@
func RegisterApexContributionsBuildComponents(ctx RegistrationContext) {
ctx.RegisterModuleType("apex_contributions", apexContributionsFactory)
+ ctx.RegisterSingletonModuleType("all_apex_contributions", allApexContributionsFactory)
}
type apexContributions struct {
@@ -65,3 +67,109 @@
// prebuilts selection.
func (m *apexContributions) GenerateAndroidBuildActions(ctx ModuleContext) {
}
+
+// A container for apex_contributions.
+// Based on product_config, it will create a dependency on the selected
+// apex_contributions per mainline module
+type allApexContributions struct {
+ SingletonModuleBase
+}
+
+func allApexContributionsFactory() SingletonModule {
+ module := &allApexContributions{}
+ InitAndroidModule(module)
+ return module
+}
+
+type apexContributionsDepTag struct {
+ blueprint.BaseDependencyTag
+}
+
+var (
+ acDepTag = apexContributionsDepTag{}
+)
+
+// Creates a dep to each selected apex_contributions
+func (a *allApexContributions) DepsMutator(ctx BottomUpMutatorContext) {
+ ctx.AddDependency(ctx.Module(), acDepTag, ctx.Config().AllApexContributions()...)
+}
+
+// Set PrebuiltSelectionInfoProvider in post deps phase
+func (a *allApexContributions) SetPrebuiltSelectionInfoProvider(ctx BaseModuleContext) {
+ addContentsToProvider := func(p *PrebuiltSelectionInfoMap, m *apexContributions) {
+ for _, content := range m.Contents() {
+ if !ctx.OtherModuleExists(content) {
+ ctx.ModuleErrorf("%s listed in apex_contributions %s does not exist\n", content, m.Name())
+ }
+ pi := &PrebuiltSelectionInfo{
+ baseModuleName: RemoveOptionalPrebuiltPrefix(content),
+ selectedModuleName: content,
+ metadataModuleName: m.Name(),
+ apiDomain: m.ApiDomain(),
+ }
+ p.Add(ctx, pi)
+ }
+ }
+
+ if ctx.Config().Bp2buildMode() { // Skip bp2build
+ return
+ }
+ p := PrebuiltSelectionInfoMap{}
+ ctx.VisitDirectDepsWithTag(acDepTag, func(child Module) {
+ if m, ok := child.(*apexContributions); ok {
+ addContentsToProvider(&p, m)
+ } else {
+ ctx.ModuleErrorf("%s is not an apex_contributions module\n", child.Name())
+ }
+ })
+ ctx.SetProvider(PrebuiltSelectionInfoProvider, p)
+}
+
+// A provider containing metadata about whether source or prebuilt should be used
+// This provider will be used in prebuilt_select mutator to redirect deps
+var PrebuiltSelectionInfoProvider = blueprint.NewMutatorProvider(PrebuiltSelectionInfoMap{}, "prebuilt_select")
+
+// Map of baseModuleName to the selected source or prebuilt
+type PrebuiltSelectionInfoMap map[string]PrebuiltSelectionInfo
+
+// Add a new entry to the map with some validations
+func (pm *PrebuiltSelectionInfoMap) Add(ctx BaseModuleContext, p *PrebuiltSelectionInfo) {
+ if p == nil {
+ return
+ }
+ // Do not allow dups. If the base module (without the prebuilt_) has been added before, raise an exception.
+ if old, exists := (*pm)[p.baseModuleName]; exists {
+ ctx.ModuleErrorf("Cannot use Soong module: %s from apex_contributions: %s because it has been added previously as: %s from apex_contributions: %s\n",
+ p.selectedModuleName, p.metadataModuleName, old.selectedModuleName, old.metadataModuleName,
+ )
+ }
+ (*pm)[p.baseModuleName] = *p
+}
+
+type PrebuiltSelectionInfo struct {
+ // e.g. libc
+ baseModuleName string
+ // e.g. (libc|prebuilt_libc)
+ selectedModuleName string
+ // Name of the apex_contributions module
+ metadataModuleName string
+ // e.g. com.android.runtime
+ apiDomain string
+}
+
+// Returns true if `name` is explicitly requested using one of the selected
+// apex_contributions metadata modules.
+func (p *PrebuiltSelectionInfoMap) IsSelected(baseModuleName, name string) bool {
+ if i, exists := (*p)[baseModuleName]; exists {
+ return i.selectedModuleName == name
+ } else {
+ return false
+ }
+}
+
+// This module type does not have any build actions.
+func (a *allApexContributions) GenerateAndroidBuildActions(ctx ModuleContext) {
+}
+
+func (a *allApexContributions) GenerateSingletonBuildActions(ctx SingletonContext) {
+}