xref: /aosp_15_r20/build/soong/aconfig/aconfig_value_set.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
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