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 aconfig 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "android/soong/android" 19*333d2b36SAndroid Build Coastguard Worker "fmt" 20*333d2b36SAndroid Build Coastguard Worker "strings" 21*333d2b36SAndroid Build Coastguard Worker 22*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint" 23*333d2b36SAndroid Build Coastguard Worker) 24*333d2b36SAndroid Build Coastguard Worker 25*333d2b36SAndroid Build Coastguard Worker// Properties for "aconfig_value_set" 26*333d2b36SAndroid Build Coastguard Workertype ValueSetModule struct { 27*333d2b36SAndroid Build Coastguard Worker android.ModuleBase 28*333d2b36SAndroid Build Coastguard Worker android.DefaultableModuleBase 29*333d2b36SAndroid Build Coastguard Worker 30*333d2b36SAndroid Build Coastguard Worker properties struct { 31*333d2b36SAndroid Build Coastguard Worker // aconfig_values modules 32*333d2b36SAndroid Build Coastguard Worker Values []string 33*333d2b36SAndroid Build Coastguard Worker 34*333d2b36SAndroid Build Coastguard Worker // Paths to the Android.bp files where the aconfig_values modules are defined. 35*333d2b36SAndroid Build Coastguard Worker Srcs []string 36*333d2b36SAndroid Build Coastguard Worker } 37*333d2b36SAndroid Build Coastguard Worker} 38*333d2b36SAndroid Build Coastguard Worker 39*333d2b36SAndroid Build Coastguard Workerfunc ValueSetFactory() android.Module { 40*333d2b36SAndroid Build Coastguard Worker module := &ValueSetModule{} 41*333d2b36SAndroid Build Coastguard Worker 42*333d2b36SAndroid Build Coastguard Worker android.InitAndroidModule(module) 43*333d2b36SAndroid Build Coastguard Worker android.InitDefaultableModule(module) 44*333d2b36SAndroid Build Coastguard Worker module.AddProperties(&module.properties) 45*333d2b36SAndroid Build Coastguard Worker 46*333d2b36SAndroid Build Coastguard Worker return module 47*333d2b36SAndroid Build Coastguard Worker} 48*333d2b36SAndroid Build Coastguard Worker 49*333d2b36SAndroid Build Coastguard Worker// Dependency tag for values property 50*333d2b36SAndroid Build Coastguard Workertype valueSetType struct { 51*333d2b36SAndroid Build Coastguard Worker blueprint.BaseDependencyTag 52*333d2b36SAndroid Build Coastguard Worker} 53*333d2b36SAndroid Build Coastguard Worker 54*333d2b36SAndroid Build Coastguard Workervar valueSetTag = valueSetType{} 55*333d2b36SAndroid Build Coastguard Worker 56*333d2b36SAndroid Build Coastguard Worker// Provider published by aconfig_value_set 57*333d2b36SAndroid Build Coastguard Workertype valueSetProviderData struct { 58*333d2b36SAndroid Build Coastguard Worker // The package of each of the 59*333d2b36SAndroid Build Coastguard Worker // (map of package --> aconfig_module) 60*333d2b36SAndroid Build Coastguard Worker AvailablePackages map[string]android.Paths 61*333d2b36SAndroid Build Coastguard Worker} 62*333d2b36SAndroid Build Coastguard Worker 63*333d2b36SAndroid Build Coastguard Workervar valueSetProviderKey = blueprint.NewProvider[valueSetProviderData]() 64*333d2b36SAndroid Build Coastguard Worker 65*333d2b36SAndroid Build Coastguard Workerfunc (module *ValueSetModule) FindAconfigValuesFromSrc(ctx android.BottomUpMutatorContext) map[string]android.Path { 66*333d2b36SAndroid Build Coastguard Worker moduleDir := ctx.ModuleDir() 67*333d2b36SAndroid Build Coastguard Worker srcs := android.PathsForModuleSrcExcludes(ctx, module.properties.Srcs, []string{ctx.BlueprintsFile()}) 68*333d2b36SAndroid Build Coastguard Worker 69*333d2b36SAndroid Build Coastguard Worker aconfigValuesPrefix := strings.Replace(module.Name(), "aconfig_value_set", "aconfig-values", 1) 70*333d2b36SAndroid Build Coastguard Worker moduleNamesSrcMap := make(map[string]android.Path) 71*333d2b36SAndroid Build Coastguard Worker for _, src := range srcs { 72*333d2b36SAndroid Build Coastguard Worker subDir := strings.TrimPrefix(src.String(), moduleDir+"/") 73*333d2b36SAndroid Build Coastguard Worker packageName, _, found := strings.Cut(subDir, "/") 74*333d2b36SAndroid Build Coastguard Worker if found { 75*333d2b36SAndroid Build Coastguard Worker moduleName := fmt.Sprintf("%s-%s-all", aconfigValuesPrefix, packageName) 76*333d2b36SAndroid Build Coastguard Worker moduleNamesSrcMap[moduleName] = src 77*333d2b36SAndroid Build Coastguard Worker } 78*333d2b36SAndroid Build Coastguard Worker } 79*333d2b36SAndroid Build Coastguard Worker return moduleNamesSrcMap 80*333d2b36SAndroid Build Coastguard Worker} 81*333d2b36SAndroid Build Coastguard Worker 82*333d2b36SAndroid Build Coastguard Workerfunc (module *ValueSetModule) DepsMutator(ctx android.BottomUpMutatorContext) { 83*333d2b36SAndroid Build Coastguard Worker 84*333d2b36SAndroid Build Coastguard Worker // TODO: b/366285733 - Replace the file path based solution with more robust solution. 85*333d2b36SAndroid Build Coastguard Worker aconfigValuesMap := module.FindAconfigValuesFromSrc(ctx) 86*333d2b36SAndroid Build Coastguard Worker for _, moduleName := range android.SortedKeys(aconfigValuesMap) { 87*333d2b36SAndroid Build Coastguard Worker if ctx.OtherModuleExists(moduleName) { 88*333d2b36SAndroid Build Coastguard Worker ctx.AddDependency(ctx.Module(), valueSetTag, moduleName) 89*333d2b36SAndroid Build Coastguard Worker } else { 90*333d2b36SAndroid Build Coastguard Worker ctx.ModuleErrorf("module %q not found. Rename the aconfig_values module defined in %q to %q", moduleName, aconfigValuesMap[moduleName], moduleName) 91*333d2b36SAndroid Build Coastguard Worker } 92*333d2b36SAndroid Build Coastguard Worker } 93*333d2b36SAndroid Build Coastguard Worker 94*333d2b36SAndroid Build Coastguard Worker deps := ctx.AddDependency(ctx.Module(), valueSetTag, module.properties.Values...) 95*333d2b36SAndroid Build Coastguard Worker for _, dep := range deps { 96*333d2b36SAndroid Build Coastguard Worker _, ok := dep.(*ValuesModule) 97*333d2b36SAndroid Build Coastguard Worker if !ok { 98*333d2b36SAndroid Build Coastguard Worker ctx.PropertyErrorf("values", "values must be a aconfig_values module") 99*333d2b36SAndroid Build Coastguard Worker return 100*333d2b36SAndroid Build Coastguard Worker } 101*333d2b36SAndroid Build Coastguard Worker } 102*333d2b36SAndroid Build Coastguard Worker} 103*333d2b36SAndroid Build Coastguard Worker 104*333d2b36SAndroid Build Coastguard Workerfunc (module *ValueSetModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 105*333d2b36SAndroid Build Coastguard Worker // Accumulate the packages of the values modules listed, and set that as an 106*333d2b36SAndroid Build Coastguard Worker // valueSetProviderKey provider that aconfig modules can read and use 107*333d2b36SAndroid Build Coastguard Worker // to append values to their aconfig actions. 108*333d2b36SAndroid Build Coastguard Worker packages := make(map[string]android.Paths) 109*333d2b36SAndroid Build Coastguard Worker ctx.VisitDirectDeps(func(dep android.Module) { 110*333d2b36SAndroid Build Coastguard Worker if depData, ok := android.OtherModuleProvider(ctx, dep, valuesProviderKey); ok { 111*333d2b36SAndroid Build Coastguard Worker srcs := make([]android.Path, len(depData.Values)) 112*333d2b36SAndroid Build Coastguard Worker copy(srcs, depData.Values) 113*333d2b36SAndroid Build Coastguard Worker packages[depData.Package] = srcs 114*333d2b36SAndroid Build Coastguard Worker } 115*333d2b36SAndroid Build Coastguard Worker 116*333d2b36SAndroid Build Coastguard Worker }) 117*333d2b36SAndroid Build Coastguard Worker android.SetProvider(ctx, valueSetProviderKey, valueSetProviderData{ 118*333d2b36SAndroid Build Coastguard Worker AvailablePackages: packages, 119*333d2b36SAndroid Build Coastguard Worker }) 120*333d2b36SAndroid Build Coastguard Worker} 121