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