xref: /aosp_15_r20/build/soong/aconfig/aconfig_declarations.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	"path/filepath"
20*333d2b36SAndroid Build Coastguard Worker	"slices"
21*333d2b36SAndroid Build Coastguard Worker	"strconv"
22*333d2b36SAndroid Build Coastguard Worker	"strings"
23*333d2b36SAndroid Build Coastguard Worker
24*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint"
25*333d2b36SAndroid Build Coastguard Worker)
26*333d2b36SAndroid Build Coastguard Worker
27*333d2b36SAndroid Build Coastguard Workertype AconfigReleaseConfigValue struct {
28*333d2b36SAndroid Build Coastguard Worker	ReleaseConfig string
29*333d2b36SAndroid Build Coastguard Worker	Values        []string `blueprint:"mutated"`
30*333d2b36SAndroid Build Coastguard Worker}
31*333d2b36SAndroid Build Coastguard Worker
32*333d2b36SAndroid Build Coastguard Workertype DeclarationsModule struct {
33*333d2b36SAndroid Build Coastguard Worker	android.ModuleBase
34*333d2b36SAndroid Build Coastguard Worker	android.DefaultableModuleBase
35*333d2b36SAndroid Build Coastguard Worker	blueprint.IncrementalModule
36*333d2b36SAndroid Build Coastguard Worker
37*333d2b36SAndroid Build Coastguard Worker	// Properties for "aconfig_declarations"
38*333d2b36SAndroid Build Coastguard Worker	properties struct {
39*333d2b36SAndroid Build Coastguard Worker		// aconfig files, relative to this Android.bp file
40*333d2b36SAndroid Build Coastguard Worker		Srcs []string `android:"path"`
41*333d2b36SAndroid Build Coastguard Worker
42*333d2b36SAndroid Build Coastguard Worker		// Release config flag package
43*333d2b36SAndroid Build Coastguard Worker		Package string
44*333d2b36SAndroid Build Coastguard Worker
45*333d2b36SAndroid Build Coastguard Worker		// Values for release configs / RELEASE_ACONFIG_VALUE_SETS
46*333d2b36SAndroid Build Coastguard Worker		// The current release config is `ReleaseConfig: ""`, others
47*333d2b36SAndroid Build Coastguard Worker		// are from RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS.
48*333d2b36SAndroid Build Coastguard Worker		ReleaseConfigValues []AconfigReleaseConfigValue
49*333d2b36SAndroid Build Coastguard Worker
50*333d2b36SAndroid Build Coastguard Worker		// Container(system/vendor/apex) that this module belongs to
51*333d2b36SAndroid Build Coastguard Worker		Container string
52*333d2b36SAndroid Build Coastguard Worker
53*333d2b36SAndroid Build Coastguard Worker		// The flags will only be repackaged if this prop is true.
54*333d2b36SAndroid Build Coastguard Worker		Exportable bool
55*333d2b36SAndroid Build Coastguard Worker	}
56*333d2b36SAndroid Build Coastguard Worker}
57*333d2b36SAndroid Build Coastguard Worker
58*333d2b36SAndroid Build Coastguard Workerfunc DeclarationsFactory() android.Module {
59*333d2b36SAndroid Build Coastguard Worker	module := &DeclarationsModule{}
60*333d2b36SAndroid Build Coastguard Worker
61*333d2b36SAndroid Build Coastguard Worker	android.InitAndroidModule(module)
62*333d2b36SAndroid Build Coastguard Worker	android.InitDefaultableModule(module)
63*333d2b36SAndroid Build Coastguard Worker	module.AddProperties(&module.properties)
64*333d2b36SAndroid Build Coastguard Worker
65*333d2b36SAndroid Build Coastguard Worker	return module
66*333d2b36SAndroid Build Coastguard Worker}
67*333d2b36SAndroid Build Coastguard Worker
68*333d2b36SAndroid Build Coastguard Workertype implicitValuesTagType struct {
69*333d2b36SAndroid Build Coastguard Worker	blueprint.BaseDependencyTag
70*333d2b36SAndroid Build Coastguard Worker
71*333d2b36SAndroid Build Coastguard Worker	// The release config name for these values.
72*333d2b36SAndroid Build Coastguard Worker	// Empty string for the actual current release config.
73*333d2b36SAndroid Build Coastguard Worker	ReleaseConfig string
74*333d2b36SAndroid Build Coastguard Worker}
75*333d2b36SAndroid Build Coastguard Worker
76*333d2b36SAndroid Build Coastguard Workervar implicitValuesTag = implicitValuesTagType{}
77*333d2b36SAndroid Build Coastguard Worker
78*333d2b36SAndroid Build Coastguard Workerfunc (module *DeclarationsModule) DepsMutator(ctx android.BottomUpMutatorContext) {
79*333d2b36SAndroid Build Coastguard Worker	// Validate Properties
80*333d2b36SAndroid Build Coastguard Worker	if len(module.properties.Srcs) == 0 {
81*333d2b36SAndroid Build Coastguard Worker		ctx.PropertyErrorf("srcs", "missing source files")
82*333d2b36SAndroid Build Coastguard Worker		return
83*333d2b36SAndroid Build Coastguard Worker	}
84*333d2b36SAndroid Build Coastguard Worker	if len(module.properties.Package) == 0 {
85*333d2b36SAndroid Build Coastguard Worker		ctx.PropertyErrorf("package", "missing package property")
86*333d2b36SAndroid Build Coastguard Worker	}
87*333d2b36SAndroid Build Coastguard Worker	if len(module.properties.Container) == 0 {
88*333d2b36SAndroid Build Coastguard Worker		ctx.PropertyErrorf("container", "missing container property")
89*333d2b36SAndroid Build Coastguard Worker	}
90*333d2b36SAndroid Build Coastguard Worker
91*333d2b36SAndroid Build Coastguard Worker	// treating system_ext as system partition as we are combining them as one container
92*333d2b36SAndroid Build Coastguard Worker	// TODO remove this logic once we start enforcing that system_ext cannot be specified as
93*333d2b36SAndroid Build Coastguard Worker	// container in the container field.
94*333d2b36SAndroid Build Coastguard Worker	if module.properties.Container == "system_ext" {
95*333d2b36SAndroid Build Coastguard Worker		module.properties.Container = "system"
96*333d2b36SAndroid Build Coastguard Worker	}
97*333d2b36SAndroid Build Coastguard Worker
98*333d2b36SAndroid Build Coastguard Worker	// Add a dependency on the aconfig_value_sets defined in
99*333d2b36SAndroid Build Coastguard Worker	// RELEASE_ACONFIG_VALUE_SETS, and add any aconfig_values that
100*333d2b36SAndroid Build Coastguard Worker	// match our package.
101*333d2b36SAndroid Build Coastguard Worker	valuesFromConfig := ctx.Config().ReleaseAconfigValueSets()
102*333d2b36SAndroid Build Coastguard Worker	if len(valuesFromConfig) > 0 {
103*333d2b36SAndroid Build Coastguard Worker		ctx.AddDependency(ctx.Module(), implicitValuesTag, valuesFromConfig...)
104*333d2b36SAndroid Build Coastguard Worker	}
105*333d2b36SAndroid Build Coastguard Worker	for rcName, valueSets := range ctx.Config().ReleaseAconfigExtraReleaseConfigsValueSets() {
106*333d2b36SAndroid Build Coastguard Worker		if len(valueSets) > 0 {
107*333d2b36SAndroid Build Coastguard Worker			ctx.AddDependency(ctx.Module(), implicitValuesTagType{ReleaseConfig: rcName}, valueSets...)
108*333d2b36SAndroid Build Coastguard Worker		}
109*333d2b36SAndroid Build Coastguard Worker	}
110*333d2b36SAndroid Build Coastguard Worker}
111*333d2b36SAndroid Build Coastguard Worker
112*333d2b36SAndroid Build Coastguard Workerfunc joinAndPrefix(prefix string, values []string) string {
113*333d2b36SAndroid Build Coastguard Worker	var sb strings.Builder
114*333d2b36SAndroid Build Coastguard Worker	for _, v := range values {
115*333d2b36SAndroid Build Coastguard Worker		sb.WriteString(prefix)
116*333d2b36SAndroid Build Coastguard Worker		sb.WriteString(v)
117*333d2b36SAndroid Build Coastguard Worker	}
118*333d2b36SAndroid Build Coastguard Worker	return sb.String()
119*333d2b36SAndroid Build Coastguard Worker}
120*333d2b36SAndroid Build Coastguard Worker
121*333d2b36SAndroid Build Coastguard Workerfunc optionalVariable(prefix string, value string) string {
122*333d2b36SAndroid Build Coastguard Worker	var sb strings.Builder
123*333d2b36SAndroid Build Coastguard Worker	if value != "" {
124*333d2b36SAndroid Build Coastguard Worker		sb.WriteString(prefix)
125*333d2b36SAndroid Build Coastguard Worker		sb.WriteString(value)
126*333d2b36SAndroid Build Coastguard Worker	}
127*333d2b36SAndroid Build Coastguard Worker	return sb.String()
128*333d2b36SAndroid Build Coastguard Worker}
129*333d2b36SAndroid Build Coastguard Worker
130*333d2b36SAndroid Build Coastguard Worker// Assemble the actual filename.
131*333d2b36SAndroid Build Coastguard Worker// If `rcName` is not empty, then insert "-{rcName}" into the path before the
132*333d2b36SAndroid Build Coastguard Worker// file extension.
133*333d2b36SAndroid Build Coastguard Workerfunc assembleFileName(rcName, path string) string {
134*333d2b36SAndroid Build Coastguard Worker	if rcName == "" {
135*333d2b36SAndroid Build Coastguard Worker		return path
136*333d2b36SAndroid Build Coastguard Worker	}
137*333d2b36SAndroid Build Coastguard Worker	dir, file := filepath.Split(path)
138*333d2b36SAndroid Build Coastguard Worker	rcName = "-" + rcName
139*333d2b36SAndroid Build Coastguard Worker	ext := filepath.Ext(file)
140*333d2b36SAndroid Build Coastguard Worker	base := file[:len(file)-len(ext)]
141*333d2b36SAndroid Build Coastguard Worker	return dir + base + rcName + ext
142*333d2b36SAndroid Build Coastguard Worker}
143*333d2b36SAndroid Build Coastguard Worker
144*333d2b36SAndroid Build Coastguard Workerfunc (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
145*333d2b36SAndroid Build Coastguard Worker	// Determine which release configs we are processing.
146*333d2b36SAndroid Build Coastguard Worker	//
147*333d2b36SAndroid Build Coastguard Worker	// We always process the current release config (empty string).
148*333d2b36SAndroid Build Coastguard Worker	// We may have been told to also create artifacts for some others.
149*333d2b36SAndroid Build Coastguard Worker	configs := append([]string{""}, ctx.Config().ReleaseAconfigExtraReleaseConfigs()...)
150*333d2b36SAndroid Build Coastguard Worker	slices.Sort(configs)
151*333d2b36SAndroid Build Coastguard Worker
152*333d2b36SAndroid Build Coastguard Worker	values := make(map[string][]string)
153*333d2b36SAndroid Build Coastguard Worker	valuesFiles := make(map[string][]android.Path, 0)
154*333d2b36SAndroid Build Coastguard Worker	providerData := android.AconfigReleaseDeclarationsProviderData{}
155*333d2b36SAndroid Build Coastguard Worker	ctx.VisitDirectDeps(func(dep android.Module) {
156*333d2b36SAndroid Build Coastguard Worker		if depData, ok := android.OtherModuleProvider(ctx, dep, valueSetProviderKey); ok {
157*333d2b36SAndroid Build Coastguard Worker			depTag := ctx.OtherModuleDependencyTag(dep)
158*333d2b36SAndroid Build Coastguard Worker			for _, config := range configs {
159*333d2b36SAndroid Build Coastguard Worker				tag := implicitValuesTagType{ReleaseConfig: config}
160*333d2b36SAndroid Build Coastguard Worker				if depTag == tag {
161*333d2b36SAndroid Build Coastguard Worker					paths, ok := depData.AvailablePackages[module.properties.Package]
162*333d2b36SAndroid Build Coastguard Worker					if ok {
163*333d2b36SAndroid Build Coastguard Worker						valuesFiles[config] = append(valuesFiles[config], paths...)
164*333d2b36SAndroid Build Coastguard Worker						for _, path := range paths {
165*333d2b36SAndroid Build Coastguard Worker							values[config] = append(values[config], path.String())
166*333d2b36SAndroid Build Coastguard Worker						}
167*333d2b36SAndroid Build Coastguard Worker					}
168*333d2b36SAndroid Build Coastguard Worker				}
169*333d2b36SAndroid Build Coastguard Worker			}
170*333d2b36SAndroid Build Coastguard Worker		}
171*333d2b36SAndroid Build Coastguard Worker	})
172*333d2b36SAndroid Build Coastguard Worker	for _, config := range configs {
173*333d2b36SAndroid Build Coastguard Worker		module.properties.ReleaseConfigValues = append(module.properties.ReleaseConfigValues, AconfigReleaseConfigValue{
174*333d2b36SAndroid Build Coastguard Worker			ReleaseConfig: config,
175*333d2b36SAndroid Build Coastguard Worker			Values:        values[config],
176*333d2b36SAndroid Build Coastguard Worker		})
177*333d2b36SAndroid Build Coastguard Worker
178*333d2b36SAndroid Build Coastguard Worker		// Intermediate format
179*333d2b36SAndroid Build Coastguard Worker		declarationFiles := android.PathsForModuleSrc(ctx, module.properties.Srcs)
180*333d2b36SAndroid Build Coastguard Worker		intermediateCacheFilePath := android.PathForModuleOut(ctx, assembleFileName(config, "intermediate.pb"))
181*333d2b36SAndroid Build Coastguard Worker		var defaultPermission string
182*333d2b36SAndroid Build Coastguard Worker		defaultPermission = ctx.Config().ReleaseAconfigFlagDefaultPermission()
183*333d2b36SAndroid Build Coastguard Worker		if config != "" {
184*333d2b36SAndroid Build Coastguard Worker			if confPerm, ok := ctx.Config().GetBuildFlag("RELEASE_ACONFIG_FLAG_DEFAULT_PERMISSION_" + config); ok {
185*333d2b36SAndroid Build Coastguard Worker				defaultPermission = confPerm
186*333d2b36SAndroid Build Coastguard Worker			}
187*333d2b36SAndroid Build Coastguard Worker		}
188*333d2b36SAndroid Build Coastguard Worker		var allowReadWrite bool
189*333d2b36SAndroid Build Coastguard Worker		if requireAllReadOnly, ok := ctx.Config().GetBuildFlag("RELEASE_ACONFIG_REQUIRE_ALL_READ_ONLY"); ok {
190*333d2b36SAndroid Build Coastguard Worker			// The build flag (RELEASE_ACONFIG_REQUIRE_ALL_READ_ONLY) is the negation of the aconfig flag
191*333d2b36SAndroid Build Coastguard Worker			// (allow-read-write) for historical reasons.
192*333d2b36SAndroid Build Coastguard Worker			// Bool build flags are always "" for false, and generally "true" for true.
193*333d2b36SAndroid Build Coastguard Worker			allowReadWrite = requireAllReadOnly == ""
194*333d2b36SAndroid Build Coastguard Worker		}
195*333d2b36SAndroid Build Coastguard Worker		inputFiles := make([]android.Path, len(declarationFiles))
196*333d2b36SAndroid Build Coastguard Worker		copy(inputFiles, declarationFiles)
197*333d2b36SAndroid Build Coastguard Worker		inputFiles = append(inputFiles, valuesFiles[config]...)
198*333d2b36SAndroid Build Coastguard Worker		args := map[string]string{
199*333d2b36SAndroid Build Coastguard Worker			"release_version":    ctx.Config().ReleaseVersion(),
200*333d2b36SAndroid Build Coastguard Worker			"package":            module.properties.Package,
201*333d2b36SAndroid Build Coastguard Worker			"declarations":       android.JoinPathsWithPrefix(declarationFiles, "--declarations "),
202*333d2b36SAndroid Build Coastguard Worker			"values":             joinAndPrefix(" --values ", values[config]),
203*333d2b36SAndroid Build Coastguard Worker			"default-permission": optionalVariable(" --default-permission ", defaultPermission),
204*333d2b36SAndroid Build Coastguard Worker			"allow-read-write":   optionalVariable(" --allow-read-write ", strconv.FormatBool(allowReadWrite)),
205*333d2b36SAndroid Build Coastguard Worker		}
206*333d2b36SAndroid Build Coastguard Worker		if len(module.properties.Container) > 0 {
207*333d2b36SAndroid Build Coastguard Worker			args["container"] = "--container " + module.properties.Container
208*333d2b36SAndroid Build Coastguard Worker		}
209*333d2b36SAndroid Build Coastguard Worker		ctx.Build(pctx, android.BuildParams{
210*333d2b36SAndroid Build Coastguard Worker			Rule:        aconfigRule,
211*333d2b36SAndroid Build Coastguard Worker			Output:      intermediateCacheFilePath,
212*333d2b36SAndroid Build Coastguard Worker			Inputs:      inputFiles,
213*333d2b36SAndroid Build Coastguard Worker			Description: "aconfig_declarations",
214*333d2b36SAndroid Build Coastguard Worker			Args:        args,
215*333d2b36SAndroid Build Coastguard Worker		})
216*333d2b36SAndroid Build Coastguard Worker
217*333d2b36SAndroid Build Coastguard Worker		intermediateDumpFilePath := android.PathForModuleOut(ctx, assembleFileName(config, "intermediate.txt"))
218*333d2b36SAndroid Build Coastguard Worker		ctx.Build(pctx, android.BuildParams{
219*333d2b36SAndroid Build Coastguard Worker			Rule:        aconfigTextRule,
220*333d2b36SAndroid Build Coastguard Worker			Output:      intermediateDumpFilePath,
221*333d2b36SAndroid Build Coastguard Worker			Inputs:      android.Paths{intermediateCacheFilePath},
222*333d2b36SAndroid Build Coastguard Worker			Description: "aconfig_text",
223*333d2b36SAndroid Build Coastguard Worker		})
224*333d2b36SAndroid Build Coastguard Worker
225*333d2b36SAndroid Build Coastguard Worker		providerData[config] = android.AconfigDeclarationsProviderData{
226*333d2b36SAndroid Build Coastguard Worker			Package:                     module.properties.Package,
227*333d2b36SAndroid Build Coastguard Worker			Container:                   module.properties.Container,
228*333d2b36SAndroid Build Coastguard Worker			Exportable:                  module.properties.Exportable,
229*333d2b36SAndroid Build Coastguard Worker			IntermediateCacheOutputPath: intermediateCacheFilePath,
230*333d2b36SAndroid Build Coastguard Worker			IntermediateDumpOutputPath:  intermediateDumpFilePath,
231*333d2b36SAndroid Build Coastguard Worker		}
232*333d2b36SAndroid Build Coastguard Worker	}
233*333d2b36SAndroid Build Coastguard Worker	android.SetProvider(ctx, android.AconfigDeclarationsProviderKey, providerData[""])
234*333d2b36SAndroid Build Coastguard Worker	android.SetProvider(ctx, android.AconfigReleaseDeclarationsProviderKey, providerData)
235*333d2b36SAndroid Build Coastguard Worker}
236*333d2b36SAndroid Build Coastguard Worker
237*333d2b36SAndroid Build Coastguard Workervar _ blueprint.Incremental = &DeclarationsModule{}
238