Add RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS

This build flag causes us to create aconfig flag artifacts for the
given extra release configs.

Bug: 298444886
Test: manual
Change-Id: I10148f6e7318b0477438ed1d8baafbf4dc594c90
This commit is contained in:
LaMont Jones
2024-06-11 11:28:54 -07:00
parent ecdb25e674
commit 21d04d99c8
8 changed files with 390 additions and 103 deletions

View File

@@ -15,6 +15,8 @@
package aconfig
import (
"path/filepath"
"slices"
"strings"
"android/soong/android"
@@ -22,6 +24,11 @@ import (
"github.com/google/blueprint"
)
type AconfigReleaseConfigValue struct {
ReleaseConfig string
Values []string `blueprint:"mutated"`
}
type DeclarationsModule struct {
android.ModuleBase
android.DefaultableModuleBase
@@ -34,8 +41,10 @@ type DeclarationsModule struct {
// Release config flag package
Package string
// Values from TARGET_RELEASE / RELEASE_ACONFIG_VALUE_SETS
Values []string `blueprint:"mutated"`
// Values for release configs / RELEASE_ACONFIG_VALUE_SETS
// The current release config is `ReleaseConfig: ""`, others
// are from RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS.
ReleaseConfigValues []AconfigReleaseConfigValue
// Container(system/vendor/apex) that this module belongs to
Container string
@@ -57,6 +66,10 @@ func DeclarationsFactory() android.Module {
type implicitValuesTagType struct {
blueprint.BaseDependencyTag
// The release config name for these values.
// Empty string for the actual current release config.
ReleaseConfig string
}
var implicitValuesTag = implicitValuesTagType{}
@@ -81,6 +94,11 @@ func (module *DeclarationsModule) DepsMutator(ctx android.BottomUpMutatorContext
if len(valuesFromConfig) > 0 {
ctx.AddDependency(ctx.Module(), implicitValuesTag, valuesFromConfig...)
}
for rcName, valueSets := range ctx.Config().ReleaseAconfigExtraReleaseConfigsValueSets() {
if len(valueSets) > 0 {
ctx.AddDependency(ctx.Module(), implicitValuesTagType{ReleaseConfig: rcName}, valueSets...)
}
}
}
func joinAndPrefix(prefix string, values []string) string {
@@ -101,59 +119,101 @@ func optionalVariable(prefix string, value string) string {
return sb.String()
}
// Assemble the actual filename.
// If `rcName` is not empty, then insert "-{rcName}" into the path before the
// file extension.
func assembleFileName(rcName, path string) string {
if rcName == "" {
return path
}
dir, file := filepath.Split(path)
rcName = "-" + rcName
ext := filepath.Ext(file)
base := file[:len(file)-len(ext)]
return dir + base + rcName + ext
}
func (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
valuesFiles := make([]android.Path, 0)
// Determine which release configs we are processing.
//
// We always process the current release config (empty string).
// We may have been told to also create artifacts for some others.
configs := append([]string{""}, ctx.Config().ReleaseAconfigExtraReleaseConfigs()...)
slices.Sort(configs)
values := make(map[string][]string)
valuesFiles := make(map[string][]android.Path, 0)
providerData := android.AconfigReleaseDeclarationsProviderData{}
ctx.VisitDirectDeps(func(dep android.Module) {
if depData, ok := android.OtherModuleProvider(ctx, dep, valueSetProviderKey); ok {
paths, ok := depData.AvailablePackages[module.properties.Package]
if ok {
valuesFiles = append(valuesFiles, paths...)
for _, path := range paths {
module.properties.Values = append(module.properties.Values, path.String())
depTag := ctx.OtherModuleDependencyTag(dep)
for _, config := range configs {
tag := implicitValuesTagType{ReleaseConfig: config}
if depTag == tag {
paths, ok := depData.AvailablePackages[module.properties.Package]
if ok {
valuesFiles[config] = append(valuesFiles[config], paths...)
for _, path := range paths {
values[config] = append(values[config], path.String())
}
}
}
}
}
})
for _, config := range configs {
module.properties.ReleaseConfigValues = append(module.properties.ReleaseConfigValues, AconfigReleaseConfigValue{
ReleaseConfig: config,
Values: values[config],
})
// Intermediate format
declarationFiles := android.PathsForModuleSrc(ctx, module.properties.Srcs)
intermediateCacheFilePath := android.PathForModuleOut(ctx, "intermediate.pb")
defaultPermission := ctx.Config().ReleaseAconfigFlagDefaultPermission()
inputFiles := make([]android.Path, len(declarationFiles))
copy(inputFiles, declarationFiles)
inputFiles = append(inputFiles, valuesFiles...)
args := map[string]string{
"release_version": ctx.Config().ReleaseVersion(),
"package": module.properties.Package,
"declarations": android.JoinPathsWithPrefix(declarationFiles, "--declarations "),
"values": joinAndPrefix(" --values ", module.properties.Values),
"default-permission": optionalVariable(" --default-permission ", defaultPermission),
// Intermediate format
declarationFiles := android.PathsForModuleSrc(ctx, module.properties.Srcs)
intermediateCacheFilePath := android.PathForModuleOut(ctx, assembleFileName(config, "intermediate.pb"))
var defaultPermission string
defaultPermission = ctx.Config().ReleaseAconfigFlagDefaultPermission()
if config != "" {
if confPerm, ok := ctx.Config().GetBuildFlag("RELEASE_ACONFIG_FLAG_DEFAULT_PERMISSION_" + config); ok {
defaultPermission = confPerm
}
}
inputFiles := make([]android.Path, len(declarationFiles))
copy(inputFiles, declarationFiles)
inputFiles = append(inputFiles, valuesFiles[config]...)
args := map[string]string{
"release_version": ctx.Config().ReleaseVersion(),
"package": module.properties.Package,
"declarations": android.JoinPathsWithPrefix(declarationFiles, "--declarations "),
"values": joinAndPrefix(" --values ", values[config]),
"default-permission": optionalVariable(" --default-permission ", defaultPermission),
}
if len(module.properties.Container) > 0 {
args["container"] = "--container " + module.properties.Container
}
ctx.Build(pctx, android.BuildParams{
Rule: aconfigRule,
Output: intermediateCacheFilePath,
Inputs: inputFiles,
Description: "aconfig_declarations",
Args: args,
})
intermediateDumpFilePath := android.PathForModuleOut(ctx, assembleFileName(config, "intermediate.txt"))
ctx.Build(pctx, android.BuildParams{
Rule: aconfigTextRule,
Output: intermediateDumpFilePath,
Inputs: android.Paths{intermediateCacheFilePath},
Description: "aconfig_text",
})
providerData[config] = android.AconfigDeclarationsProviderData{
Package: module.properties.Package,
Container: module.properties.Container,
Exportable: module.properties.Exportable,
IntermediateCacheOutputPath: intermediateCacheFilePath,
IntermediateDumpOutputPath: intermediateDumpFilePath,
}
}
if len(module.properties.Container) > 0 {
args["container"] = "--container " + module.properties.Container
}
ctx.Build(pctx, android.BuildParams{
Rule: aconfigRule,
Output: intermediateCacheFilePath,
Inputs: inputFiles,
Description: "aconfig_declarations",
Args: args,
})
intermediateDumpFilePath := android.PathForModuleOut(ctx, "intermediate.txt")
ctx.Build(pctx, android.BuildParams{
Rule: aconfigTextRule,
Output: intermediateDumpFilePath,
Inputs: android.Paths{intermediateCacheFilePath},
Description: "aconfig_text",
})
android.SetProvider(ctx, android.AconfigDeclarationsProviderKey, android.AconfigDeclarationsProviderData{
Package: module.properties.Package,
Container: module.properties.Container,
Exportable: module.properties.Exportable,
IntermediateCacheOutputPath: intermediateCacheFilePath,
IntermediateDumpOutputPath: intermediateDumpFilePath,
})
android.SetProvider(ctx, android.AconfigDeclarationsProviderKey, providerData[""])
android.SetProvider(ctx, android.AconfigReleaseDeclarationsProviderKey, providerData)
}

View File

@@ -15,6 +15,7 @@
package aconfig
import (
"slices"
"strings"
"testing"
@@ -134,3 +135,95 @@ func TestMandatoryProperties(t *testing.T) {
})
}
}
func TestAssembleFileName(t *testing.T) {
testCases := []struct {
name string
releaseConfig string
path string
expectedValue string
}{
{
name: "active release config",
path: "file.path",
expectedValue: "file.path",
},
{
name: "release config FOO",
releaseConfig: "FOO",
path: "file.path",
expectedValue: "file-FOO.path",
},
}
for _, test := range testCases {
actualValue := assembleFileName(test.releaseConfig, test.path)
if actualValue != test.expectedValue {
t.Errorf("Expected %q found %q", test.expectedValue, actualValue)
}
}
}
func TestGenerateAndroidBuildActions(t *testing.T) {
testCases := []struct {
name string
buildFlags map[string]string
bp string
errorHandler android.FixtureErrorHandler
}{
{
name: "generate extra",
buildFlags: map[string]string{
"RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS": "config2",
"RELEASE_ACONFIG_VALUE_SETS": "aconfig_value_set-config1",
"RELEASE_ACONFIG_VALUE_SETS_config2": "aconfig_value_set-config2",
},
bp: `
aconfig_declarations {
name: "module_name",
package: "com.example.package",
container: "com.android.foo",
srcs: [
"foo.aconfig",
"bar.aconfig",
],
}
aconfig_value_set {
name: "aconfig_value_set-config1",
values: []
}
aconfig_value_set {
name: "aconfig_value_set-config2",
values: []
}
`,
},
}
for _, test := range testCases {
fixture := PrepareForTest(t, addBuildFlagsForTest(test.buildFlags))
if test.errorHandler != nil {
fixture = fixture.ExtendWithErrorHandler(test.errorHandler)
}
result := fixture.RunTestWithBp(t, test.bp)
module := result.ModuleForTests("module_name", "").Module().(*DeclarationsModule)
depData, _ := android.SingletonModuleProvider(result, module, android.AconfigReleaseDeclarationsProviderKey)
expectedKeys := []string{""}
for _, rc := range strings.Split(test.buildFlags["RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS"], " ") {
expectedKeys = append(expectedKeys, rc)
}
slices.Sort(expectedKeys)
actualKeys := []string{}
for rc := range depData {
actualKeys = append(actualKeys, rc)
}
slices.Sort(actualKeys)
android.AssertStringEquals(t, "provider keys", strings.Join(expectedKeys, " "), strings.Join(actualKeys, " "))
for _, rc := range actualKeys {
if !strings.HasSuffix(depData[rc].IntermediateCacheOutputPath.String(), assembleFileName(rc, "/intermediate.pb")) {
t.Errorf("Incorrect intermediates proto path in provider for release config %s: %s", rc, depData[rc].IntermediateCacheOutputPath.String())
}
if !strings.HasSuffix(depData[rc].IntermediateDumpOutputPath.String(), assembleFileName(rc, "/intermediate.txt")) {
t.Errorf("Incorrect intermediates text path in provider for release config %s: %s", rc, depData[rc].IntermediateDumpOutputPath.String())
}
}
}
}

View File

@@ -17,6 +17,7 @@ package aconfig
import (
"android/soong/android"
"fmt"
"slices"
)
// A singleton module that collects all of the aconfig flags declared in the
@@ -27,70 +28,90 @@ import (
// ones that are relevant to the product currently being built, so that that infra
// doesn't need to pull from multiple builds and merge them.
func AllAconfigDeclarationsFactory() android.Singleton {
return &allAconfigDeclarationsSingleton{}
return &allAconfigDeclarationsSingleton{releaseMap: make(map[string]allAconfigReleaseDeclarationsSingleton)}
}
type allAconfigDeclarationsSingleton struct {
type allAconfigReleaseDeclarationsSingleton struct {
intermediateBinaryProtoPath android.OutputPath
intermediateTextProtoPath android.OutputPath
}
type allAconfigDeclarationsSingleton struct {
releaseMap map[string]allAconfigReleaseDeclarationsSingleton
}
func (this *allAconfigDeclarationsSingleton) sortedConfigNames() []string {
var names []string
for k := range this.releaseMap {
names = append(names, k)
}
slices.Sort(names)
return names
}
func (this *allAconfigDeclarationsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
// Find all of the aconfig_declarations modules
var packages = make(map[string]int)
var cacheFiles android.Paths
ctx.VisitAllModules(func(module android.Module) {
decl, ok := android.SingletonModuleProvider(ctx, module, android.AconfigDeclarationsProviderKey)
if !ok {
return
for _, rcName := range append([]string{""}, ctx.Config().ReleaseAconfigExtraReleaseConfigs()...) {
// Find all of the aconfig_declarations modules
var packages = make(map[string]int)
var cacheFiles android.Paths
ctx.VisitAllModules(func(module android.Module) {
decl, ok := android.SingletonModuleProvider(ctx, module, android.AconfigReleaseDeclarationsProviderKey)
if !ok {
return
}
cacheFiles = append(cacheFiles, decl[rcName].IntermediateCacheOutputPath)
packages[decl[rcName].Package]++
})
var numOffendingPkg = 0
for pkg, cnt := range packages {
if cnt > 1 {
fmt.Printf("%d aconfig_declarations found for package %s\n", cnt, pkg)
numOffendingPkg++
}
}
cacheFiles = append(cacheFiles, decl.IntermediateCacheOutputPath)
packages[decl.Package]++
})
var numOffendingPkg = 0
for pkg, cnt := range packages {
if cnt > 1 {
fmt.Printf("%d aconfig_declarations found for package %s\n", cnt, pkg)
numOffendingPkg++
if numOffendingPkg > 0 {
panic(fmt.Errorf("Only one aconfig_declarations allowed for each package."))
}
// Generate build action for aconfig (binary proto output)
paths := allAconfigReleaseDeclarationsSingleton{
intermediateBinaryProtoPath: android.PathForIntermediates(ctx, assembleFileName(rcName, "all_aconfig_declarations.pb")),
intermediateTextProtoPath: android.PathForIntermediates(ctx, assembleFileName(rcName, "all_aconfig_declarations.textproto")),
}
this.releaseMap[rcName] = paths
ctx.Build(pctx, android.BuildParams{
Rule: AllDeclarationsRule,
Inputs: cacheFiles,
Output: this.releaseMap[rcName].intermediateBinaryProtoPath,
Description: "all_aconfig_declarations",
Args: map[string]string{
"cache_files": android.JoinPathsWithPrefix(cacheFiles, "--cache "),
},
})
ctx.Phony("all_aconfig_declarations", this.releaseMap[rcName].intermediateBinaryProtoPath)
// Generate build action for aconfig (text proto output)
ctx.Build(pctx, android.BuildParams{
Rule: AllDeclarationsRuleTextProto,
Inputs: cacheFiles,
Output: this.releaseMap[rcName].intermediateTextProtoPath,
Description: "all_aconfig_declarations_textproto",
Args: map[string]string{
"cache_files": android.JoinPathsWithPrefix(cacheFiles, "--cache "),
},
})
ctx.Phony("all_aconfig_declarations_textproto", this.releaseMap[rcName].intermediateTextProtoPath)
}
if numOffendingPkg > 0 {
panic(fmt.Errorf("Only one aconfig_declarations allowed for each package."))
}
// Generate build action for aconfig (binary proto output)
this.intermediateBinaryProtoPath = android.PathForIntermediates(ctx, "all_aconfig_declarations.pb")
ctx.Build(pctx, android.BuildParams{
Rule: AllDeclarationsRule,
Inputs: cacheFiles,
Output: this.intermediateBinaryProtoPath,
Description: "all_aconfig_declarations",
Args: map[string]string{
"cache_files": android.JoinPathsWithPrefix(cacheFiles, "--cache "),
},
})
ctx.Phony("all_aconfig_declarations", this.intermediateBinaryProtoPath)
// Generate build action for aconfig (text proto output)
this.intermediateTextProtoPath = android.PathForIntermediates(ctx, "all_aconfig_declarations.textproto")
ctx.Build(pctx, android.BuildParams{
Rule: AllDeclarationsRuleTextProto,
Inputs: cacheFiles,
Output: this.intermediateTextProtoPath,
Description: "all_aconfig_declarations_textproto",
Args: map[string]string{
"cache_files": android.JoinPathsWithPrefix(cacheFiles, "--cache "),
},
})
ctx.Phony("all_aconfig_declarations_textproto", this.intermediateTextProtoPath)
}
func (this *allAconfigDeclarationsSingleton) MakeVars(ctx android.MakeVarsContext) {
ctx.DistForGoal("droid", this.intermediateBinaryProtoPath)
for _, goal := range []string{"docs", "droid", "sdk"} {
ctx.DistForGoalWithFilename(goal, this.intermediateBinaryProtoPath, "flags.pb")
ctx.DistForGoalWithFilename(goal, this.intermediateTextProtoPath, "flags.textproto")
for _, rcName := range this.sortedConfigNames() {
ctx.DistForGoal("droid", this.releaseMap[rcName].intermediateBinaryProtoPath)
for _, goal := range []string{"docs", "droid", "sdk"} {
ctx.DistForGoalWithFilename(goal, this.releaseMap[rcName].intermediateBinaryProtoPath, assembleFileName(rcName, "flags.pb"))
ctx.DistForGoalWithFilename(goal, this.releaseMap[rcName].intermediateTextProtoPath, assembleFileName(rcName, "flags.textproto"))
}
}
}

View File

@@ -23,7 +23,25 @@ import (
var PrepareForTestWithAconfigBuildComponents = android.FixtureRegisterWithContext(RegisterBuildComponents)
func runTest(t *testing.T, errorHandler android.FixtureErrorHandler, bp string) *android.TestResult {
return android.GroupFixturePreparers(PrepareForTestWithAconfigBuildComponents).
return PrepareForTest(t).
ExtendWithErrorHandler(errorHandler).
RunTestWithBp(t, bp)
}
func PrepareForTest(t *testing.T, preparers ...android.FixturePreparer) android.FixturePreparer {
preparers = append([]android.FixturePreparer{PrepareForTestWithAconfigBuildComponents}, preparers...)
return android.GroupFixturePreparers(preparers...)
}
func addBuildFlagsForTest(buildFlags map[string]string) android.FixturePreparer {
return android.GroupFixturePreparers(
android.FixtureModifyProductVariables(func(vars android.FixtureProductVariables) {
if vars.BuildFlags == nil {
vars.BuildFlags = make(map[string]string)
}
for k, v := range buildFlags {
vars.BuildFlags[k] = v
}
}),
)
}

View File

@@ -43,6 +43,10 @@ type AconfigDeclarationsProviderData struct {
var AconfigDeclarationsProviderKey = blueprint.NewProvider[AconfigDeclarationsProviderData]()
type AconfigReleaseDeclarationsProviderData map[string]AconfigDeclarationsProviderData
var AconfigReleaseDeclarationsProviderKey = blueprint.NewProvider[AconfigReleaseDeclarationsProviderData]()
type ModeInfo struct {
Container string
Mode string
@@ -112,6 +116,8 @@ func aconfigUpdateAndroidBuildActions(ctx ModuleContext) {
if dep, ok := OtherModuleProvider(ctx, module, AconfigDeclarationsProviderKey); ok {
mergedAconfigFiles[dep.Container] = append(mergedAconfigFiles[dep.Container], dep.IntermediateCacheOutputPath)
}
// If we were generating on-device artifacts for other release configs, we would need to add code here to propagate
// those artifacts as well. See also b/298444886.
if dep, ok := OtherModuleProvider(ctx, module, AconfigPropagatingProviderKey); ok {
for container, v := range dep.AconfigFiles {
mergedAconfigFiles[container] = append(mergedAconfigFiles[container], v...)

View File

@@ -198,6 +198,33 @@ func (c Config) ReleaseAconfigValueSets() []string {
return c.config.productVariables.ReleaseAconfigValueSets
}
func (c Config) ReleaseAconfigExtraReleaseConfigs() []string {
result := []string{}
if val, ok := c.config.productVariables.BuildFlags["RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS"]; ok {
if len(val) > 0 {
// Remove any duplicates from the list.
found := make(map[string]bool)
for _, k := range strings.Split(val, " ") {
if !found[k] {
found[k] = true
result = append(result, k)
}
}
}
}
return result
}
func (c Config) ReleaseAconfigExtraReleaseConfigsValueSets() map[string][]string {
result := make(map[string][]string)
for _, rcName := range c.ReleaseAconfigExtraReleaseConfigs() {
if value, ok := c.config.productVariables.BuildFlags["RELEASE_ACONFIG_VALUE_SETS_"+rcName]; ok {
result[rcName] = strings.Split(value, " ")
}
}
return result
}
// The flag default permission value passed to aconfig
// derived from RELEASE_ACONFIG_FLAG_DEFAULT_PERMISSION
func (c Config) ReleaseAconfigFlagDefaultPermission() string {

View File

@@ -125,6 +125,43 @@ func assertStringEquals(t *testing.T, expected, actual string) {
}
}
func TestReleaseAconfigExtraReleaseConfigs(t *testing.T) {
testCases := []struct {
name string
flag string
expected []string
}{
{
name: "empty",
flag: "",
expected: []string{},
},
{
name: "specified",
flag: "bar foo",
expected: []string{"bar", "foo"},
},
{
name: "duplicates",
flag: "foo bar foo",
expected: []string{"foo", "bar"},
},
}
for _, tc := range testCases {
fixture := GroupFixturePreparers(
FixtureModifyProductVariables(func(vars FixtureProductVariables) {
if vars.BuildFlags == nil {
vars.BuildFlags = make(map[string]string)
}
vars.BuildFlags["RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS"] = tc.flag
}),
)
actual := fixture.RunTest(t).Config.ReleaseAconfigExtraReleaseConfigs()
AssertArrayString(t, tc.name, tc.expected, actual)
}
}
func TestConfiguredJarList(t *testing.T) {
list1 := CreateTestConfiguredJarList([]string{"apex1:jarA"})

View File

@@ -226,8 +226,16 @@ func (config *ReleaseConfig) GenerateReleaseConfig(configs *ReleaseConfigs) erro
config.PriorStagesMap[priorStage] = true
}
myDirsMap[contrib.DeclarationIndex] = true
if config.AconfigFlagsOnly && len(contrib.FlagValues) > 0 {
return fmt.Errorf("%s does not allow build flag overrides", config.Name)
if config.AconfigFlagsOnly {
// AconfigFlagsOnly allows very very few build flag values, all of them are part of aconfig flags.
allowedFlags := map[string]bool{
"RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS": true,
}
for _, fv := range contrib.FlagValues {
if !allowedFlags[*fv.proto.Name] {
return fmt.Errorf("%s does not allow build flag overrides", config.Name)
}
}
}
for _, value := range contrib.FlagValues {
name := *value.proto.Name
@@ -256,7 +264,7 @@ func (config *ReleaseConfig) GenerateReleaseConfig(configs *ReleaseConfigs) erro
myAconfigValueSets := []string{}
myAconfigValueSetsMap := map[string]bool{}
for _, v := range strings.Split(releaseAconfigValueSets.Value.GetStringValue(), " ") {
if myAconfigValueSetsMap[v] {
if v == "" || myAconfigValueSetsMap[v] {
continue
}
myAconfigValueSetsMap[v] = true
@@ -320,6 +328,23 @@ func (config *ReleaseConfig) WriteMakefile(outFile, targetRelease string, config
makeVars := make(map[string]string)
myFlagArtifacts := config.FlagArtifacts.Clone()
// Add any RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS variables.
var extraAconfigReleaseConfigs []string
if extraAconfigValueSetsValue, ok := config.FlagArtifacts["RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS"]; ok {
if val := MarshalValue(extraAconfigValueSetsValue.Value); len(val) > 0 {
extraAconfigReleaseConfigs = strings.Split(val, " ")
}
}
for _, rcName := range extraAconfigReleaseConfigs {
rc, err := configs.GetReleaseConfig(rcName)
if err != nil {
return err
}
myFlagArtifacts["RELEASE_ACONFIG_VALUE_SETS_"+rcName] = rc.FlagArtifacts["RELEASE_ACONFIG_VALUE_SETS"]
myFlagArtifacts["RELEASE_ACONFIG_FLAG_DEFAULT_PERMISSION_"+rcName] = rc.FlagArtifacts["RELEASE_ACONFIG_FLAG_DEFAULT_PERMISSION"]
}
// Sort the flags by name first.
names := myFlagArtifacts.SortedFlagNames()
partitions := make(map[string][]string)