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