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