1// Copyright 2023 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package android 16 17import ( 18 "github.com/google/blueprint" 19 "github.com/google/blueprint/proptools" 20) 21 22func init() { 23 RegisterApexContributionsBuildComponents(InitRegistrationContext) 24} 25 26func RegisterApexContributionsBuildComponents(ctx RegistrationContext) { 27 ctx.RegisterModuleType("apex_contributions", apexContributionsFactory) 28 ctx.RegisterModuleType("apex_contributions_defaults", apexContributionsDefaultsFactory) 29 ctx.RegisterSingletonModuleType("all_apex_contributions", allApexContributionsFactory) 30} 31 32type apexContributions struct { 33 ModuleBase 34 DefaultableModuleBase 35 properties contributionProps 36} 37 38type contributionProps struct { 39 // Name of the mainline module 40 Api_domain *string 41 // A list of module names that should be used when this contribution 42 // is selected via product_config 43 // The name should be explicit (foo or prebuilt_foo) 44 Contents []string 45} 46 47func (m *apexContributions) ApiDomain() string { 48 return proptools.String(m.properties.Api_domain) 49} 50 51func (m *apexContributions) Contents() []string { 52 return m.properties.Contents 53} 54 55// apex_contributions contains a list of module names (source or 56// prebuilt) belonging to the mainline module 57// An apex can have multiple apex_contributions modules 58// with different combinations of source or prebuilts, but only one can be 59// selected via product_config. 60func apexContributionsFactory() Module { 61 module := &apexContributions{} 62 module.AddProperties(&module.properties) 63 InitAndroidModule(module) 64 InitDefaultableModule(module) 65 return module 66} 67 68// This module type does not have any build actions. 69// It provides metadata that is used in post-deps mutator phase for source vs 70// prebuilts selection. 71func (m *apexContributions) GenerateAndroidBuildActions(ctx ModuleContext) { 72} 73 74type apexContributionsDefaults struct { 75 ModuleBase 76 DefaultsModuleBase 77} 78 79func apexContributionsDefaultsFactory() Module { 80 module := &apexContributionsDefaults{} 81 module.AddProperties(&contributionProps{}) 82 InitDefaultsModule(module) 83 return module 84} 85 86// A container for apex_contributions. 87// Based on product_config, it will create a dependency on the selected 88// apex_contributions per mainline module 89type allApexContributions struct { 90 SingletonModuleBase 91} 92 93func allApexContributionsFactory() SingletonModule { 94 module := &allApexContributions{} 95 InitAndroidModule(module) 96 return module 97} 98 99type apexContributionsDepTag struct { 100 blueprint.BaseDependencyTag 101} 102 103var ( 104 AcDepTag = apexContributionsDepTag{} 105) 106 107// Creates a dep to each selected apex_contributions 108func (a *allApexContributions) DepsMutator(ctx BottomUpMutatorContext) { 109 // Skip apex_contributions if BuildApexContributionContents is true 110 // This product config var allows some products in the same family to use mainline modules from source 111 // (e.g. shiba and shiba_fullmte) 112 // Eventually these product variants will have their own release config maps. 113 if !proptools.Bool(ctx.Config().BuildIgnoreApexContributionContents()) { 114 ctx.AddDependency(ctx.Module(), AcDepTag, ctx.Config().AllApexContributions()...) 115 } 116} 117 118// Set PrebuiltSelectionInfoProvider in post deps phase 119func (a *allApexContributions) SetPrebuiltSelectionInfoProvider(ctx BaseModuleContext) { 120 addContentsToProvider := func(p *PrebuiltSelectionInfoMap, m *apexContributions) { 121 for _, content := range m.Contents() { 122 // Verify that the module listed in contents exists in the tree 123 // Remove the prebuilt_ prefix to account for partner worksapces where the source module does not 124 // exist, and PrebuiltRenameMutator renames `prebuilt_foo` to `foo` 125 if !ctx.OtherModuleExists(content) && !ctx.OtherModuleExists(RemoveOptionalPrebuiltPrefix(content)) && !ctx.Config().AllowMissingDependencies() { 126 ctx.ModuleErrorf("%s listed in apex_contributions %s does not exist\n", content, m.Name()) 127 } 128 pi := &PrebuiltSelectionInfo{ 129 selectedModuleName: content, 130 metadataModuleName: m.Name(), 131 apiDomain: m.ApiDomain(), 132 } 133 p.Add(ctx, pi) 134 } 135 } 136 137 p := PrebuiltSelectionInfoMap{} 138 ctx.VisitDirectDepsWithTag(AcDepTag, func(child Module) { 139 if m, ok := child.(*apexContributions); ok { 140 addContentsToProvider(&p, m) 141 } else { 142 ctx.ModuleErrorf("%s is not an apex_contributions module\n", child.Name()) 143 } 144 }) 145 SetProvider(ctx, PrebuiltSelectionInfoProvider, p) 146} 147 148// A provider containing metadata about whether source or prebuilt should be used 149// This provider will be used in prebuilt_select mutator to redirect deps 150var PrebuiltSelectionInfoProvider = blueprint.NewMutatorProvider[PrebuiltSelectionInfoMap]("prebuilt_select") 151 152// Map of selected module names to a metadata object 153// The metadata contains information about the api_domain of the selected module 154type PrebuiltSelectionInfoMap map[string]PrebuiltSelectionInfo 155 156// Add a new entry to the map with some validations 157func (pm *PrebuiltSelectionInfoMap) Add(ctx BaseModuleContext, p *PrebuiltSelectionInfo) { 158 if p == nil { 159 return 160 } 161 (*pm)[p.selectedModuleName] = *p 162} 163 164type PrebuiltSelectionInfo struct { 165 // e.g. (libc|prebuilt_libc) 166 selectedModuleName string 167 // Name of the apex_contributions module 168 metadataModuleName string 169 // e.g. com.android.runtime 170 apiDomain string 171} 172 173// Returns true if `name` is explicitly requested using one of the selected 174// apex_contributions metadata modules. 175func (p *PrebuiltSelectionInfoMap) IsSelected(name string) bool { 176 _, exists := (*p)[name] 177 return exists 178} 179 180// Return the list of soong modules selected for this api domain 181// In the case of apexes, it is the canonical name of the apex on device (/apex/<apex_name>) 182func (p *PrebuiltSelectionInfoMap) GetSelectedModulesForApiDomain(apiDomain string) []string { 183 selected := []string{} 184 for _, entry := range *p { 185 if entry.apiDomain == apiDomain { 186 selected = append(selected, entry.selectedModuleName) 187 } 188 } 189 return selected 190} 191 192// This module type does not have any build actions. 193func (a *allApexContributions) GenerateAndroidBuildActions(ctx ModuleContext) { 194} 195 196func (a *allApexContributions) GenerateSingletonBuildActions(ctx SingletonContext) { 197} 198