xref: /aosp_15_r20/build/soong/aconfig/all_aconfig_declarations.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	"fmt"
19	"slices"
20
21	"android/soong/android"
22)
23
24// A singleton module that collects all of the aconfig flags declared in the
25// tree into a single combined file for export to the external flag setting
26// server (inside Google it's Gantry).
27//
28// Note that this is ALL aconfig_declarations modules present in the tree, not just
29// ones that are relevant to the product currently being built, so that that infra
30// doesn't need to pull from multiple builds and merge them.
31func AllAconfigDeclarationsFactory() android.Singleton {
32	return &allAconfigDeclarationsSingleton{releaseMap: make(map[string]allAconfigReleaseDeclarationsSingleton)}
33}
34
35type allAconfigReleaseDeclarationsSingleton struct {
36	intermediateBinaryProtoPath android.OutputPath
37	intermediateTextProtoPath   android.OutputPath
38}
39
40type allAconfigDeclarationsSingleton struct {
41	releaseMap map[string]allAconfigReleaseDeclarationsSingleton
42}
43
44func (this *allAconfigDeclarationsSingleton) sortedConfigNames() []string {
45	var names []string
46	for k := range this.releaseMap {
47		names = append(names, k)
48	}
49	slices.Sort(names)
50	return names
51}
52
53func (this *allAconfigDeclarationsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
54	for _, rcName := range append([]string{""}, ctx.Config().ReleaseAconfigExtraReleaseConfigs()...) {
55		// Find all of the aconfig_declarations modules
56		var packages = make(map[string]int)
57		var cacheFiles android.Paths
58		ctx.VisitAllModules(func(module android.Module) {
59			decl, ok := android.OtherModuleProvider(ctx, module, android.AconfigReleaseDeclarationsProviderKey)
60			if !ok {
61				return
62			}
63			cacheFiles = append(cacheFiles, decl[rcName].IntermediateCacheOutputPath)
64			packages[decl[rcName].Package]++
65		})
66
67		var numOffendingPkg = 0
68		for pkg, cnt := range packages {
69			if cnt > 1 {
70				fmt.Printf("%d aconfig_declarations found for package %s\n", cnt, pkg)
71				numOffendingPkg++
72			}
73		}
74
75		if numOffendingPkg > 0 {
76			panic(fmt.Errorf("Only one aconfig_declarations allowed for each package."))
77		}
78
79		// Generate build action for aconfig (binary proto output)
80		paths := allAconfigReleaseDeclarationsSingleton{
81			intermediateBinaryProtoPath: android.PathForIntermediates(ctx, assembleFileName(rcName, "all_aconfig_declarations.pb")),
82			intermediateTextProtoPath:   android.PathForIntermediates(ctx, assembleFileName(rcName, "all_aconfig_declarations.textproto")),
83		}
84		this.releaseMap[rcName] = paths
85		ctx.Build(pctx, android.BuildParams{
86			Rule:        AllDeclarationsRule,
87			Inputs:      cacheFiles,
88			Output:      this.releaseMap[rcName].intermediateBinaryProtoPath,
89			Description: "all_aconfig_declarations",
90			Args: map[string]string{
91				"cache_files": android.JoinPathsWithPrefix(cacheFiles, "--cache "),
92			},
93		})
94		ctx.Phony("all_aconfig_declarations", this.releaseMap[rcName].intermediateBinaryProtoPath)
95
96		// Generate build action for aconfig (text proto output)
97		ctx.Build(pctx, android.BuildParams{
98			Rule:        AllDeclarationsRuleTextProto,
99			Inputs:      cacheFiles,
100			Output:      this.releaseMap[rcName].intermediateTextProtoPath,
101			Description: "all_aconfig_declarations_textproto",
102			Args: map[string]string{
103				"cache_files": android.JoinPathsWithPrefix(cacheFiles, "--cache "),
104			},
105		})
106		ctx.Phony("all_aconfig_declarations_textproto", this.releaseMap[rcName].intermediateTextProtoPath)
107	}
108}
109
110func (this *allAconfigDeclarationsSingleton) MakeVars(ctx android.MakeVarsContext) {
111	for _, rcName := range this.sortedConfigNames() {
112		ctx.DistForGoal("droid", this.releaseMap[rcName].intermediateBinaryProtoPath)
113		for _, goal := range []string{"docs", "droid", "sdk"} {
114			ctx.DistForGoalWithFilename(goal, this.releaseMap[rcName].intermediateBinaryProtoPath, assembleFileName(rcName, "flags.pb"))
115			ctx.DistForGoalWithFilename(goal, this.releaseMap[rcName].intermediateTextProtoPath, assembleFileName(rcName, "flags.textproto"))
116		}
117	}
118}
119