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:
@@ -15,6 +15,8 @@
|
|||||||
package aconfig
|
package aconfig
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
@@ -22,6 +24,11 @@ import (
|
|||||||
"github.com/google/blueprint"
|
"github.com/google/blueprint"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type AconfigReleaseConfigValue struct {
|
||||||
|
ReleaseConfig string
|
||||||
|
Values []string `blueprint:"mutated"`
|
||||||
|
}
|
||||||
|
|
||||||
type DeclarationsModule struct {
|
type DeclarationsModule struct {
|
||||||
android.ModuleBase
|
android.ModuleBase
|
||||||
android.DefaultableModuleBase
|
android.DefaultableModuleBase
|
||||||
@@ -34,8 +41,10 @@ type DeclarationsModule struct {
|
|||||||
// Release config flag package
|
// Release config flag package
|
||||||
Package string
|
Package string
|
||||||
|
|
||||||
// Values from TARGET_RELEASE / RELEASE_ACONFIG_VALUE_SETS
|
// Values for release configs / RELEASE_ACONFIG_VALUE_SETS
|
||||||
Values []string `blueprint:"mutated"`
|
// 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(system/vendor/apex) that this module belongs to
|
||||||
Container string
|
Container string
|
||||||
@@ -57,6 +66,10 @@ func DeclarationsFactory() android.Module {
|
|||||||
|
|
||||||
type implicitValuesTagType struct {
|
type implicitValuesTagType struct {
|
||||||
blueprint.BaseDependencyTag
|
blueprint.BaseDependencyTag
|
||||||
|
|
||||||
|
// The release config name for these values.
|
||||||
|
// Empty string for the actual current release config.
|
||||||
|
ReleaseConfig string
|
||||||
}
|
}
|
||||||
|
|
||||||
var implicitValuesTag = implicitValuesTagType{}
|
var implicitValuesTag = implicitValuesTagType{}
|
||||||
@@ -81,6 +94,11 @@ func (module *DeclarationsModule) DepsMutator(ctx android.BottomUpMutatorContext
|
|||||||
if len(valuesFromConfig) > 0 {
|
if len(valuesFromConfig) > 0 {
|
||||||
ctx.AddDependency(ctx.Module(), implicitValuesTag, valuesFromConfig...)
|
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 {
|
func joinAndPrefix(prefix string, values []string) string {
|
||||||
@@ -101,59 +119,101 @@ func optionalVariable(prefix string, value string) string {
|
|||||||
return sb.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) {
|
func (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
// Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
|
// Determine which release configs we are processing.
|
||||||
valuesFiles := make([]android.Path, 0)
|
//
|
||||||
|
// 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) {
|
ctx.VisitDirectDeps(func(dep android.Module) {
|
||||||
if depData, ok := android.OtherModuleProvider(ctx, dep, valueSetProviderKey); ok {
|
if depData, ok := android.OtherModuleProvider(ctx, dep, valueSetProviderKey); ok {
|
||||||
paths, ok := depData.AvailablePackages[module.properties.Package]
|
depTag := ctx.OtherModuleDependencyTag(dep)
|
||||||
if ok {
|
for _, config := range configs {
|
||||||
valuesFiles = append(valuesFiles, paths...)
|
tag := implicitValuesTagType{ReleaseConfig: config}
|
||||||
for _, path := range paths {
|
if depTag == tag {
|
||||||
module.properties.Values = append(module.properties.Values, path.String())
|
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
|
// Intermediate format
|
||||||
declarationFiles := android.PathsForModuleSrc(ctx, module.properties.Srcs)
|
declarationFiles := android.PathsForModuleSrc(ctx, module.properties.Srcs)
|
||||||
intermediateCacheFilePath := android.PathForModuleOut(ctx, "intermediate.pb")
|
intermediateCacheFilePath := android.PathForModuleOut(ctx, assembleFileName(config, "intermediate.pb"))
|
||||||
defaultPermission := ctx.Config().ReleaseAconfigFlagDefaultPermission()
|
var defaultPermission string
|
||||||
inputFiles := make([]android.Path, len(declarationFiles))
|
defaultPermission = ctx.Config().ReleaseAconfigFlagDefaultPermission()
|
||||||
copy(inputFiles, declarationFiles)
|
if config != "" {
|
||||||
inputFiles = append(inputFiles, valuesFiles...)
|
if confPerm, ok := ctx.Config().GetBuildFlag("RELEASE_ACONFIG_FLAG_DEFAULT_PERMISSION_" + config); ok {
|
||||||
args := map[string]string{
|
defaultPermission = confPerm
|
||||||
"release_version": ctx.Config().ReleaseVersion(),
|
}
|
||||||
"package": module.properties.Package,
|
}
|
||||||
"declarations": android.JoinPathsWithPrefix(declarationFiles, "--declarations "),
|
inputFiles := make([]android.Path, len(declarationFiles))
|
||||||
"values": joinAndPrefix(" --values ", module.properties.Values),
|
copy(inputFiles, declarationFiles)
|
||||||
"default-permission": optionalVariable(" --default-permission ", defaultPermission),
|
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 {
|
android.SetProvider(ctx, android.AconfigDeclarationsProviderKey, providerData[""])
|
||||||
args["container"] = "--container " + module.properties.Container
|
android.SetProvider(ctx, android.AconfigReleaseDeclarationsProviderKey, providerData)
|
||||||
}
|
|
||||||
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,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
package aconfig
|
package aconfig
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -17,6 +17,7 @@ package aconfig
|
|||||||
import (
|
import (
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A singleton module that collects all of the aconfig flags declared in the
|
// 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
|
// 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.
|
// doesn't need to pull from multiple builds and merge them.
|
||||||
func AllAconfigDeclarationsFactory() android.Singleton {
|
func AllAconfigDeclarationsFactory() android.Singleton {
|
||||||
return &allAconfigDeclarationsSingleton{}
|
return &allAconfigDeclarationsSingleton{releaseMap: make(map[string]allAconfigReleaseDeclarationsSingleton)}
|
||||||
}
|
}
|
||||||
|
|
||||||
type allAconfigDeclarationsSingleton struct {
|
type allAconfigReleaseDeclarationsSingleton struct {
|
||||||
intermediateBinaryProtoPath android.OutputPath
|
intermediateBinaryProtoPath android.OutputPath
|
||||||
intermediateTextProtoPath 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) {
|
func (this *allAconfigDeclarationsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
|
||||||
// Find all of the aconfig_declarations modules
|
for _, rcName := range append([]string{""}, ctx.Config().ReleaseAconfigExtraReleaseConfigs()...) {
|
||||||
var packages = make(map[string]int)
|
// Find all of the aconfig_declarations modules
|
||||||
var cacheFiles android.Paths
|
var packages = make(map[string]int)
|
||||||
ctx.VisitAllModules(func(module android.Module) {
|
var cacheFiles android.Paths
|
||||||
decl, ok := android.SingletonModuleProvider(ctx, module, android.AconfigDeclarationsProviderKey)
|
ctx.VisitAllModules(func(module android.Module) {
|
||||||
if !ok {
|
decl, ok := android.SingletonModuleProvider(ctx, module, android.AconfigReleaseDeclarationsProviderKey)
|
||||||
return
|
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
|
if numOffendingPkg > 0 {
|
||||||
for pkg, cnt := range packages {
|
panic(fmt.Errorf("Only one aconfig_declarations allowed for each package."))
|
||||||
if cnt > 1 {
|
|
||||||
fmt.Printf("%d aconfig_declarations found for package %s\n", cnt, pkg)
|
|
||||||
numOffendingPkg++
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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) {
|
func (this *allAconfigDeclarationsSingleton) MakeVars(ctx android.MakeVarsContext) {
|
||||||
ctx.DistForGoal("droid", this.intermediateBinaryProtoPath)
|
for _, rcName := range this.sortedConfigNames() {
|
||||||
for _, goal := range []string{"docs", "droid", "sdk"} {
|
ctx.DistForGoal("droid", this.releaseMap[rcName].intermediateBinaryProtoPath)
|
||||||
ctx.DistForGoalWithFilename(goal, this.intermediateBinaryProtoPath, "flags.pb")
|
for _, goal := range []string{"docs", "droid", "sdk"} {
|
||||||
ctx.DistForGoalWithFilename(goal, this.intermediateTextProtoPath, "flags.textproto")
|
ctx.DistForGoalWithFilename(goal, this.releaseMap[rcName].intermediateBinaryProtoPath, assembleFileName(rcName, "flags.pb"))
|
||||||
|
ctx.DistForGoalWithFilename(goal, this.releaseMap[rcName].intermediateTextProtoPath, assembleFileName(rcName, "flags.textproto"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -23,7 +23,25 @@ import (
|
|||||||
var PrepareForTestWithAconfigBuildComponents = android.FixtureRegisterWithContext(RegisterBuildComponents)
|
var PrepareForTestWithAconfigBuildComponents = android.FixtureRegisterWithContext(RegisterBuildComponents)
|
||||||
|
|
||||||
func runTest(t *testing.T, errorHandler android.FixtureErrorHandler, bp string) *android.TestResult {
|
func runTest(t *testing.T, errorHandler android.FixtureErrorHandler, bp string) *android.TestResult {
|
||||||
return android.GroupFixturePreparers(PrepareForTestWithAconfigBuildComponents).
|
return PrepareForTest(t).
|
||||||
ExtendWithErrorHandler(errorHandler).
|
ExtendWithErrorHandler(errorHandler).
|
||||||
RunTestWithBp(t, bp)
|
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
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@@ -43,6 +43,10 @@ type AconfigDeclarationsProviderData struct {
|
|||||||
|
|
||||||
var AconfigDeclarationsProviderKey = blueprint.NewProvider[AconfigDeclarationsProviderData]()
|
var AconfigDeclarationsProviderKey = blueprint.NewProvider[AconfigDeclarationsProviderData]()
|
||||||
|
|
||||||
|
type AconfigReleaseDeclarationsProviderData map[string]AconfigDeclarationsProviderData
|
||||||
|
|
||||||
|
var AconfigReleaseDeclarationsProviderKey = blueprint.NewProvider[AconfigReleaseDeclarationsProviderData]()
|
||||||
|
|
||||||
type ModeInfo struct {
|
type ModeInfo struct {
|
||||||
Container string
|
Container string
|
||||||
Mode string
|
Mode string
|
||||||
@@ -112,6 +116,8 @@ func aconfigUpdateAndroidBuildActions(ctx ModuleContext) {
|
|||||||
if dep, ok := OtherModuleProvider(ctx, module, AconfigDeclarationsProviderKey); ok {
|
if dep, ok := OtherModuleProvider(ctx, module, AconfigDeclarationsProviderKey); ok {
|
||||||
mergedAconfigFiles[dep.Container] = append(mergedAconfigFiles[dep.Container], dep.IntermediateCacheOutputPath)
|
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 {
|
if dep, ok := OtherModuleProvider(ctx, module, AconfigPropagatingProviderKey); ok {
|
||||||
for container, v := range dep.AconfigFiles {
|
for container, v := range dep.AconfigFiles {
|
||||||
mergedAconfigFiles[container] = append(mergedAconfigFiles[container], v...)
|
mergedAconfigFiles[container] = append(mergedAconfigFiles[container], v...)
|
||||||
|
@@ -198,6 +198,33 @@ func (c Config) ReleaseAconfigValueSets() []string {
|
|||||||
return c.config.productVariables.ReleaseAconfigValueSets
|
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
|
// The flag default permission value passed to aconfig
|
||||||
// derived from RELEASE_ACONFIG_FLAG_DEFAULT_PERMISSION
|
// derived from RELEASE_ACONFIG_FLAG_DEFAULT_PERMISSION
|
||||||
func (c Config) ReleaseAconfigFlagDefaultPermission() string {
|
func (c Config) ReleaseAconfigFlagDefaultPermission() string {
|
||||||
|
@@ -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) {
|
func TestConfiguredJarList(t *testing.T) {
|
||||||
list1 := CreateTestConfiguredJarList([]string{"apex1:jarA"})
|
list1 := CreateTestConfiguredJarList([]string{"apex1:jarA"})
|
||||||
|
|
||||||
|
@@ -226,8 +226,16 @@ func (config *ReleaseConfig) GenerateReleaseConfig(configs *ReleaseConfigs) erro
|
|||||||
config.PriorStagesMap[priorStage] = true
|
config.PriorStagesMap[priorStage] = true
|
||||||
}
|
}
|
||||||
myDirsMap[contrib.DeclarationIndex] = true
|
myDirsMap[contrib.DeclarationIndex] = true
|
||||||
if config.AconfigFlagsOnly && len(contrib.FlagValues) > 0 {
|
if config.AconfigFlagsOnly {
|
||||||
return fmt.Errorf("%s does not allow build flag overrides", config.Name)
|
// 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 {
|
for _, value := range contrib.FlagValues {
|
||||||
name := *value.proto.Name
|
name := *value.proto.Name
|
||||||
@@ -256,7 +264,7 @@ func (config *ReleaseConfig) GenerateReleaseConfig(configs *ReleaseConfigs) erro
|
|||||||
myAconfigValueSets := []string{}
|
myAconfigValueSets := []string{}
|
||||||
myAconfigValueSetsMap := map[string]bool{}
|
myAconfigValueSetsMap := map[string]bool{}
|
||||||
for _, v := range strings.Split(releaseAconfigValueSets.Value.GetStringValue(), " ") {
|
for _, v := range strings.Split(releaseAconfigValueSets.Value.GetStringValue(), " ") {
|
||||||
if myAconfigValueSetsMap[v] {
|
if v == "" || myAconfigValueSetsMap[v] {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
myAconfigValueSetsMap[v] = true
|
myAconfigValueSetsMap[v] = true
|
||||||
@@ -320,6 +328,23 @@ func (config *ReleaseConfig) WriteMakefile(outFile, targetRelease string, config
|
|||||||
makeVars := make(map[string]string)
|
makeVars := make(map[string]string)
|
||||||
|
|
||||||
myFlagArtifacts := config.FlagArtifacts.Clone()
|
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.
|
// Sort the flags by name first.
|
||||||
names := myFlagArtifacts.SortedFlagNames()
|
names := myFlagArtifacts.SortedFlagNames()
|
||||||
partitions := make(map[string][]string)
|
partitions := make(map[string][]string)
|
||||||
|
Reference in New Issue
Block a user