diff options
70 files changed, 2101 insertions, 1420 deletions
diff --git a/Android.bp b/Android.bp index 2c0ef4740..682711d42 100644 --- a/Android.bp +++ b/Android.bp @@ -122,12 +122,15 @@ dexpreopt_systemserver_check { } // buildinfo.prop contains common properties for system/build.prop, like ro.build.version.* +// TODO(b/322090587): merge this to gen_build_prop.py script. buildinfo_prop { name: "buildinfo.prop", // not installable because this will be included to system/build.prop installable: false, + product_config: ":product_config", + // Currently, only microdroid can refer to buildinfo.prop visibility: ["//packages/modules/Virtualization/microdroid"], } @@ -136,3 +139,8 @@ buildinfo_prop { all_apex_contributions { name: "all_apex_contributions", } + +product_config { + name: "product_config", + visibility: ["//device/google/cuttlefish/system_image"], +} diff --git a/aconfig/aconfig_declarations.go b/aconfig/aconfig_declarations.go index dac0ae36d..9e3d291b6 100644 --- a/aconfig/aconfig_declarations.go +++ b/aconfig/aconfig_declarations.go @@ -15,6 +15,8 @@ package aconfig import ( + "path/filepath" + "slices" "strings" "android/soong/android" @@ -22,9 +24,15 @@ import ( "github.com/google/blueprint" ) +type AconfigReleaseConfigValue struct { + ReleaseConfig string + Values []string `blueprint:"mutated"` +} + type DeclarationsModule struct { android.ModuleBase android.DefaultableModuleBase + blueprint.IncrementalModule // Properties for "aconfig_declarations" properties struct { @@ -34,8 +42,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 +67,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 +95,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 +120,115 @@ 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()) + } + } } } } }) - - // 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), - } - if len(module.properties.Container) > 0 { - args["container"] = "--container " + module.properties.Container + 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, 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, + } } - ctx.Build(pctx, android.BuildParams{ - Rule: aconfigRule, - Output: intermediateCacheFilePath, - Inputs: inputFiles, - Description: "aconfig_declarations", - Args: args, - }) + android.SetProvider(ctx, android.AconfigDeclarationsProviderKey, providerData[""]) + android.SetProvider(ctx, android.AconfigReleaseDeclarationsProviderKey, providerData) +} - intermediateDumpFilePath := android.PathForModuleOut(ctx, "intermediate.txt") - ctx.Build(pctx, android.BuildParams{ - Rule: aconfigTextRule, - Output: intermediateDumpFilePath, - Inputs: android.Paths{intermediateCacheFilePath}, - Description: "aconfig_text", - }) +func (module *DeclarationsModule) BuildActionProviderKeys() []blueprint.AnyProviderKey { + return []blueprint.AnyProviderKey{android.AconfigDeclarationsProviderKey} +} - android.SetProvider(ctx, android.AconfigDeclarationsProviderKey, android.AconfigDeclarationsProviderData{ - Package: module.properties.Package, - Container: module.properties.Container, - Exportable: module.properties.Exportable, - IntermediateCacheOutputPath: intermediateCacheFilePath, - IntermediateDumpOutputPath: intermediateDumpFilePath, - }) +func (module *DeclarationsModule) PackageContextPath() string { + return pkgPath } + +func (module *DeclarationsModule) CachedRules() []blueprint.Rule { + return []blueprint.Rule{aconfigRule, aconfigTextRule} +} + +var _ blueprint.Incremental = &DeclarationsModule{} diff --git a/aconfig/aconfig_declarations_test.go b/aconfig/aconfig_declarations_test.go index c37274c71..548329523 100644 --- a/aconfig/aconfig_declarations_test.go +++ b/aconfig/aconfig_declarations_test.go @@ -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()) + } + } + } +} diff --git a/aconfig/all_aconfig_declarations.go b/aconfig/all_aconfig_declarations.go index e771d0597..0437c266f 100644 --- a/aconfig/all_aconfig_declarations.go +++ b/aconfig/all_aconfig_declarations.go @@ -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 - } - cacheFiles = append(cacheFiles, decl.IntermediateCacheOutputPath) - packages[decl.Package]++ - }) + 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++ + 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.")) - } + 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 (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) - 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) + // 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) + } } 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")) + } } } diff --git a/aconfig/init.go b/aconfig/init.go index 46554676b..256b213cc 100644 --- a/aconfig/init.go +++ b/aconfig/init.go @@ -15,13 +15,16 @@ package aconfig import ( + "encoding/gob" + "android/soong/android" "github.com/google/blueprint" ) var ( - pctx = android.NewPackageContext("android/soong/aconfig") + pkgPath = "android/soong/aconfig" + pctx = android.NewPackageContext(pkgPath) // For aconfig_declarations: Generate cache file aconfigRule = pctx.AndroidStaticRule("aconfig", @@ -106,6 +109,9 @@ func init() { RegisterBuildComponents(android.InitRegistrationContext) pctx.HostBinToolVariable("aconfig", "aconfig") pctx.HostBinToolVariable("soong_zip", "soong_zip") + + gob.Register(android.AconfigDeclarationsProviderData{}) + gob.Register(android.ModuleOutPath{}) } func RegisterBuildComponents(ctx android.RegistrationContext) { diff --git a/aconfig/testing.go b/aconfig/testing.go index f6489ec3f..4ceb6b3e5 100644 --- a/aconfig/testing.go +++ b/aconfig/testing.go @@ -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 + } + }), + ) +} diff --git a/android/Android.bp b/android/Android.bp index 9ce8cdcd2..ce8c9b0b3 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -38,6 +38,7 @@ bootstrap_go_package { "arch_list.go", "arch_module_context.go", "base_module_context.go", + "build_prop.go", "buildinfo_prop.go", "config.go", "test_config.go", @@ -83,6 +84,7 @@ bootstrap_go_package { "plugin.go", "prebuilt.go", "prebuilt_build_tool.go", + "product_config.go", "proto.go", "provider.go", "raw_files.go", diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go index ee9891df1..a47e80f03 100644 --- a/android/aconfig_providers.go +++ b/android/aconfig_providers.go @@ -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...) diff --git a/android/androidmk.go b/android/androidmk.go index 66f42f97c..9699ce5b8 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -499,6 +499,7 @@ type fillInEntriesContext interface { Config() Config moduleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) ModuleType(module blueprint.Module) string + OtherModulePropertyErrorf(module Module, property string, fmt string, args ...interface{}) } func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod blueprint.Module) { @@ -514,7 +515,7 @@ func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod blueprint if a.Include == "" { a.Include = "$(BUILD_PREBUILT)" } - a.Required = append(a.Required, amod.RequiredModuleNames()...) + a.Required = append(a.Required, amod.RequiredModuleNames(ctx)...) a.Host_required = append(a.Host_required, amod.HostRequiredModuleNames()...) a.Target_required = append(a.Target_required, amod.TargetRequiredModuleNames()...) diff --git a/android/apex.go b/android/apex.go index 2ac6ed08d..683e50162 100644 --- a/android/apex.go +++ b/android/apex.go @@ -84,6 +84,9 @@ type ApexInfo struct { // Returns the name of the test apexes that this module is included in. TestApexes []string + + // Returns the name of the overridden apex (com.android.foo) + BaseApexName string } // AllApexInfo holds the ApexInfo of all apexes that include this module. diff --git a/android/build_prop.go b/android/build_prop.go new file mode 100644 index 000000000..45c17c35b --- /dev/null +++ b/android/build_prop.go @@ -0,0 +1,125 @@ +// Copyright 2024 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +import ( + "github.com/google/blueprint/proptools" +) + +func init() { + ctx := InitRegistrationContext + ctx.RegisterModuleType("build_prop", buildPropFactory) +} + +type buildPropProperties struct { + // Output file name. Defaults to "build.prop" + Stem *string + + // List of prop names to exclude. This affects not only common build properties but also + // properties in prop_files. + Block_list []string + + // Path to the input prop files. The contents of the files are directly + // emitted to the output + Prop_files []string `android:"path"` + + // Files to be appended at the end of build.prop. These files are appended after + // post_process_props without any further checking. + Footer_files []string `android:"path"` + + // Path to a JSON file containing product configs. + Product_config *string `android:"path"` +} + +type buildPropModule struct { + ModuleBase + + properties buildPropProperties + + outputFilePath OutputPath + installPath InstallPath +} + +func (p *buildPropModule) stem() string { + return proptools.StringDefault(p.properties.Stem, "build.prop") +} + +func (p *buildPropModule) GenerateAndroidBuildActions(ctx ModuleContext) { + p.outputFilePath = PathForModuleOut(ctx, "build.prop").OutputPath + if !ctx.Config().KatiEnabled() { + WriteFileRule(ctx, p.outputFilePath, "# no build.prop if kati is disabled") + return + } + + partition := p.PartitionTag(ctx.DeviceConfig()) + if partition != "system" { + ctx.PropertyErrorf("partition", "unsupported partition %q: only \"system\" is supported", partition) + return + } + + rule := NewRuleBuilder(pctx, ctx) + + config := ctx.Config() + + cmd := rule.Command().BuiltTool("gen_build_prop") + + cmd.FlagWithInput("--build-hostname-file=", config.BuildHostnameFile(ctx)) + cmd.FlagWithInput("--build-number-file=", config.BuildNumberFile(ctx)) + // shouldn't depend on BuildFingerprintFile and BuildThumbprintFile to prevent from rebuilding + // on every incremental build. + cmd.FlagWithArg("--build-fingerprint-file=", config.BuildFingerprintFile(ctx).String()) + // Export build thumbprint only if the product has specified at least one oem fingerprint property + // b/17888863 + if shouldAddBuildThumbprint(config) { + // In the previous make implementation, a dependency was not added on the thumbprint file + cmd.FlagWithArg("--build-thumbprint-file=", config.BuildThumbprintFile(ctx).String()) + } + cmd.FlagWithArg("--build-username=", config.Getenv("BUILD_USERNAME")) + // shouldn't depend on BUILD_DATETIME_FILE to prevent from rebuilding on every incremental + // build. + cmd.FlagWithArg("--date-file=", ctx.Config().Getenv("BUILD_DATETIME_FILE")) + cmd.FlagWithInput("--platform-preview-sdk-fingerprint-file=", ApiFingerprintPath(ctx)) + cmd.FlagWithInput("--product-config=", PathForModuleSrc(ctx, proptools.String(p.properties.Product_config))) + cmd.FlagWithArg("--partition=", partition) + cmd.FlagWithOutput("--out=", p.outputFilePath) + + postProcessCmd := rule.Command().BuiltTool("post_process_props") + if ctx.DeviceConfig().BuildBrokenDupSysprop() { + postProcessCmd.Flag("--allow-dup") + } + postProcessCmd.FlagWithArg("--sdk-version ", config.PlatformSdkVersion().String()) + postProcessCmd.FlagWithInput("--kernel-version-file-for-uffd-gc ", PathForOutput(ctx, "dexpreopt/kernel_version_for_uffd_gc.txt")) + postProcessCmd.Text(p.outputFilePath.String()) + postProcessCmd.Flags(p.properties.Block_list) + + rule.Command().Text("echo").Text(proptools.NinjaAndShellEscape("# end of file")).FlagWithArg(">> ", p.outputFilePath.String()) + + rule.Build(ctx.ModuleName(), "generating build.prop") + + p.installPath = PathForModuleInstall(ctx) + ctx.InstallFile(p.installPath, p.stem(), p.outputFilePath) + + ctx.SetOutputFiles(Paths{p.outputFilePath}, "") +} + +// build_prop module generates {partition}/build.prop file. At first common build properties are +// printed based on Soong config variables. And then prop_files are printed as-is. Finally, +// post_process_props tool is run to check if the result build.prop is valid or not. +func buildPropFactory() Module { + module := &buildPropModule{} + module.AddProperties(&module.properties) + InitAndroidArchModule(module, DeviceSupported, MultilibCommon) + return module +} diff --git a/android/buildinfo_prop.go b/android/buildinfo_prop.go index 083f3efcb..defbff0b0 100644 --- a/android/buildinfo_prop.go +++ b/android/buildinfo_prop.go @@ -16,7 +16,6 @@ package android import ( "fmt" - "strings" "github.com/google/blueprint/proptools" ) @@ -29,6 +28,8 @@ func init() { type buildinfoPropProperties struct { // Whether this module is directly installable to one of the partitions. Default: true. Installable *bool + + Product_config *string `android:"path"` } type buildinfoPropModule struct { @@ -54,24 +55,6 @@ func (p *buildinfoPropModule) OutputFiles(tag string) (Paths, error) { return Paths{p.outputFilePath}, nil } -func getBuildVariant(config Config) string { - if config.Eng() { - return "eng" - } else if config.Debuggable() { - return "userdebug" - } else { - return "user" - } -} - -func getBuildFlavor(config Config) string { - buildFlavor := config.DeviceProduct() + "-" + getBuildVariant(config) - if InList("address", config.SanitizeDevice()) && !strings.Contains(buildFlavor, "_asan") { - buildFlavor += "_asan" - } - return buildFlavor -} - func shouldAddBuildThumbprint(config Config) bool { knownOemProperties := []string{ "ro.product.brand", @@ -101,63 +84,27 @@ func (p *buildinfoPropModule) GenerateAndroidBuildActions(ctx ModuleContext) { rule := NewRuleBuilder(pctx, ctx) config := ctx.Config() - buildVariant := getBuildVariant(config) - buildFlavor := getBuildFlavor(config) cmd := rule.Command().BuiltTool("buildinfo") - if config.BoardUseVbmetaDigestInFingerprint() { - cmd.Flag("--use-vbmeta-digest-in-fingerprint") - } - - cmd.FlagWithArg("--build-flavor=", buildFlavor) cmd.FlagWithInput("--build-hostname-file=", config.BuildHostnameFile(ctx)) - cmd.FlagWithArg("--build-id=", config.BuildId()) - cmd.FlagWithArg("--build-keys=", config.BuildKeys()) - // Note: depending on BuildNumberFile will cause the build.prop file to be rebuilt // every build, but that's intentional. cmd.FlagWithInput("--build-number-file=", config.BuildNumberFile(ctx)) + // Export build thumbprint only if the product has specified at least one oem fingerprint property + // b/17888863 if shouldAddBuildThumbprint(config) { // In the previous make implementation, a dependency was not added on the thumbprint file cmd.FlagWithArg("--build-thumbprint-file=", config.BuildThumbprintFile(ctx).String()) } - - cmd.FlagWithArg("--build-type=", config.BuildType()) cmd.FlagWithArg("--build-username=", config.Getenv("BUILD_USERNAME")) - cmd.FlagWithArg("--build-variant=", buildVariant) - cmd.FlagForEachArg("--cpu-abis=", config.DeviceAbi()) - // Technically we should also have a dependency on BUILD_DATETIME_FILE, // but it can be either an absolute or relative path, which is hard to turn into // a Path object. So just rely on the BuildNumberFile always changing to cause // us to rebuild. cmd.FlagWithArg("--date-file=", ctx.Config().Getenv("BUILD_DATETIME_FILE")) - - if len(config.ProductLocales()) > 0 { - cmd.FlagWithArg("--default-locale=", config.ProductLocales()[0]) - } - - cmd.FlagForEachArg("--default-wifi-channels=", config.ProductDefaultWifiChannels()) - cmd.FlagWithArg("--device=", config.DeviceName()) - if config.DisplayBuildNumber() { - cmd.Flag("--display-build-number") - } - - cmd.FlagWithArg("--platform-base-os=", config.PlatformBaseOS()) - cmd.FlagWithArg("--platform-display-version=", config.PlatformDisplayVersionName()) - cmd.FlagWithArg("--platform-min-supported-target-sdk-version=", config.PlatformMinSupportedTargetSdkVersion()) cmd.FlagWithInput("--platform-preview-sdk-fingerprint-file=", ApiFingerprintPath(ctx)) - cmd.FlagWithArg("--platform-preview-sdk-version=", config.PlatformPreviewSdkVersion()) - cmd.FlagWithArg("--platform-sdk-version=", config.PlatformSdkVersion().String()) - cmd.FlagWithArg("--platform-security-patch=", config.PlatformSecurityPatch()) - cmd.FlagWithArg("--platform-version=", config.PlatformVersionName()) - cmd.FlagWithArg("--platform-version-codename=", config.PlatformSdkCodename()) - cmd.FlagForEachArg("--platform-version-all-codenames=", config.PlatformVersionActiveCodenames()) - cmd.FlagWithArg("--platform-version-known-codenames=", config.PlatformVersionKnownCodenames()) - cmd.FlagWithArg("--platform-version-last-stable=", config.PlatformVersionLastStable()) - cmd.FlagWithArg("--product=", config.DeviceProduct()) - + cmd.FlagWithInput("--product-config=", PathForModuleSrc(ctx, proptools.String(p.properties.Product_config))) cmd.FlagWithOutput("--out=", p.outputFilePath) rule.Build(ctx.ModuleName(), "generating buildinfo props") diff --git a/android/config.go b/android/config.go index da76f0dd2..cda01f090 100644 --- a/android/config.go +++ b/android/config.go @@ -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 { @@ -779,6 +806,17 @@ func (c *config) DisplayBuildNumber() bool { return Bool(c.productVariables.DisplayBuildNumber) } +// BuildFingerprintFile returns the path to a text file containing metadata +// representing the current build's fingerprint. +// +// Rules that want to reference the build fingerprint should read from this file +// without depending on it. They will run whenever their other dependencies +// require them to run and get the current build fingerprint. This ensures they +// don't rebuild on every incremental build when the build number changes. +func (c *config) BuildFingerprintFile(ctx PathContext) Path { + return PathForArbitraryOutput(ctx, "target", "product", c.DeviceName(), String(c.productVariables.BuildFingerprintFile)) +} + // BuildNumberFile returns the path to a text file containing metadata // representing the current build's number. // @@ -1314,10 +1352,6 @@ func (c *config) PrebuiltHiddenApiDir(_ PathContext) string { return String(c.productVariables.PrebuiltHiddenApiDir) } -func (c *config) IsVndkDeprecated() bool { - return !Bool(c.productVariables.KeepVndk) -} - func (c *config) VendorApiLevel() string { return String(c.productVariables.VendorApiLevel) } @@ -1882,6 +1916,10 @@ func (c *deviceConfig) BuildBrokenDontCheckSystemSdk() bool { return c.config.productVariables.BuildBrokenDontCheckSystemSdk } +func (c *deviceConfig) BuildBrokenDupSysprop() bool { + return c.config.productVariables.BuildBrokenDupSysprop +} + func (c *config) BuildWarningBadOptionalUsesLibsAllowlist() []string { return c.productVariables.BuildWarningBadOptionalUsesLibsAllowlist } diff --git a/android/config_test.go b/android/config_test.go index 7d327a27e..ca7c7f8b4 100644 --- a/android/config_test.go +++ b/android/config_test.go @@ -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"}) diff --git a/android/module.go b/android/module.go index dc585d295..b43815063 100644 --- a/android/module.go +++ b/android/module.go @@ -113,7 +113,7 @@ type Module interface { // Get information about the properties that can contain visibility rules. visibilityProperties() []visibilityProperty - RequiredModuleNames() []string + RequiredModuleNames(ctx ConfigAndErrorContext) []string HostRequiredModuleNames() []string TargetRequiredModuleNames() []string @@ -422,7 +422,7 @@ type commonProperties struct { Vintf_fragments []string `android:"path"` // names of other modules to install if this module is installed - Required []string `android:"arch_variant"` + Required proptools.Configurable[[]string] `android:"arch_variant"` // names of other modules to install on host if this module is installed Host_required []string `android:"arch_variant"` @@ -1101,7 +1101,7 @@ func addRequiredDeps(ctx BottomUpMutatorContext) { hostTargets = append(hostTargets, ctx.Config().BuildOSCommonTarget) if ctx.Device() { - for _, depName := range ctx.Module().RequiredModuleNames() { + for _, depName := range ctx.Module().RequiredModuleNames(ctx) { for _, target := range deviceTargets { addDep(target, depName) } @@ -1114,7 +1114,7 @@ func addRequiredDeps(ctx BottomUpMutatorContext) { } if ctx.Host() { - for _, depName := range ctx.Module().RequiredModuleNames() { + for _, depName := range ctx.Module().RequiredModuleNames(ctx) { for _, target := range hostTargets { // When a host module requires another host module, don't make a // dependency if they have different OSes (i.e. hostcross). @@ -1619,8 +1619,8 @@ func (m *ModuleBase) InRecovery() bool { return m.base().commonProperties.ImageVariation == RecoveryVariation } -func (m *ModuleBase) RequiredModuleNames() []string { - return m.base().commonProperties.Required +func (m *ModuleBase) RequiredModuleNames(ctx ConfigAndErrorContext) []string { + return m.base().commonProperties.Required.GetOrDefault(m.ConfigurableEvaluator(ctx), nil) } func (m *ModuleBase) HostRequiredModuleNames() []string { @@ -1913,9 +1913,54 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) return } - m.module.GenerateAndroidBuildActions(ctx) - if ctx.Failed() { - return + incrementalAnalysis := false + incrementalEnabled := false + var cacheKey *blueprint.BuildActionCacheKey = nil + var incrementalModule *blueprint.Incremental = nil + if ctx.bp.GetIncrementalEnabled() { + if im, ok := m.module.(blueprint.Incremental); ok { + incrementalModule = &im + incrementalEnabled = im.IncrementalSupported() + incrementalAnalysis = ctx.bp.GetIncrementalAnalysis() && incrementalEnabled + } + } + if incrementalEnabled { + hash, err := proptools.CalculateHash(m.GetProperties()) + if err != nil { + ctx.ModuleErrorf("failed to calculate properties hash: %s", err) + return + } + cacheInput := new(blueprint.BuildActionCacheInput) + cacheInput.PropertiesHash = hash + ctx.VisitDirectDeps(func(module Module) { + cacheInput.ProvidersHash = + append(cacheInput.ProvidersHash, ctx.bp.OtherModuleProviderInitialValueHashes(module)) + }) + hash, err = proptools.CalculateHash(&cacheInput) + if err != nil { + ctx.ModuleErrorf("failed to calculate cache input hash: %s", err) + return + } + cacheKey = &blueprint.BuildActionCacheKey{ + Id: ctx.bp.ModuleId(), + InputHash: hash, + } + } + + restored := false + if incrementalAnalysis && cacheKey != nil { + restored = ctx.bp.RestoreBuildActions(cacheKey, incrementalModule) + } + + if !restored { + m.module.GenerateAndroidBuildActions(ctx) + if ctx.Failed() { + return + } + } + + if incrementalEnabled && cacheKey != nil { + ctx.bp.CacheBuildActions(cacheKey, incrementalModule) } // Create the set of tagged dist files after calling GenerateAndroidBuildActions @@ -1992,7 +2037,7 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) TargetDependencies: targetRequired, HostDependencies: hostRequired, Data: data, - Required: m.RequiredModuleNames(), + Required: m.RequiredModuleNames(ctx), } SetProvider(ctx, ModuleInfoJSONProvider, m.moduleInfoJSON) } diff --git a/android/module_context.go b/android/module_context.go index 591e270f0..e2677a4f6 100644 --- a/android/module_context.go +++ b/android/module_context.go @@ -183,7 +183,7 @@ type ModuleContext interface { InstallInVendor() bool InstallForceOS() (*OsType, *ArchType) - RequiredModuleNames() []string + RequiredModuleNames(ctx ConfigAndErrorContext) []string HostRequiredModuleNames() []string TargetRequiredModuleNames() []string @@ -755,8 +755,8 @@ func (m *moduleContext) ExpandOptionalSource(srcFile *string, _ string) Optional return OptionalPath{} } -func (m *moduleContext) RequiredModuleNames() []string { - return m.module.RequiredModuleNames() +func (m *moduleContext) RequiredModuleNames(ctx ConfigAndErrorContext) []string { + return m.module.RequiredModuleNames(ctx) } func (m *moduleContext) HostRequiredModuleNames() []string { diff --git a/android/paths.go b/android/paths.go index edc07000c..adbee70be 100644 --- a/android/paths.go +++ b/android/paths.go @@ -15,6 +15,9 @@ package android import ( + "bytes" + "encoding/gob" + "errors" "fmt" "os" "path/filepath" @@ -1068,6 +1071,28 @@ type basePath struct { rel string } +func (p basePath) GobEncode() ([]byte, error) { + w := new(bytes.Buffer) + encoder := gob.NewEncoder(w) + err := errors.Join(encoder.Encode(p.path), encoder.Encode(p.rel)) + if err != nil { + return nil, err + } + + return w.Bytes(), nil +} + +func (p *basePath) GobDecode(data []byte) error { + r := bytes.NewBuffer(data) + decoder := gob.NewDecoder(r) + err := errors.Join(decoder.Decode(&p.path), decoder.Decode(&p.rel)) + if err != nil { + return err + } + + return nil +} + func (p basePath) Ext() string { return filepath.Ext(p.path) } @@ -1306,6 +1331,28 @@ type OutputPath struct { fullPath string } +func (p OutputPath) GobEncode() ([]byte, error) { + w := new(bytes.Buffer) + encoder := gob.NewEncoder(w) + err := errors.Join(encoder.Encode(p.basePath), encoder.Encode(p.soongOutDir), encoder.Encode(p.fullPath)) + if err != nil { + return nil, err + } + + return w.Bytes(), nil +} + +func (p *OutputPath) GobDecode(data []byte) error { + r := bytes.NewBuffer(data) + decoder := gob.NewDecoder(r) + err := errors.Join(decoder.Decode(&p.basePath), decoder.Decode(&p.soongOutDir), decoder.Decode(&p.fullPath)) + if err != nil { + return err + } + + return nil +} + func (p OutputPath) withRel(rel string) OutputPath { p.basePath = p.basePath.withRel(rel) p.fullPath = filepath.Join(p.fullPath, rel) diff --git a/android/product_config.go b/android/product_config.go new file mode 100644 index 000000000..20b29a7c4 --- /dev/null +++ b/android/product_config.go @@ -0,0 +1,58 @@ +// Copyright 2024 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +import "github.com/google/blueprint/proptools" + +func init() { + ctx := InitRegistrationContext + ctx.RegisterModuleType("product_config", productConfigFactory) +} + +type productConfigModule struct { + ModuleBase +} + +func (p *productConfigModule) GenerateAndroidBuildActions(ctx ModuleContext) { + if ctx.ModuleName() != "product_config" || ctx.ModuleDir() != "build/soong" { + ctx.ModuleErrorf("There can only be one product_config module in build/soong") + return + } + outputFilePath := PathForModuleOut(ctx, p.Name()+".json").OutputPath + + // DeviceProduct can be null so calling ctx.Config().DeviceProduct() may cause null dereference + targetProduct := proptools.String(ctx.Config().config.productVariables.DeviceProduct) + if targetProduct != "" { + targetProduct += "." + } + soongVariablesPath := PathForOutput(ctx, "soong."+targetProduct+"variables") + extraVariablesPath := PathForOutput(ctx, "soong."+targetProduct+"extra.variables") + + rule := NewRuleBuilder(pctx, ctx) + rule.Command().BuiltTool("merge_json"). + Output(outputFilePath). + Input(soongVariablesPath). + Input(extraVariablesPath). + rule.Build("product_config.json", "building product_config.json") + + ctx.SetOutputFiles(Paths{outputFilePath}, "") +} + +// product_config module exports product variables and extra variables as a JSON file. +func productConfigFactory() Module { + module := &productConfigModule{} + InitAndroidModule(module) + return module +} diff --git a/android/soongconfig/modules.go b/android/soongconfig/modules.go index 87af774fd..f6046d00c 100644 --- a/android/soongconfig/modules.go +++ b/android/soongconfig/modules.go @@ -824,11 +824,16 @@ func (s *listVariable) printfIntoPropertyRecursive(fieldName []string, propStruc } field.Set(newField) case reflect.Struct: - fieldName = append(fieldName, propStruct.Type().Field(i).Name) - if err := s.printfIntoPropertyRecursive(fieldName, field, configValues); err != nil { - return err + if proptools.IsConfigurable(field.Type()) { + fieldName = append(fieldName, propStruct.Type().Field(i).Name) + return fmt.Errorf("soong_config_variables.%s.%s: list variables are not supported on configurable properties", s.variable, strings.Join(fieldName, ".")) + } else { + fieldName = append(fieldName, propStruct.Type().Field(i).Name) + if err := s.printfIntoPropertyRecursive(fieldName, field, configValues); err != nil { + return err + } + fieldName = fieldName[:len(fieldName)-1] } - fieldName = fieldName[:len(fieldName)-1] default: fieldName = append(fieldName, propStruct.Type().Field(i).Name) return fmt.Errorf("soong_config_variables.%s.%s: unsupported property type %q", s.variable, strings.Join(fieldName, "."), kind) diff --git a/android/testing.go b/android/testing.go index 6fb2997cb..8dd467dce 100644 --- a/android/testing.go +++ b/android/testing.go @@ -224,6 +224,10 @@ func (ctx *TestContext) OtherModuleProviderAdaptor() OtherModuleProviderContext }) } +func (ctx *TestContext) OtherModulePropertyErrorf(module Module, property string, fmt_ string, args ...interface{}) { + panic(fmt.Sprintf(fmt_, args...)) +} + // registeredComponentOrder defines the order in which a sortableComponent type is registered at // runtime and provides support for reordering the components registered for a test in the same // way. diff --git a/android/updatable_modules.go b/android/updatable_modules.go index 1548170f9..dd7dc2c2f 100644 --- a/android/updatable_modules.go +++ b/android/updatable_modules.go @@ -33,4 +33,4 @@ package android // * AOSP - xx9990000 // * x-mainline-prod - xx9990000 // * master - 990090000 -const DefaultUpdatableModuleVersion = "990090000" +const DefaultUpdatableModuleVersion = "350090000" diff --git a/android/variable.go b/android/variable.go index 16338166b..2cdcd5355 100644 --- a/android/variable.go +++ b/android/variable.go @@ -199,11 +199,12 @@ type ProductVariables struct { // Suffix to add to generated Makefiles Make_suffix *string `json:",omitempty"` - BuildId *string `json:",omitempty"` - BuildNumberFile *string `json:",omitempty"` - BuildHostnameFile *string `json:",omitempty"` - BuildThumbprintFile *string `json:",omitempty"` - DisplayBuildNumber *bool `json:",omitempty"` + BuildId *string `json:",omitempty"` + BuildFingerprintFile *string `json:",omitempty"` + BuildNumberFile *string `json:",omitempty"` + BuildHostnameFile *string `json:",omitempty"` + BuildThumbprintFile *string `json:",omitempty"` + DisplayBuildNumber *bool `json:",omitempty"` Platform_display_version_name *string `json:",omitempty"` Platform_version_name *string `json:",omitempty"` @@ -458,6 +459,7 @@ type ProductVariables struct { BuildBrokenIncorrectPartitionImages bool `json:",omitempty"` BuildBrokenInputDirModules []string `json:",omitempty"` BuildBrokenDontCheckSystemSdk bool `json:",omitempty"` + BuildBrokenDupSysprop bool `json:",omitempty"` BuildWarningBadOptionalUsesLibsAllowlist []string `json:",omitempty"` @@ -490,8 +492,6 @@ type ProductVariables struct { ReleaseDefaultModuleBuildFromSource *bool `json:",omitempty"` - KeepVndk *bool `json:",omitempty"` - CheckVendorSeappViolations *bool `json:",omitempty"` BuildFlags map[string]string `json:",omitempty"` diff --git a/apex/androidmk.go b/apex/androidmk.go index 619be8dc4..4112108dd 100644 --- a/apex/androidmk.go +++ b/apex/androidmk.go @@ -218,7 +218,7 @@ func (a *apexBundle) writeRequiredModules(w io.Writer, moduleNames []string) { var required []string var targetRequired []string var hostRequired []string - required = append(required, a.RequiredModuleNames()...) + required = append(required, a.required...) targetRequired = append(targetRequired, a.TargetRequiredModuleNames()...) hostRequired = append(hostRequired, a.HostRequiredModuleNames()...) for _, fi := range a.filesInfo { diff --git a/apex/apex.go b/apex/apex.go index dc9b23698..754f8981e 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -18,7 +18,6 @@ package apex import ( "fmt" - "log" "path/filepath" "regexp" "sort" @@ -490,6 +489,9 @@ type apexBundle struct { javaApisUsedByModuleFile android.ModuleOutPath aconfigFiles []android.Path + + // Required modules, filled out during GenerateAndroidBuildActions and used in AndroidMk + required []string } // apexFileClass represents a type of file that can be included in APEX. @@ -568,7 +570,7 @@ func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, androidM if module != nil { ret.moduleDir = ctx.OtherModuleDir(module) ret.partition = module.PartitionTag(ctx.DeviceConfig()) - ret.requiredModuleNames = module.RequiredModuleNames() + ret.requiredModuleNames = module.RequiredModuleNames(ctx) ret.targetRequiredModuleNames = module.TargetRequiredModuleNames() ret.hostRequiredModuleNames = module.HostRequiredModuleNames() ret.multilib = module.Target().Arch.ArchType.Multilib @@ -954,7 +956,6 @@ func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) { // the non-system APEXes because the VNDK libraries won't be included (and duped) in the // APEX, but shared across APEXes via the VNDK APEX. useVndk := a.SocSpecific() || a.DeviceSpecific() || (a.ProductSpecific() && mctx.Config().EnforceProductPartitionInterface()) - excludeVndkLibs := useVndk && a.useVndkAsStable(mctx) if proptools.Bool(a.properties.Use_vndk_as_stable) { if !useVndk { mctx.PropertyErrorf("use_vndk_as_stable", "not supported for system/system_ext APEXes") @@ -962,11 +963,6 @@ func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) { if a.minSdkVersionValue(mctx) != "" { mctx.PropertyErrorf("use_vndk_as_stable", "not supported when min_sdk_version is set") } - mctx.VisitDirectDepsWithTag(sharedLibTag, func(dep android.Module) { - if c, ok := dep.(*cc.Module); ok && c.IsVndk() { - mctx.PropertyErrorf("use_vndk_as_stable", "Trying to include a VNDK library(%s) while use_vndk_as_stable is true.", dep.Name()) - } - }) if mctx.Failed() { return } @@ -988,16 +984,9 @@ func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) { if !android.IsDepInSameApex(mctx, parent, child) { return false } - if excludeVndkLibs { - if c, ok := child.(*cc.Module); ok && c.IsVndk() { - return false - } - } - //TODO: b/296491928 Vendor APEX should use libbinder.ndk instead of libbinder once VNDK is fully deprecated. - if useVndk && mctx.Config().IsVndkDeprecated() && child.Name() == "libbinder" { - log.Print("Libbinder is linked from Vendor APEX ", a.Name(), " with module ", parent.Name()) - return false + if useVndk && child.Name() == "libbinder" { + mctx.ModuleErrorf("Module %s in the vendor APEX %s should not use libbinder. Use libbinder_ndk instead.", parent.Name(), a.Name()) } // By default, all the transitive dependencies are collected, unless filtered out @@ -1054,6 +1043,7 @@ func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) { InApexModules: []string{a.Name()}, // could be com.mycompany.android.foo ApexContents: []*android.ApexContents{apexContents}, TestApexes: testApexes, + BaseApexName: mctx.ModuleName(), } mctx.WalkDeps(func(child, parent android.Module) bool { if !continueApexDepsWalk(child, parent) { @@ -2195,15 +2185,6 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, // tags used below are private (e.g. `cc.sharedDepTag`). if cc.IsSharedDepTag(depTag) || cc.IsRuntimeDepTag(depTag) { if ch, ok := child.(*cc.Module); ok { - if ch.UseVndk() && a.useVndkAsStable(ctx) && ch.IsVndk() { - vctx.requireNativeLibs = append(vctx.requireNativeLibs, ":vndk") - return false - } - - //TODO: b/296491928 Vendor APEX should use libbinder.ndk instead of libbinder once VNDK is fully deprecated. - if ch.InVendorOrProduct() && ctx.Config().IsVndkDeprecated() && child.Name() == "libbinder" { - return false - } af := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs) af.transitiveDep = true @@ -2449,6 +2430,8 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.provideApexExportsInfo(ctx) a.providePrebuiltInfo(ctx) + + a.required = a.RequiredModuleNames(ctx) } // Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file @@ -3024,12 +3007,3 @@ func rBcpPackages() map[string][]string { func (a *apexBundle) IsTestApex() bool { return a.testApex } - -func (a *apexBundle) useVndkAsStable(ctx android.BaseModuleContext) bool { - // VNDK cannot be linked if it is deprecated - if ctx.Config().IsVndkDeprecated() { - return false - } - - return proptools.Bool(a.properties.Use_vndk_as_stable) -} diff --git a/apex/apex_test.go b/apex/apex_test.go index c60ee73cd..dfc4bb372 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -3785,32 +3785,31 @@ func TestVndkApexNameRule(t *testing.T) { } func TestVndkApexDoesntSupportNativeBridgeSupported(t *testing.T) { - testApexError(t, `module "com.android.vndk.current" .*: native_bridge_supported: .* doesn't support native bridge binary`, ` + testApexError(t, `module "com.android.vndk.v30" .*: native_bridge_supported: .* doesn't support native bridge binary`, ` apex_vndk { - name: "com.android.vndk.current", - key: "com.android.vndk.current.key", + name: "com.android.vndk.v30", + key: "com.android.vndk.v30.key", file_contexts: ":myapex-file_contexts", native_bridge_supported: true, } apex_key { - name: "com.android.vndk.current.key", + name: "com.android.vndk.v30.key", public_key: "testkey.avbpubkey", private_key: "testkey.pem", } - cc_library { + vndk_prebuilt_shared { name: "libvndk", + version: "30", + target_arch: "arm", srcs: ["mylib.cpp"], vendor_available: true, product_available: true, native_bridge_supported: true, - host_supported: true, vndk: { enabled: true, }, - system_shared_libs: [], - stl: "none", } `) } @@ -9807,188 +9806,196 @@ func ensureDoesNotContainRequiredDeps(t *testing.T, ctx *android.TestContext, mo } } -// TODO(b/193460475): Re-enable this test -//func TestApexStrictUpdtabilityLint(t *testing.T) { -// bpTemplate := ` -// apex { -// name: "myapex", -// key: "myapex.key", -// java_libs: ["myjavalib"], -// updatable: %v, -// min_sdk_version: "29", -// } -// apex_key { -// name: "myapex.key", -// } -// java_library { -// name: "myjavalib", -// srcs: ["MyClass.java"], -// apex_available: [ "myapex" ], -// lint: { -// strict_updatability_linting: %v, -// }, -// sdk_version: "current", -// min_sdk_version: "29", -// } -// ` -// fs := android.MockFS{ -// "lint-baseline.xml": nil, -// } -// -// testCases := []struct { -// testCaseName string -// apexUpdatable bool -// javaStrictUpdtabilityLint bool -// lintFileExists bool -// disallowedFlagExpected bool -// }{ -// { -// testCaseName: "lint-baseline.xml does not exist, no disallowed flag necessary in lint cmd", -// apexUpdatable: true, -// javaStrictUpdtabilityLint: true, -// lintFileExists: false, -// disallowedFlagExpected: false, -// }, -// { -// testCaseName: "non-updatable apex respects strict_updatability of javalib", -// apexUpdatable: false, -// javaStrictUpdtabilityLint: false, -// lintFileExists: true, -// disallowedFlagExpected: false, -// }, -// { -// testCaseName: "non-updatable apex respects strict updatability of javalib", -// apexUpdatable: false, -// javaStrictUpdtabilityLint: true, -// lintFileExists: true, -// disallowedFlagExpected: true, -// }, -// { -// testCaseName: "updatable apex sets strict updatability of javalib to true", -// apexUpdatable: true, -// javaStrictUpdtabilityLint: false, // will be set to true by mutator -// lintFileExists: true, -// disallowedFlagExpected: true, -// }, -// } -// -// for _, testCase := range testCases { -// bp := fmt.Sprintf(bpTemplate, testCase.apexUpdatable, testCase.javaStrictUpdtabilityLint) -// fixtures := []android.FixturePreparer{} -// if testCase.lintFileExists { -// fixtures = append(fixtures, fs.AddToFixture()) -// } -// -// result := testApex(t, bp, fixtures...) -// myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29") -// sboxProto := android.RuleBuilderSboxProtoForTests(t, myjavalib.Output("lint.sbox.textproto")) -// disallowedFlagActual := strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi") -// -// if disallowedFlagActual != testCase.disallowedFlagExpected { -// t.Errorf("Failed testcase: %v \nActual lint cmd: %v", testCase.testCaseName, *sboxProto.Commands[0].Command) -// } -// } -//} -// -//func TestUpdatabilityLintSkipLibcore(t *testing.T) { -// bp := ` -// apex { -// name: "myapex", -// key: "myapex.key", -// java_libs: ["myjavalib"], -// updatable: true, -// min_sdk_version: "29", -// } -// apex_key { -// name: "myapex.key", -// } -// java_library { -// name: "myjavalib", -// srcs: ["MyClass.java"], -// apex_available: [ "myapex" ], -// sdk_version: "current", -// min_sdk_version: "29", -// } -// ` -// -// testCases := []struct { -// testCaseName string -// moduleDirectory string -// disallowedFlagExpected bool -// }{ -// { -// testCaseName: "lintable module defined outside libcore", -// moduleDirectory: "", -// disallowedFlagExpected: true, -// }, -// { -// testCaseName: "lintable module defined in libcore root directory", -// moduleDirectory: "libcore/", -// disallowedFlagExpected: false, -// }, -// { -// testCaseName: "lintable module defined in libcore child directory", -// moduleDirectory: "libcore/childdir/", -// disallowedFlagExpected: true, -// }, -// } -// -// for _, testCase := range testCases { -// lintFileCreator := android.FixtureAddTextFile(testCase.moduleDirectory+"lint-baseline.xml", "") -// bpFileCreator := android.FixtureAddTextFile(testCase.moduleDirectory+"Android.bp", bp) -// result := testApex(t, "", lintFileCreator, bpFileCreator) -// myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29") -// sboxProto := android.RuleBuilderSboxProtoForTests(t, myjavalib.Output("lint.sbox.textproto")) -// cmdFlags := fmt.Sprintf("--baseline %vlint-baseline.xml --disallowed_issues NewApi", testCase.moduleDirectory) -// disallowedFlagActual := strings.Contains(*sboxProto.Commands[0].Command, cmdFlags) -// -// if disallowedFlagActual != testCase.disallowedFlagExpected { -// t.Errorf("Failed testcase: %v \nActual lint cmd: %v", testCase.testCaseName, *sboxProto.Commands[0].Command) -// } -// } -//} -// -//// checks transtive deps of an apex coming from bootclasspath_fragment -//func TestApexStrictUpdtabilityLintBcpFragmentDeps(t *testing.T) { -// bp := ` -// apex { -// name: "myapex", -// key: "myapex.key", -// bootclasspath_fragments: ["mybootclasspathfragment"], -// updatable: true, -// min_sdk_version: "29", -// } -// apex_key { -// name: "myapex.key", -// } -// bootclasspath_fragment { -// name: "mybootclasspathfragment", -// contents: ["myjavalib"], -// apex_available: ["myapex"], -// hidden_api: { -// split_packages: ["*"], -// }, -// } -// java_library { -// name: "myjavalib", -// srcs: ["MyClass.java"], -// apex_available: [ "myapex" ], -// sdk_version: "current", -// min_sdk_version: "29", -// compile_dex: true, -// } -// ` -// fs := android.MockFS{ -// "lint-baseline.xml": nil, -// } -// -// result := testApex(t, bp, dexpreopt.FixtureSetApexBootJars("myapex:myjavalib"), fs.AddToFixture()) -// myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29") -// sboxProto := android.RuleBuilderSboxProtoForTests(t, myjavalib.Output("lint.sbox.textproto")) -// if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi") { -// t.Errorf("Strict updabality lint missing in myjavalib coming from bootclasspath_fragment mybootclasspath-fragment\nActual lint cmd: %v", *sboxProto.Commands[0].Command) -// } -//} +func TestApexStrictUpdtabilityLint(t *testing.T) { + bpTemplate := ` + apex { + name: "myapex", + key: "myapex.key", + java_libs: ["myjavalib"], + updatable: %v, + min_sdk_version: "29", + } + apex_key { + name: "myapex.key", + } + java_library { + name: "myjavalib", + srcs: ["MyClass.java"], + apex_available: [ "myapex" ], + lint: { + strict_updatability_linting: %v, + %s + }, + sdk_version: "current", + min_sdk_version: "29", + } + ` + fs := android.MockFS{ + "lint-baseline.xml": nil, + } + + testCases := []struct { + testCaseName string + apexUpdatable bool + javaStrictUpdtabilityLint bool + lintFileExists bool + disallowedFlagExpected bool + }{ + { + testCaseName: "lint-baseline.xml does not exist, no disallowed flag necessary in lint cmd", + apexUpdatable: true, + javaStrictUpdtabilityLint: true, + lintFileExists: false, + disallowedFlagExpected: false, + }, + { + testCaseName: "non-updatable apex respects strict_updatability of javalib", + apexUpdatable: false, + javaStrictUpdtabilityLint: false, + lintFileExists: true, + disallowedFlagExpected: false, + }, + { + testCaseName: "non-updatable apex respects strict updatability of javalib", + apexUpdatable: false, + javaStrictUpdtabilityLint: true, + lintFileExists: true, + disallowedFlagExpected: true, + }, + { + testCaseName: "updatable apex sets strict updatability of javalib to true", + apexUpdatable: true, + javaStrictUpdtabilityLint: false, // will be set to true by mutator + lintFileExists: true, + disallowedFlagExpected: true, + }, + } + + for _, testCase := range testCases { + fixtures := []android.FixturePreparer{} + baselineProperty := "" + if testCase.lintFileExists { + fixtures = append(fixtures, fs.AddToFixture()) + baselineProperty = "baseline_filename: \"lint-baseline.xml\"" + } + bp := fmt.Sprintf(bpTemplate, testCase.apexUpdatable, testCase.javaStrictUpdtabilityLint, baselineProperty) + + result := testApex(t, bp, fixtures...) + myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29") + sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto")) + disallowedFlagActual := strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi") + + if disallowedFlagActual != testCase.disallowedFlagExpected { + t.Errorf("Failed testcase: %v \nActual lint cmd: %v", testCase.testCaseName, *sboxProto.Commands[0].Command) + } + } +} + +func TestUpdatabilityLintSkipLibcore(t *testing.T) { + bp := ` + apex { + name: "myapex", + key: "myapex.key", + java_libs: ["myjavalib"], + updatable: true, + min_sdk_version: "29", + } + apex_key { + name: "myapex.key", + } + java_library { + name: "myjavalib", + srcs: ["MyClass.java"], + apex_available: [ "myapex" ], + sdk_version: "current", + min_sdk_version: "29", + lint: { + baseline_filename: "lint-baseline.xml", + } + } + ` + + testCases := []struct { + testCaseName string + moduleDirectory string + disallowedFlagExpected bool + }{ + { + testCaseName: "lintable module defined outside libcore", + moduleDirectory: "", + disallowedFlagExpected: true, + }, + { + testCaseName: "lintable module defined in libcore root directory", + moduleDirectory: "libcore/", + disallowedFlagExpected: false, + }, + { + testCaseName: "lintable module defined in libcore child directory", + moduleDirectory: "libcore/childdir/", + disallowedFlagExpected: true, + }, + } + + for _, testCase := range testCases { + lintFileCreator := android.FixtureAddTextFile(testCase.moduleDirectory+"lint-baseline.xml", "") + bpFileCreator := android.FixtureAddTextFile(testCase.moduleDirectory+"Android.bp", bp) + result := testApex(t, "", lintFileCreator, bpFileCreator) + myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29") + sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto")) + cmdFlags := fmt.Sprintf("--baseline %vlint-baseline.xml --disallowed_issues NewApi", testCase.moduleDirectory) + disallowedFlagActual := strings.Contains(*sboxProto.Commands[0].Command, cmdFlags) + + if disallowedFlagActual != testCase.disallowedFlagExpected { + t.Errorf("Failed testcase: %v \nActual lint cmd: %v", testCase.testCaseName, *sboxProto.Commands[0].Command) + } + } +} + +// checks transtive deps of an apex coming from bootclasspath_fragment +func TestApexStrictUpdtabilityLintBcpFragmentDeps(t *testing.T) { + bp := ` + apex { + name: "myapex", + key: "myapex.key", + bootclasspath_fragments: ["mybootclasspathfragment"], + updatable: true, + min_sdk_version: "29", + } + apex_key { + name: "myapex.key", + } + bootclasspath_fragment { + name: "mybootclasspathfragment", + contents: ["myjavalib"], + apex_available: ["myapex"], + hidden_api: { + split_packages: ["*"], + }, + } + java_library { + name: "myjavalib", + srcs: ["MyClass.java"], + apex_available: [ "myapex" ], + sdk_version: "current", + min_sdk_version: "29", + compile_dex: true, + lint: { + baseline_filename: "lint-baseline.xml", + } + } + ` + fs := android.MockFS{ + "lint-baseline.xml": nil, + } + + result := testApex(t, bp, dexpreopt.FixtureSetApexBootJars("myapex:myjavalib"), fs.AddToFixture()) + myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29") + sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto")) + if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi") { + t.Errorf("Strict updabality lint missing in myjavalib coming from bootclasspath_fragment mybootclasspath-fragment\nActual lint cmd: %v", *sboxProto.Commands[0].Command) + } +} // updatable apexes should propagate updatable=true to its apps func TestUpdatableApexEnforcesAppUpdatability(t *testing.T) { diff --git a/apex/prebuilt.go b/apex/prebuilt.go index d91943fdf..65c23d34b 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -588,15 +588,6 @@ func (a *Prebuilt) hasSanitizedSource(sanitizer string) bool { return false } -func (p *Prebuilt) OutputFiles(tag string) (android.Paths, error) { - switch tag { - case "": - return android.Paths{p.outputApex}, nil - default: - return nil, fmt.Errorf("unsupported module reference tag %q", tag) - } -} - // prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex. func PrebuiltFactory() android.Module { module := &Prebuilt{} @@ -895,6 +886,8 @@ func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) { p.installedFile = ctx.InstallFile(p.installDir, p.installFilename, p.inputApex, p.compatSymlinks...) p.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, p.inputApex, p.installedFile) } + + ctx.SetOutputFiles(android.Paths{p.outputApex}, "") } func (p *Prebuilt) ProvenanceMetaDataFile() android.OutputPath { @@ -1010,15 +1003,6 @@ func (a *ApexSet) hasSanitizedSource(sanitizer string) bool { return false } -func (a *ApexSet) OutputFiles(tag string) (android.Paths, error) { - switch tag { - case "": - return android.Paths{a.outputApex}, nil - default: - return nil, fmt.Errorf("unsupported module reference tag %q", tag) - } -} - // prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex. func apexSetFactory() android.Module { module := &ApexSet{} @@ -1122,6 +1106,8 @@ func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { for _, overridden := range a.prebuiltCommonProperties.Overrides { a.compatSymlinks = append(a.compatSymlinks, makeCompatSymlinks(overridden, ctx)...) } + + ctx.SetOutputFiles(android.Paths{a.outputApex}, "") } type systemExtContext struct { diff --git a/cc/androidmk.go b/cc/androidmk.go index 62ba4debd..143e86f09 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -104,16 +104,6 @@ func (c *Module) AndroidMkEntries() []android.AndroidMkEntries { entries.AddStrings("LOCAL_RUNTIME_LIBRARIES", c.Properties.AndroidMkRuntimeLibs...) } entries.SetString("LOCAL_SOONG_LINK_TYPE", c.makeLinkType) - if c.InVendorOrProduct() { - if c.IsVndk() && !c.static() { - entries.SetString("LOCAL_SOONG_VNDK_VERSION", c.VndkVersion()) - // VNDK libraries available to vendor are not installed because - // they are packaged in VNDK APEX and installed by APEX packages (apex/apex.go) - if !c.IsVndkExt() { - entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true) - } - } - } if c.InVendor() { entries.SetBool("LOCAL_IN_VENDOR", true) } else if c.InProduct() { @@ -49,7 +49,6 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) { ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) { ctx.BottomUp("sdk", sdkMutator).Parallel() - ctx.BottomUp("vndk", VndkMutator).Parallel() ctx.BottomUp("llndk", llndkMutator).Parallel() ctx.BottomUp("link", LinkageMutator).Parallel() ctx.BottomUp("test_per_src", TestPerSrcMutator).Parallel() @@ -480,19 +479,6 @@ type VendorProperties struct { // IsLLNDK is set to true for the vendor variant of a cc_library module that has LLNDK stubs. IsLLNDK bool `blueprint:"mutated"` - // IsVNDKCore is set if a VNDK module does not set the vndk.support_system_process property. - IsVNDKCore bool `blueprint:"mutated"` - - // IsVNDKSP is set if a VNDK module sets the vndk.support_system_process property. - IsVNDKSP bool `blueprint:"mutated"` - - // IsVNDKPrivate is set if a VNDK module sets the vndk.private property or an LLNDK - // module sets the llndk.private property. - IsVNDKPrivate bool `blueprint:"mutated"` - - // IsVNDKProduct is set if a VNDK module sets the product_available property. - IsVNDKProduct bool `blueprint:"mutated"` - // IsVendorPublicLibrary is set for the core and product variants of a library that has // vendor_public_library stubs. IsVendorPublicLibrary bool `blueprint:"mutated"` @@ -519,12 +505,7 @@ type ModuleContextIntf interface { useVndk() bool isNdk(config android.Config) bool IsLlndk() bool - IsLlndkPublic() bool isImplementationForLLNDKPublic() bool - IsVndkPrivate() bool - isVndk() bool - isVndkSp() bool - IsVndkExt() bool IsVendorPublicLibrary() bool inProduct() bool inVendor() bool @@ -534,7 +515,6 @@ type ModuleContextIntf interface { InVendorOrProduct() bool selectedStl() string baseModuleName() string - getVndkExtendsModuleName() string isAfdoCompile(ctx ModuleContext) bool isOrderfileCompile() bool isCfi() bool @@ -900,7 +880,6 @@ type Module struct { coverage *coverage fuzzer *fuzzer sabi *sabi - vndkdep *vndkdep lto *lto afdo *afdo orderfile *orderfile @@ -974,12 +953,7 @@ func (c *Module) AddJSONData(d *map[string]interface{}) { "InstallInVendorRamdisk": c.InstallInVendorRamdisk(), "InstallInRecovery": c.InstallInRecovery(), "InstallInRoot": c.InstallInRoot(), - "IsVndk": c.IsVndk(), - "IsVndkExt": c.IsVndkExt(), - "IsVndkPrivate": c.IsVndkPrivate(), - "IsVndkSp": c.IsVndkSp(), "IsLlndk": c.IsLlndk(), - "IsLlndkPublic": c.IsLlndkPublic(), "IsVendorPublicLibrary": c.IsVendorPublicLibrary(), "ApexSdkVersion": c.apexSdkVersion, "TestFor": c.TestFor(), @@ -1007,8 +981,8 @@ func (c *Module) HiddenFromMake() bool { return c.Properties.HideFromMake } -func (c *Module) RequiredModuleNames() []string { - required := android.CopyOf(c.ModuleBase.RequiredModuleNames()) +func (c *Module) RequiredModuleNames(ctx android.ConfigAndErrorContext) []string { + required := android.CopyOf(c.ModuleBase.RequiredModuleNames(ctx)) if c.ImageVariation().Variation == android.CoreVariation { required = append(required, c.Properties.Target.Platform.Required...) required = removeListFromList(required, c.Properties.Target.Platform.Exclude_required) @@ -1289,9 +1263,6 @@ func (c *Module) Init() android.Module { if c.sabi != nil { c.AddProperties(c.sabi.props()...) } - if c.vndkdep != nil { - c.AddProperties(c.vndkdep.props()...) - } if c.lto != nil { c.AddProperties(c.lto.props()...) } @@ -1346,10 +1317,6 @@ func (c *Module) IsLlndk() bool { return c.VendorProperties.IsLLNDK } -func (c *Module) IsLlndkPublic() bool { - return c.VendorProperties.IsLLNDK && !c.VendorProperties.IsVNDKPrivate -} - func (m *Module) NeedsLlndkVariants() bool { lib := moduleLibraryInterface(m) return lib != nil && (lib.hasLLNDKStubs() || lib.hasLLNDKHeaders()) @@ -1396,31 +1363,6 @@ func (c *Module) isImplementationForLLNDKPublic() bool { !Bool(library.Properties.Llndk.Private) } -// Returns true for LLNDK-private, VNDK-SP-private, and VNDK-core-private. -func (c *Module) IsVndkPrivate() bool { - // Check if VNDK-core-private or VNDK-SP-private - if c.IsVndk() { - return Bool(c.vndkdep.Properties.Vndk.Private) - } - - // Check if LLNDK-private - if library, ok := c.library.(*libraryDecorator); ok && c.IsLlndk() { - return Bool(library.Properties.Llndk.Private) - } - - return false -} - -// IsVndk() returns true if this module has a vndk variant. -// Note that IsVndk() returns true for all variants of vndk-enabled libraries. Not only vendor variant, -// but also platform and product variants of vndk-enabled libraries return true for IsVndk(). -func (c *Module) IsVndk() bool { - if vndkdep := c.vndkdep; vndkdep != nil { - return vndkdep.isVndk() - } - return false -} - func (c *Module) isAfdoCompile(ctx ModuleContext) bool { if afdo := c.afdo; afdo != nil { return afdo.isAfdoCompile(ctx) @@ -1456,31 +1398,10 @@ func (c *Module) isNDKStubLibrary() bool { return false } -func (c *Module) IsVndkSp() bool { - if vndkdep := c.vndkdep; vndkdep != nil { - return vndkdep.isVndkSp() - } - return false -} - -func (c *Module) IsVndkExt() bool { - if vndkdep := c.vndkdep; vndkdep != nil { - return vndkdep.isVndkExt() - } - return false -} - func (c *Module) SubName() string { return c.Properties.SubName } -func (c *Module) getVndkExtendsModuleName() string { - if vndkdep := c.vndkdep; vndkdep != nil { - return vndkdep.getVndkExtendsModuleName() - } - return "" -} - func (c *Module) IsStubs() bool { if lib := c.library; lib != nil { return lib.buildStubs() @@ -1638,14 +1559,6 @@ func (ctx *moduleContextImpl) useSdk() bool { func (ctx *moduleContextImpl) sdkVersion() string { if ctx.ctx.Device() { - config := ctx.ctx.Config() - if !config.IsVndkDeprecated() && ctx.useVndk() { - vndkVer := ctx.mod.VndkVersion() - if inList(vndkVer, config.PlatformVersionActiveCodenames()) { - return "current" - } - return vndkVer - } return String(ctx.mod.Properties.Sdk_version) } return "" @@ -1662,7 +1575,7 @@ func (ctx *moduleContextImpl) minSdkVersion() string { if ctx.ctx.Device() { config := ctx.ctx.Config() - if config.IsVndkDeprecated() && ctx.inVendor() { + if ctx.inVendor() { // If building for vendor with final API, then use the latest _stable_ API as "current". if config.VendorApiLevelFrozen() && (ver == "" || ver == "current") { ver = config.PlatformSdkVersion().String() @@ -1722,22 +1635,10 @@ func (ctx *moduleContextImpl) IsLlndk() bool { return ctx.mod.IsLlndk() } -func (ctx *moduleContextImpl) IsLlndkPublic() bool { - return ctx.mod.IsLlndkPublic() -} - func (ctx *moduleContextImpl) isImplementationForLLNDKPublic() bool { return ctx.mod.isImplementationForLLNDKPublic() } -func (ctx *moduleContextImpl) IsVndkPrivate() bool { - return ctx.mod.IsVndkPrivate() -} - -func (ctx *moduleContextImpl) isVndk() bool { - return ctx.mod.IsVndk() -} - func (ctx *moduleContextImpl) isAfdoCompile(mctx ModuleContext) bool { return ctx.mod.isAfdoCompile(mctx) } @@ -1758,14 +1659,6 @@ func (ctx *moduleContextImpl) isNDKStubLibrary() bool { return ctx.mod.isNDKStubLibrary() } -func (ctx *moduleContextImpl) isVndkSp() bool { - return ctx.mod.IsVndkSp() -} - -func (ctx *moduleContextImpl) IsVndkExt() bool { - return ctx.mod.IsVndkExt() -} - func (ctx *moduleContextImpl) IsVendorPublicLibrary() bool { return ctx.mod.IsVendorPublicLibrary() } @@ -1785,10 +1678,6 @@ func (ctx *moduleContextImpl) baseModuleName() string { return ctx.mod.BaseModuleName() } -func (ctx *moduleContextImpl) getVndkExtendsModuleName() string { - return ctx.mod.getVndkExtendsModuleName() -} - func (ctx *moduleContextImpl) isForPlatform() bool { apexInfo, _ := android.ModuleProvider(ctx.ctx, android.ApexInfoProvider) return apexInfo.IsForPlatform() @@ -1853,7 +1742,6 @@ func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Mo module.coverage = &coverage{} module.fuzzer = &fuzzer{} module.sabi = &sabi{} - module.vndkdep = &vndkdep{} module.lto = <o{} module.afdo = &afdo{} module.orderfile = &orderfile{} @@ -2785,15 +2673,6 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { {Mutator: "link", Variation: "shared"}, }, ndkLateStubDepTag, apiLateNdkLibs...) - if vndkdep := c.vndkdep; vndkdep != nil { - if vndkdep.isVndkExt() { - actx.AddVariationDependencies([]blueprint.Variation{ - c.ImageVariation(), - {Mutator: "link", Variation: "shared"}, - }, vndkExtDepTag, vndkdep.getVndkExtendsModuleName()) - } - } - if len(deps.AidlLibs) > 0 { actx.AddDependency( c, @@ -2831,20 +2710,6 @@ func checkLinkType(ctx android.BaseModuleContext, from LinkableInterface, to Lin return } - // VNDK is cc.Module supported only for now. - if ccFrom, ok := from.(*Module); ok && from.UseVndk() { - // Though allowed dependency is limited by the image mutator, - // each vendor and product module needs to check link-type - // for VNDK. - if ccTo, ok := to.(*Module); ok { - if ccFrom.vndkdep != nil { - ccFrom.vndkdep.vndkCheckLinkType(ctx, ccTo, tag) - } - } else if _, ok := to.(LinkableInterface); !ok { - ctx.ModuleErrorf("Attempting to link VNDK cc.Module with unsupported module type") - } - return - } // TODO(b/244244438) : Remove this once all variants are implemented if ccFrom, ok := from.(*Module); ok && ccFrom.isImportedApiLibrary() { return @@ -2999,7 +2864,7 @@ func checkDoubleLoadableLibraries(ctx android.TopDownMutatorContext) { return true } - if to.IsVndkSp() || to.IsLlndk() { + if to.IsLlndk() { return false } @@ -3833,15 +3698,6 @@ func (m *Module) Rlib() bool { func GetMakeLinkType(actx android.ModuleContext, c LinkableInterface) string { if c.InVendorOrProduct() { if c.IsLlndk() { - if !c.IsLlndkPublic() { - return "native:vndk_private" - } - return "native:vndk" - } - if c.IsVndk() && !c.IsVndkExt() { - if c.IsVndkPrivate() { - return "native:vndk_private" - } return "native:vndk" } if c.InProduct() { @@ -4043,15 +3899,6 @@ func (c *Module) AlwaysRequiresPlatformApexVariant() bool { return c.IsStubs() || c.Target().NativeBridge == android.NativeBridgeEnabled } -// Overrides android.ApexModuleBase.UniqueApexVariations -func (c *Module) UniqueApexVariations() bool { - // When a vendor APEX needs a VNDK lib in it (use_vndk_as_stable: false), it should be a unique - // APEX variation. Otherwise, another vendor APEX with use_vndk_as_stable:true may use a wrong - // variation of the VNDK lib because APEX variations are merged/grouped. - // TODO(b/274401041) Find a way to merge APEX variations for vendor apexes. - return c.UseVndk() && c.IsVndk() -} - func (c *Module) overriddenModules() []string { if o, ok := c.linker.(overridable); ok { return o.overriddenModules() @@ -4159,7 +4006,6 @@ func DefaultsFactory(props ...interface{}) android.Module { &TidyProperties{}, &CoverageProperties{}, &SAbiProperties{}, - &VndkProperties{}, <OProperties{}, &AfdoProperties{}, &OrderfileProperties{}, diff --git a/cc/cc_test.go b/cc/cc_test.go index 026d291e0..c2bb25ad8 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -658,7 +658,7 @@ func TestMakeLinkType(t *testing.T) { }{ {vendorVariant, "libvendor", "native:vendor"}, {vendorVariant, "libllndk", "native:vndk"}, - {vendorVariant27, "prevndk.vndk.27.arm.binder32", "native:vndk"}, + {vendorVariant27, "prevndk.vndk.27.arm.binder32", "native:vendor"}, {coreVariant, "libllndk", "native:platform"}, } for _, test := range tests { diff --git a/cc/image.go b/cc/image.go index 28692d863..48a9174e3 100644 --- a/cc/image.go +++ b/cc/image.go @@ -17,8 +17,6 @@ package cc // functions to determine where a module is installed, etc. import ( - "fmt" - "reflect" "strings" "android/soong/android" @@ -157,52 +155,6 @@ func (c *Module) OnlyInRecovery() bool { return c.ModuleBase.InstallInRecovery() } -func visitPropsAndCompareVendorAndProductProps(v reflect.Value) bool { - if v.Kind() != reflect.Struct { - return true - } - for i := 0; i < v.NumField(); i++ { - prop := v.Field(i) - if prop.Kind() == reflect.Struct && v.Type().Field(i).Name == "Target" { - vendor_prop := prop.FieldByName("Vendor") - product_prop := prop.FieldByName("Product") - if vendor_prop.Kind() != reflect.Struct && product_prop.Kind() != reflect.Struct { - // Neither Target.Vendor nor Target.Product is defined - continue - } - if vendor_prop.Kind() != reflect.Struct || product_prop.Kind() != reflect.Struct || - !reflect.DeepEqual(vendor_prop.Interface(), product_prop.Interface()) { - // If only one of either Target.Vendor or Target.Product is - // defined or they have different values, it fails the build - // since VNDK must have the same properties for both vendor - // and product variants. - return false - } - } else if !visitPropsAndCompareVendorAndProductProps(prop) { - // Visit the substructures to find Target.Vendor and Target.Product - return false - } - } - return true -} - -// In the case of VNDK, vendor and product variants must have the same properties. -// VNDK installs only one file and shares it for both vendor and product modules on -// runtime. We may not define different versions of a VNDK lib for each partition. -// This function is used only for the VNDK modules that is available to both vendor -// and product partitions. -func (c *Module) compareVendorAndProductProps() bool { - if !c.IsVndk() && !Bool(c.VendorProperties.Product_available) { - panic(fmt.Errorf("This is only for product available VNDK libs. %q is not a VNDK library or not product available", c.Name())) - } - for _, properties := range c.GetProperties() { - if !visitPropsAndCompareVendorAndProductProps(reflect.ValueOf(properties).Elem()) { - return false - } - } - return true -} - // ImageMutatableModule provides a common image mutation interface for LinkableInterface modules. type ImageMutatableModule interface { android.Module @@ -260,62 +212,9 @@ type ImageMutatableModule interface { var _ ImageMutatableModule = (*Module)(nil) func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { - m.CheckVndkProperties(mctx) MutateImage(mctx, m) } -// CheckVndkProperties checks whether the VNDK-related properties are set correctly. -// If properties are not set correctly, results in a module context property error. -func (m *Module) CheckVndkProperties(mctx android.BaseModuleContext) { - vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific() - productSpecific := mctx.ProductSpecific() - - if vndkdep := m.vndkdep; vndkdep != nil { - if vndkdep.isVndk() { - if vendorSpecific || productSpecific { - if !vndkdep.isVndkExt() { - mctx.PropertyErrorf("vndk", - "must set `extends: \"...\"` to vndk extension") - } else if Bool(m.VendorProperties.Vendor_available) { - mctx.PropertyErrorf("vendor_available", - "must not set at the same time as `vndk: {extends: \"...\"}`") - } else if Bool(m.VendorProperties.Product_available) { - mctx.PropertyErrorf("product_available", - "must not set at the same time as `vndk: {extends: \"...\"}`") - } - } else { - if vndkdep.isVndkExt() { - mctx.PropertyErrorf("vndk", - "must set `vendor: true` or `product_specific: true` to set `extends: %q`", - m.getVndkExtendsModuleName()) - } - if !Bool(m.VendorProperties.Vendor_available) { - mctx.PropertyErrorf("vndk", - "vendor_available must be set to true when `vndk: {enabled: true}`") - } - if Bool(m.VendorProperties.Product_available) { - // If a VNDK module creates both product and vendor variants, they - // must have the same properties since they share a single VNDK - // library on runtime. - if !m.compareVendorAndProductProps() { - mctx.ModuleErrorf("product properties must have the same values with the vendor properties for VNDK modules") - } - } - } - } else { - if vndkdep.isVndkSp() { - mctx.PropertyErrorf("vndk", - "must set `enabled: true` to set `support_system_process: true`") - } - if vndkdep.isVndkExt() { - mctx.PropertyErrorf("vndk", - "must set `enabled: true` to set `extends: %q`", - m.getVndkExtendsModuleName()) - } - } - } -} - func (m *Module) VendorAvailable() bool { return Bool(m.VendorProperties.Vendor_available) } @@ -456,7 +355,7 @@ func MutateImage(mctx android.BaseModuleContext, m ImageMutatableModule) { } else { vendorVariants = append(vendorVariants, m.SnapshotVersion(mctx)) } - } else if m.HasNonSystemVariants() && !m.IsVndkExt() { + } else if m.HasNonSystemVariants() { // This will be available to /system unless it is product_specific // which will be handled later. coreVariantNeeded = true diff --git a/cc/library.go b/cc/library.go index d692b40b3..e49f50cc0 100644 --- a/cc/library.go +++ b/cc/library.go @@ -1762,22 +1762,7 @@ func (library *libraryDecorator) installSymlinkToRuntimeApex(ctx ModuleContext, func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) { if library.shared() { - if ctx.Device() && ctx.useVndk() { - // set subDir for VNDK extensions - if ctx.IsVndkExt() { - if ctx.isVndkSp() { - library.baseInstaller.subDir = "vndk-sp" - } else { - library.baseInstaller.subDir = "vndk" - } - } - - // do not install vndk libs - // vndk libs are packaged into VNDK APEX - if ctx.isVndk() && !ctx.IsVndkExt() && !ctx.Config().IsVndkDeprecated() && !ctx.inProduct() { - return - } - } else if library.hasStubsVariants() && !ctx.Host() && ctx.directlyInAnyApex() { + if library.hasStubsVariants() && !ctx.Host() && ctx.directlyInAnyApex() { // Bionic libraries (e.g. libc.so) is installed to the bootstrap subdirectory. // The original path becomes a symlink to the corresponding file in the // runtime APEX. diff --git a/cc/linkable.go b/cc/linkable.go index fecc6a2e6..2309fe800 100644 --- a/cc/linkable.go +++ b/cc/linkable.go @@ -136,9 +136,6 @@ type LinkableInterface interface { // IsLlndk returns true for both LLNDK (public) and LLNDK-private libs. IsLlndk() bool - // IsLlndkPublic returns true only for LLNDK (public) libs. - IsLlndkPublic() bool - // HasLlndkStubs returns true if this library has a variant that will build LLNDK stubs. HasLlndkStubs() bool @@ -162,12 +159,6 @@ type LinkableInterface interface { // Bootstrap tests if this module is allowed to use non-APEX version of libraries. Bootstrap() bool - // IsVndkSp returns true if this is a VNDK-SP module. - IsVndkSp() bool - - IsVndk() bool - IsVndkExt() bool - IsVndkPrivate() bool IsVendorPublicLibrary() bool IsVndkPrebuiltLibrary() bool HasVendorVariant() bool diff --git a/cc/llndk_library.go b/cc/llndk_library.go index d612e9e72..632c76d90 100644 --- a/cc/llndk_library.go +++ b/cc/llndk_library.go @@ -15,6 +15,7 @@ package cc import ( + "fmt" "strings" "android/soong/android" @@ -122,6 +123,16 @@ func (txt *llndkLibrariesTxtModule) GenerateAndroidBuildActions(ctx android.Modu ctx.SetOutputFiles(android.Paths{txt.outputFile}, "") } +func getVndkFileName(m *Module) (string, error) { + if library, ok := m.linker.(*libraryDecorator); ok { + return library.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil + } + if prebuilt, ok := m.linker.(*prebuiltLibraryLinker); ok { + return prebuilt.libraryDecorator.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil + } + return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", m.linker) +} + func (txt *llndkLibrariesTxtModule) GenerateSingletonBuildActions(ctx android.SingletonContext) { if txt.outputFile.String() == "" { // Skip if target file path is empty @@ -197,8 +208,10 @@ func llndkMutator(mctx android.BottomUpMutatorContext) { m.VendorProperties.IsLLNDK = true } - if m.IsVndkPrebuiltLibrary() && !m.IsVndk() { - m.VendorProperties.IsLLNDK = true + if vndkprebuilt, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok { + if !Bool(vndkprebuilt.properties.Vndk.Enabled) { + m.VendorProperties.IsLLNDK = true + } } } @@ -110,7 +110,7 @@ func (lto *lto) flags(ctx ModuleContext, flags Flags) Flags { var ltoLdFlags []string // Do not perform costly LTO optimizations for Eng builds. - if Bool(lto.Properties.Lto_O0) || ctx.Config().Eng() { + if Bool(lto.Properties.Lto_O0) || ctx.optimizeForSize() || ctx.Config().Eng() { ltoLdFlags = append(ltoLdFlags, "-Wl,--lto-O0") } diff --git a/cc/sanitize.go b/cc/sanitize.go index 3abba8065..d72d7d36f 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -681,12 +681,6 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { s.Integer_overflow = nil } - // Also disable CFI for VNDK variants of components - if ctx.isVndk() && ctx.useVndk() { - s.Cfi = nil - s.Diag.Cfi = nil - } - if ctx.inRamdisk() || ctx.inVendorRamdisk() || ctx.inRecovery() { // HWASan ramdisk (which is built from recovery) goes over some bootloader limit. // Keep libc instrumented so that ramdisk / vendor_ramdisk / recovery can run hwasan-instrumented code if necessary. diff --git a/cc/testing.go b/cc/testing.go index 989be0272..02f992426 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -555,7 +555,6 @@ var PrepareForTestWithCcBuildComponents = android.GroupFixturePreparers( ctx.RegisterModuleType("cc_test_library", TestLibraryFactory) ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory) - RegisterVndkLibraryTxtTypes(ctx) RegisterLlndkLibraryTxtType(ctx) }), @@ -704,7 +703,6 @@ func CreateTestContext(config android.Config) *android.TestContext { ctx.RegisterModuleType("filegroup", android.FileGroupFactory) ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory) - RegisterVndkLibraryTxtTypes(ctx) RegisterLlndkLibraryTxtType(ctx) ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators) diff --git a/cc/vndk.go b/cc/vndk.go index 7141ea812..9d196a0f8 100644 --- a/cc/vndk.go +++ b/cc/vndk.go @@ -15,25 +15,17 @@ package cc import ( - "errors" - "fmt" "strings" "android/soong/android" - "android/soong/etc" - - "github.com/google/blueprint" - "github.com/google/blueprint/proptools" ) const ( - llndkLibrariesTxt = "llndk.libraries.txt" - llndkLibrariesTxtForApex = "llndk.libraries.txt.apex" - vndkCoreLibrariesTxt = "vndkcore.libraries.txt" - vndkSpLibrariesTxt = "vndksp.libraries.txt" - vndkPrivateLibrariesTxt = "vndkprivate.libraries.txt" - vndkProductLibrariesTxt = "vndkproduct.libraries.txt" - vndkUsingCoreVariantLibrariesTxt = "vndkcorevariant.libraries.txt" + llndkLibrariesTxt = "llndk.libraries.txt" + vndkCoreLibrariesTxt = "vndkcore.libraries.txt" + vndkSpLibrariesTxt = "vndksp.libraries.txt" + vndkPrivateLibrariesTxt = "vndkprivate.libraries.txt" + vndkProductLibrariesTxt = "vndkproduct.libraries.txt" ) func VndkLibrariesTxtModules(vndkVersion string, ctx android.BaseModuleContext) []string { @@ -83,440 +75,9 @@ type VndkProperties struct { } } -type vndkdep struct { - Properties VndkProperties -} - -func (vndk *vndkdep) props() []interface{} { - return []interface{}{&vndk.Properties} -} - -func (vndk *vndkdep) isVndk() bool { - return Bool(vndk.Properties.Vndk.Enabled) -} - -func (vndk *vndkdep) isVndkSp() bool { - return Bool(vndk.Properties.Vndk.Support_system_process) -} - -func (vndk *vndkdep) isVndkExt() bool { - return vndk.Properties.Vndk.Extends != nil -} - -func (vndk *vndkdep) getVndkExtendsModuleName() string { - return String(vndk.Properties.Vndk.Extends) -} - -func (vndk *vndkdep) typeName() string { - if !vndk.isVndk() { - return "native:vendor" - } - if !vndk.isVndkExt() { - if !vndk.isVndkSp() { - return "native:vendor:vndk" - } - return "native:vendor:vndksp" - } - if !vndk.isVndkSp() { - return "native:vendor:vndkext" - } - return "native:vendor:vndkspext" -} - -// VNDK link type check from a module with UseVndk() == true. -func (vndk *vndkdep) vndkCheckLinkType(ctx android.BaseModuleContext, to *Module, tag blueprint.DependencyTag) { - if to.linker == nil { - return - } - if !vndk.isVndk() { - // Non-VNDK modules those installed to /vendor, /system/vendor, - // /product or /system/product cannot depend on VNDK-private modules - // that include VNDK-core-private, VNDK-SP-private and LLNDK-private. - if to.IsVndkPrivate() { - ctx.ModuleErrorf("non-VNDK module should not link to %q which has `private: true`", to.Name()) - } - } - if lib, ok := to.linker.(*libraryDecorator); !ok || !lib.shared() { - // Check only shared libraries. - // Other (static) libraries are allowed to link. - return - } - - if to.IsLlndk() { - // LL-NDK libraries are allowed to link - return - } - - if !to.UseVndk() { - ctx.ModuleErrorf("(%s) should not link to %q which is not a vendor-available library", - vndk.typeName(), to.Name()) - return - } - if tag == vndkExtDepTag { - // Ensure `extends: "name"` property refers a vndk module that has vendor_available - // and has identical vndk properties. - if to.vndkdep == nil || !to.vndkdep.isVndk() { - ctx.ModuleErrorf("`extends` refers a non-vndk module %q", to.Name()) - return - } - if vndk.isVndkSp() != to.vndkdep.isVndkSp() { - ctx.ModuleErrorf( - "`extends` refers a module %q with mismatched support_system_process", - to.Name()) - return - } - if to.IsVndkPrivate() { - ctx.ModuleErrorf( - "`extends` refers module %q which has `private: true`", - to.Name()) - return - } - } - if to.vndkdep == nil { - return - } - - // Check the dependencies of VNDK shared libraries. - if err := vndkIsVndkDepAllowed(vndk, to.vndkdep); err != nil { - ctx.ModuleErrorf("(%s) should not link to %q (%s): %v", - vndk.typeName(), to.Name(), to.vndkdep.typeName(), err) - return - } -} - -func vndkIsVndkDepAllowed(from *vndkdep, to *vndkdep) error { - // Check the dependencies of VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext and vendor modules. - if from.isVndkExt() { - if from.isVndkSp() { - if to.isVndk() && !to.isVndkSp() { - return errors.New("VNDK-SP extensions must not depend on VNDK or VNDK extensions") - } - return nil - } - // VNDK-Ext may depend on VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext, or vendor libs. - return nil - } - if from.isVndk() { - if to.isVndkExt() { - return errors.New("VNDK-core and VNDK-SP must not depend on VNDK extensions") - } - if from.isVndkSp() { - if !to.isVndkSp() { - return errors.New("VNDK-SP must only depend on VNDK-SP") - } - return nil - } - if !to.isVndk() { - return errors.New("VNDK-core must only depend on VNDK-core or VNDK-SP") - } - return nil - } - // Vendor modules may depend on VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext, or vendor libs. - return nil -} - -type moduleListerFunc func(ctx android.SingletonContext) (moduleNames, fileNames []string) - -var ( - vndkSPLibraries = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKSP }) - vndkCoreLibraries = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKCore }) - vndkPrivateLibraries = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKPrivate }) - vndkProductLibraries = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKProduct }) -) - -// vndkModuleLister takes a predicate that operates on a Module and returns a moduleListerFunc -// that produces a list of module names and output file names for which the predicate returns true. -func vndkModuleLister(predicate func(*Module) bool) moduleListerFunc { - return func(ctx android.SingletonContext) (moduleNames, fileNames []string) { - ctx.VisitAllModules(func(m android.Module) { - if c, ok := m.(*Module); ok && predicate(c) && !c.IsVndkPrebuiltLibrary() { - filename, err := getVndkFileName(c) - if err != nil { - ctx.ModuleErrorf(m, "%s", err) - } - moduleNames = append(moduleNames, ctx.ModuleName(m)) - fileNames = append(fileNames, filename) - } - }) - moduleNames = android.SortedUniqueStrings(moduleNames) - fileNames = android.SortedUniqueStrings(fileNames) - return - } -} - -// vndkModuleListRemover takes a moduleListerFunc and a prefix and returns a moduleListerFunc -// that returns the same lists as the input moduleListerFunc, but with modules with the -// given prefix removed. -func vndkModuleListRemover(lister moduleListerFunc, prefix string) moduleListerFunc { - return func(ctx android.SingletonContext) (moduleNames, fileNames []string) { - moduleNames, fileNames = lister(ctx) - filter := func(in []string) []string { - out := make([]string, 0, len(in)) - for _, lib := range in { - if strings.HasPrefix(lib, prefix) { - continue - } - out = append(out, lib) - } - return out - } - return filter(moduleNames), filter(fileNames) - } -} - -func processVndkLibrary(mctx android.BottomUpMutatorContext, m *Module) { - if m.InProduct() { - // We may skip the steps for the product variants because they - // are already covered by the vendor variants. - return - } - - name := m.BaseModuleName() - - if lib := m.library; lib != nil && lib.hasStubsVariants() && name != "libz" { - // b/155456180 libz is the ONLY exception here. We don't want to make - // libz an LLNDK library because we in general can't guarantee that - // libz will behave consistently especially about the compression. - // i.e. the compressed output might be different across releases. - // As the library is an external one, it's risky to keep the compatibility - // promise if it becomes an LLNDK. - mctx.PropertyErrorf("vndk.enabled", "This library provides stubs. Shouldn't be VNDK. Consider making it as LLNDK") - } - - if m.vndkdep.isVndkSp() { - m.VendorProperties.IsVNDKSP = true - } else { - m.VendorProperties.IsVNDKCore = true - } - if m.IsVndkPrivate() { - m.VendorProperties.IsVNDKPrivate = true - } - if Bool(m.VendorProperties.Product_available) { - m.VendorProperties.IsVNDKProduct = true - } -} - -// Check for modules that mustn't be VNDK -func shouldSkipVndkMutator(ctx android.ConfigAndErrorContext, m *Module) bool { - if !m.Enabled(ctx) { - return true - } - if !m.Device() { - // Skip non-device modules - return true - } - if m.Target().NativeBridge == android.NativeBridgeEnabled { - // Skip native_bridge modules - return true - } - return false -} - -func IsForVndkApex(mctx android.BottomUpMutatorContext, m *Module) bool { - if shouldSkipVndkMutator(mctx, m) { - return false - } - - // TODO(b/142675459): Use enabled: to select target device in vndk_prebuilt_shared - // When b/142675459 is landed, remove following check - if p, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok { - // prebuilt vndk modules should match with device - if !p.MatchesWithDevice(mctx.DeviceConfig()) { - return false - } - } - - if lib, ok := m.linker.(libraryInterface); ok { - // VNDK APEX doesn't need stub variants - if lib.buildStubs() { - return false - } - return lib.shared() && m.InVendor() && m.IsVndk() && !m.IsVndkExt() - } - return false -} - -// gather list of vndk-core, vndk-sp, and ll-ndk libs -func VndkMutator(mctx android.BottomUpMutatorContext) { - m, ok := mctx.Module().(*Module) - if !ok { - return - } - - if shouldSkipVndkMutator(mctx, m) { - return - } - - lib, isLib := m.linker.(*libraryDecorator) - prebuiltLib, isPrebuiltLib := m.linker.(*prebuiltLibraryLinker) - - if m.InVendorOrProduct() && isLib && lib.hasLLNDKStubs() { - m.VendorProperties.IsVNDKPrivate = Bool(lib.Properties.Llndk.Private) - } - if m.InVendorOrProduct() && isPrebuiltLib && prebuiltLib.hasLLNDKStubs() { - m.VendorProperties.IsVNDKPrivate = Bool(prebuiltLib.Properties.Llndk.Private) - } - - if (isLib && lib.buildShared()) || (isPrebuiltLib && prebuiltLib.buildShared()) { - if m.vndkdep != nil && m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() { - processVndkLibrary(mctx, m) - return - } - } -} - -func init() { - RegisterVndkLibraryTxtTypes(android.InitRegistrationContext) -} - -func RegisterVndkLibraryTxtTypes(ctx android.RegistrationContext) { - ctx.RegisterParallelSingletonModuleType("vndksp_libraries_txt", vndkSPLibrariesTxtFactory) - ctx.RegisterParallelSingletonModuleType("vndkcore_libraries_txt", vndkCoreLibrariesTxtFactory) - ctx.RegisterParallelSingletonModuleType("vndkprivate_libraries_txt", vndkPrivateLibrariesTxtFactory) - ctx.RegisterParallelSingletonModuleType("vndkproduct_libraries_txt", vndkProductLibrariesTxtFactory) -} - -type vndkLibrariesTxt struct { - android.SingletonModuleBase - - lister moduleListerFunc - makeVarName string - filterOutFromMakeVar string - - properties VndkLibrariesTxtProperties - - outputFile android.OutputPath - moduleNames []string - fileNames []string -} - -type VndkLibrariesTxtProperties struct { - Insert_vndk_version *bool - Stem *string -} - -var _ etc.PrebuiltEtcModule = &vndkLibrariesTxt{} - -// vndksp_libraries_txt is a singleton module whose content is a list of VNDKSP libraries -// generated by Soong but can be referenced by other modules. -// For example, apex_vndk can depend on these files as prebuilt. -func vndkSPLibrariesTxtFactory() android.SingletonModule { - return newVndkLibrariesTxt(vndkSPLibraries, "VNDK_SAMEPROCESS_LIBRARIES") -} - -// vndkcore_libraries_txt is a singleton module whose content is a list of VNDK core libraries -// generated by Soong but can be referenced by other modules. -// For example, apex_vndk can depend on these files as prebuilt. -func vndkCoreLibrariesTxtFactory() android.SingletonModule { - return newVndkLibrariesTxt(vndkCoreLibraries, "VNDK_CORE_LIBRARIES") -} - -// vndkprivate_libraries_txt is a singleton module whose content is a list of VNDK private libraries -// generated by Soong but can be referenced by other modules. -// For example, apex_vndk can depend on these files as prebuilt. -func vndkPrivateLibrariesTxtFactory() android.SingletonModule { - return newVndkLibrariesTxt(vndkPrivateLibraries, "VNDK_PRIVATE_LIBRARIES") -} - -// vndkproduct_libraries_txt is a singleton module whose content is a list of VNDK product libraries -// generated by Soong but can be referenced by other modules. -// For example, apex_vndk can depend on these files as prebuilt. -func vndkProductLibrariesTxtFactory() android.SingletonModule { - return newVndkLibrariesTxt(vndkProductLibraries, "VNDK_PRODUCT_LIBRARIES") -} - -func newVndkLibrariesWithMakeVarFilter(lister moduleListerFunc, makeVarName string, filter string) android.SingletonModule { - m := &vndkLibrariesTxt{ - lister: lister, - makeVarName: makeVarName, - filterOutFromMakeVar: filter, - } - m.AddProperties(&m.properties) - android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) - return m -} - -func newVndkLibrariesTxt(lister moduleListerFunc, makeVarName string) android.SingletonModule { - return newVndkLibrariesWithMakeVarFilter(lister, makeVarName, "") -} - func insertVndkVersion(filename string, vndkVersion string) string { if index := strings.LastIndex(filename, "."); index != -1 { return filename[:index] + "." + vndkVersion + filename[index:] } return filename } - -func (txt *vndkLibrariesTxt) GenerateAndroidBuildActions(ctx android.ModuleContext) { - filename := proptools.StringDefault(txt.properties.Stem, txt.Name()) - - txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath - - installPath := android.PathForModuleInstall(ctx, "etc") - ctx.InstallFile(installPath, filename, txt.outputFile) - - ctx.SetOutputFiles(android.Paths{txt.outputFile}, "") -} - -func (txt *vndkLibrariesTxt) GenerateSingletonBuildActions(ctx android.SingletonContext) { - txt.moduleNames, txt.fileNames = txt.lister(ctx) - android.WriteFileRule(ctx, txt.outputFile, strings.Join(txt.fileNames, "\n")) -} - -func (txt *vndkLibrariesTxt) AndroidMkEntries() []android.AndroidMkEntries { - return []android.AndroidMkEntries{android.AndroidMkEntries{ - Class: "ETC", - OutputFile: android.OptionalPathForPath(txt.outputFile), - ExtraEntries: []android.AndroidMkExtraEntriesFunc{ - func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { - entries.SetString("LOCAL_MODULE_STEM", txt.outputFile.Base()) - }, - }, - }} -} - -func (txt *vndkLibrariesTxt) MakeVars(ctx android.MakeVarsContext) { - if txt.makeVarName == "" { - return - } - - filter := func(modules []string, prefix string) []string { - if prefix == "" { - return modules - } - var result []string - for _, module := range modules { - if strings.HasPrefix(module, prefix) { - continue - } else { - result = append(result, module) - } - } - return result - } - ctx.Strict(txt.makeVarName, strings.Join(filter(txt.moduleNames, txt.filterOutFromMakeVar), " ")) -} - -// PrebuiltEtcModule interface -func (txt *vndkLibrariesTxt) BaseDir() string { - return "etc" -} - -// PrebuiltEtcModule interface -func (txt *vndkLibrariesTxt) SubDir() string { - return "" -} - -func (txt *vndkLibrariesTxt) OutputFiles(tag string) (android.Paths, error) { - return android.Paths{txt.outputFile}, nil -} - -func getVndkFileName(m *Module) (string, error) { - if library, ok := m.linker.(*libraryDecorator); ok { - return library.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil - } - if prebuilt, ok := m.linker.(*prebuiltLibraryLinker); ok { - return prebuilt.libraryDecorator.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil - } - return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", m.linker) -} diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go index 4d2412fe5..e7dff4012 100644 --- a/cc/vndk_prebuilt.go +++ b/cc/vndk_prebuilt.go @@ -49,6 +49,8 @@ var ( // }, // } type vndkPrebuiltProperties struct { + VndkProperties + // VNDK snapshot version. Version *string @@ -268,3 +270,14 @@ func VndkPrebuiltSharedFactory() android.Module { func init() { android.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory) } + +func IsForVndkApex(mctx android.BottomUpMutatorContext, m *Module) bool { + if !m.Enabled(mctx) { + return true + } + + if p, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok { + return p.MatchesWithDevice(mctx.DeviceConfig()) && Bool(p.properties.Vndk.Enabled) + } + return false +} diff --git a/cmd/release_config/release_config_lib/flag_artifact.go b/cmd/release_config/release_config_lib/flag_artifact.go index 6cdde7c06..cfac7d794 100644 --- a/cmd/release_config/release_config_lib/flag_artifact.go +++ b/cmd/release_config/release_config_lib/flag_artifact.go @@ -67,7 +67,7 @@ func FlagArtifactsFactory(artifactsPath string) *FlagArtifacts { if artifactsPath != "" { fas := &rc_proto.FlagArtifacts{} LoadMessage(artifactsPath, fas) - for _, fa_pb := range fas.FlagArtifacts { + for _, fa_pb := range fas.Flags { fa := &FlagArtifact{} fa.FlagDeclaration = fa_pb.GetFlagDeclaration() if val := fa_pb.GetValue(); val != nil { diff --git a/cmd/release_config/release_config_lib/release_config.go b/cmd/release_config/release_config_lib/release_config.go index f0ce1bb67..6d71d9343 100644 --- a/cmd/release_config/release_config_lib/release_config.go +++ b/cmd/release_config/release_config_lib/release_config.go @@ -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 @@ -282,13 +290,13 @@ func (config *ReleaseConfig) GenerateReleaseConfig(configs *ReleaseConfigs) erro if _, ok := config.PartitionBuildFlags[container]; !ok { config.PartitionBuildFlags[container] = &rc_proto.FlagArtifacts{} } - config.PartitionBuildFlags[container].FlagArtifacts = append(config.PartitionBuildFlags[container].FlagArtifacts, artifact) + config.PartitionBuildFlags[container].Flags = append(config.PartitionBuildFlags[container].Flags, artifact) } } config.ReleaseConfigArtifact = &rc_proto.ReleaseConfigArtifact{ Name: proto.String(config.Name), OtherNames: config.OtherNames, - FlagArtifacts: func() []*rc_proto.FlagArtifact { + Flags: func() []*rc_proto.FlagArtifact { ret := []*rc_proto.FlagArtifact{} flagNames := []string{} for k := range config.FlagArtifacts { @@ -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) @@ -386,7 +411,7 @@ func (config *ReleaseConfig) WriteMakefile(outFile, targetRelease string, config func (config *ReleaseConfig) WritePartitionBuildFlags(outDir string) error { var err error for partition, flags := range config.PartitionBuildFlags { - slices.SortFunc(flags.FlagArtifacts, func(a, b *rc_proto.FlagArtifact) int { + slices.SortFunc(flags.Flags, func(a, b *rc_proto.FlagArtifact) int { return cmp.Compare(*a.FlagDeclaration.Name, *b.FlagDeclaration.Name) }) // The json file name must not be modified as this is read from diff --git a/cmd/release_config/release_config_proto/build_flags_common.pb.go b/cmd/release_config/release_config_proto/build_flags_common.pb.go index 1e927db6c..82fbcfaf9 100644 --- a/cmd/release_config/release_config_proto/build_flags_common.pb.go +++ b/cmd/release_config/release_config_proto/build_flags_common.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc v3.21.12 // source: build_flags_common.proto diff --git a/cmd/release_config/release_config_proto/build_flags_declarations.pb.go b/cmd/release_config/release_config_proto/build_flags_declarations.pb.go index c0573edf3..73a7e8790 100644 --- a/cmd/release_config/release_config_proto/build_flags_declarations.pb.go +++ b/cmd/release_config/release_config_proto/build_flags_declarations.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc v3.21.12 // source: build_flags_declarations.proto diff --git a/cmd/release_config/release_config_proto/build_flags_out.pb.go b/cmd/release_config/release_config_proto/build_flags_out.pb.go index 309ec3452..b246eb66d 100644 --- a/cmd/release_config/release_config_proto/build_flags_out.pb.go +++ b/cmd/release_config/release_config_proto/build_flags_out.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc v3.21.12 // source: build_flags_out.proto @@ -163,7 +163,7 @@ type FlagArtifacts struct { unknownFields protoimpl.UnknownFields // The artifacts - FlagArtifacts []*FlagArtifact `protobuf:"bytes,1,rep,name=flag_artifacts,json=flagArtifacts" json:"flag_artifacts,omitempty"` + Flags []*FlagArtifact `protobuf:"bytes,1,rep,name=flags" json:"flags,omitempty"` } func (x *FlagArtifacts) Reset() { @@ -198,9 +198,9 @@ func (*FlagArtifacts) Descriptor() ([]byte, []int) { return file_build_flags_out_proto_rawDescGZIP(), []int{2} } -func (x *FlagArtifacts) GetFlagArtifacts() []*FlagArtifact { +func (x *FlagArtifacts) GetFlags() []*FlagArtifact { if x != nil { - return x.FlagArtifacts + return x.Flags } return nil } @@ -217,7 +217,7 @@ type ReleaseConfigArtifact struct { OtherNames []string `protobuf:"bytes,2,rep,name=other_names,json=otherNames" json:"other_names,omitempty"` // The complete set of build flags in this release config, after all // inheritance and other processing is complete. - FlagArtifacts []*FlagArtifact `protobuf:"bytes,3,rep,name=flag_artifacts,json=flagArtifacts" json:"flag_artifacts,omitempty"` + Flags []*FlagArtifact `protobuf:"bytes,3,rep,name=flags" json:"flags,omitempty"` // The (complete) list of aconfig_value_sets Soong modules to use. AconfigValueSets []string `protobuf:"bytes,4,rep,name=aconfig_value_sets,json=aconfigValueSets" json:"aconfig_value_sets,omitempty"` // The names of the release_config_artifacts from which we inherited. @@ -277,9 +277,9 @@ func (x *ReleaseConfigArtifact) GetOtherNames() []string { return nil } -func (x *ReleaseConfigArtifact) GetFlagArtifacts() []*FlagArtifact { +func (x *ReleaseConfigArtifact) GetFlags() []*FlagArtifact { if x != nil { - return x.FlagArtifacts + return x.Flags } return nil } @@ -406,67 +406,67 @@ var file_build_flags_out_proto_rawDesc = []byte{ 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x52, 0x06, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x22, 0x64, 0x0a, 0x0e, 0x66, 0x6c, 0x61, - 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, 0x52, 0x0a, 0x0e, 0x66, - 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, - 0x52, 0x0d, 0x66, 0x6c, 0x61, 0x67, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x22, - 0xb1, 0x02, 0x0a, 0x17, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x1f, 0x0a, 0x0b, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x73, - 0x12, 0x52, 0x0a, 0x0e, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, - 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, - 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x72, 0x74, - 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x0d, 0x66, 0x6c, 0x61, 0x67, 0x41, 0x72, 0x74, 0x69, 0x66, - 0x61, 0x63, 0x74, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x10, 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x65, - 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x73, 0x18, 0x05, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x73, 0x12, 0x20, - 0x0a, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, - 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x67, 0x65, 0x73, - 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x53, 0x74, 0x61, - 0x67, 0x65, 0x73, 0x22, 0xe8, 0x03, 0x0a, 0x18, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, - 0x12, 0x5c, 0x0a, 0x0e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, - 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, - 0x0d, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x69, - 0x0a, 0x15, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, - 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, - 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, - 0x66, 0x61, 0x63, 0x74, 0x52, 0x13, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x52, 0x65, 0x6c, 0x65, 0x61, - 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x87, 0x01, 0x0a, 0x17, 0x72, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6d, 0x61, 0x70, - 0x73, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x50, 0x2e, 0x61, 0x6e, + 0x74, 0x52, 0x06, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x22, 0x63, 0x0a, 0x0e, 0x66, 0x6c, 0x61, + 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x12, 0x41, 0x0a, 0x05, 0x66, + 0x6c, 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x61, 0x6e, 0x64, + 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x52, 0x0e, + 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x22, 0xb0, + 0x02, 0x0a, 0x17, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, + 0x0a, 0x0b, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, + 0x41, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, + 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, + 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x66, 0x6c, + 0x61, 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x05, 0x66, 0x6c, 0x61, + 0x67, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, + 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x65, 0x74, 0x73, + 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x73, 0x12, 0x20, 0x0a, 0x0b, + 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x21, + 0x0a, 0x0c, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x67, 0x65, 0x73, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x67, 0x65, + 0x73, 0x52, 0x0e, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, + 0x73, 0x22, 0xe8, 0x03, 0x0a, 0x18, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x73, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x5c, + 0x0a, 0x0e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, + 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x0d, 0x72, + 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x69, 0x0a, 0x15, + 0x6f, 0x74, 0x68, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, - 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, - 0x61, 0x63, 0x74, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x4d, 0x61, 0x70, 0x73, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x72, - 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x73, - 0x4d, 0x61, 0x70, 0x1a, 0x79, 0x0a, 0x19, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x73, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x46, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x30, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, - 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, - 0x6d, 0x61, 0x70, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x33, - 0x5a, 0x31, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, - 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72, - 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, + 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, + 0x63, 0x74, 0x52, 0x13, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x87, 0x01, 0x0a, 0x17, 0x72, 0x65, 0x6c, 0x65, + 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6d, 0x61, 0x70, 0x73, 0x5f, + 0x6d, 0x61, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x50, 0x2e, 0x61, 0x6e, 0x64, 0x72, + 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, + 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x5f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, + 0x61, 0x70, 0x73, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x72, 0x65, 0x6c, + 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x73, 0x4d, 0x61, + 0x70, 0x1a, 0x79, 0x0a, 0x19, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x4d, 0x61, 0x70, 0x73, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x46, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x30, 0x2e, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, + 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x72, + 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6d, 0x61, + 0x70, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x33, 0x5a, 0x31, + 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x72, 0x65, + 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x72, 0x65, 0x6c, + 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, } var ( @@ -498,8 +498,8 @@ var file_build_flags_out_proto_depIdxs = []int32{ 7, // 1: android.release_config_proto.flag_artifact.flag_declaration:type_name -> android.release_config_proto.flag_declaration 6, // 2: android.release_config_proto.flag_artifact.value:type_name -> android.release_config_proto.value 0, // 3: android.release_config_proto.flag_artifact.traces:type_name -> android.release_config_proto.tracepoint - 1, // 4: android.release_config_proto.flag_artifacts.flag_artifacts:type_name -> android.release_config_proto.flag_artifact - 1, // 5: android.release_config_proto.release_config_artifact.flag_artifacts:type_name -> android.release_config_proto.flag_artifact + 1, // 4: android.release_config_proto.flag_artifacts.flags:type_name -> android.release_config_proto.flag_artifact + 1, // 5: android.release_config_proto.release_config_artifact.flags:type_name -> android.release_config_proto.flag_artifact 3, // 6: android.release_config_proto.release_configs_artifact.release_config:type_name -> android.release_config_proto.release_config_artifact 3, // 7: android.release_config_proto.release_configs_artifact.other_release_configs:type_name -> android.release_config_proto.release_config_artifact 5, // 8: android.release_config_proto.release_configs_artifact.release_config_maps_map:type_name -> android.release_config_proto.release_configs_artifact.ReleaseConfigMapsMapEntry diff --git a/cmd/release_config/release_config_proto/build_flags_out.proto b/cmd/release_config/release_config_proto/build_flags_out.proto index 0cbc15713..2f1715b39 100644 --- a/cmd/release_config/release_config_proto/build_flags_out.proto +++ b/cmd/release_config/release_config_proto/build_flags_out.proto @@ -58,7 +58,8 @@ message flag_artifact { message flag_artifacts { // The artifacts - repeated flag_artifact flag_artifacts = 1; + repeated flag_artifact flags = 1; + reserved "flag_artifacts"; } message release_config_artifact { @@ -71,7 +72,8 @@ message release_config_artifact { // The complete set of build flags in this release config, after all // inheritance and other processing is complete. - repeated flag_artifact flag_artifacts = 3; + repeated flag_artifact flags = 3; + reserved "flag_artifacts"; // The (complete) list of aconfig_value_sets Soong modules to use. repeated string aconfig_value_sets = 4; diff --git a/cmd/release_config/release_config_proto/build_flags_src.pb.go b/cmd/release_config/release_config_proto/build_flags_src.pb.go index 8de340ea1..bc5f5c013 100644 --- a/cmd/release_config/release_config_proto/build_flags_src.pb.go +++ b/cmd/release_config/release_config_proto/build_flags_src.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.33.0 // protoc v3.21.12 // source: build_flags_src.proto diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go index 3dac8bdae..a8be7ec16 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -16,6 +16,7 @@ package main import ( "bytes" + "encoding/json" "errors" "flag" "fmt" @@ -28,11 +29,11 @@ import ( "android/soong/android/allowlists" "android/soong/bp2build" "android/soong/shared" - "github.com/google/blueprint" "github.com/google/blueprint/bootstrap" "github.com/google/blueprint/deptools" "github.com/google/blueprint/metrics" + "github.com/google/blueprint/proptools" androidProtobuf "google.golang.org/protobuf/android" ) @@ -49,6 +50,14 @@ var ( cmdlineArgs android.CmdArgs ) +const configCacheFile = "config.cache" + +type ConfigCache struct { + EnvDepsHash uint64 + ProductVariableFileTimestamp int64 + SoongBuildFileTimestamp int64 +} + func init() { // Flags that make sense in every mode flag.StringVar(&topDir, "top", "", "Top directory of the Android source tree") @@ -82,6 +91,7 @@ func init() { // Flags that probably shouldn't be flags of soong_build, but we haven't found // the time to remove them yet flag.BoolVar(&cmdlineArgs.RunGoTests, "t", false, "build and run go tests during bootstrap") + flag.BoolVar(&cmdlineArgs.IncrementalBuildActions, "incremental-build-actions", false, "generate build actions incrementally") // Disable deterministic randomization in the protobuf package, so incremental // builds with unrelated Soong changes don't trigger large rebuilds (since we @@ -218,6 +228,60 @@ func writeDepFile(outputFile string, eventHandler *metrics.EventHandler, ninjaDe maybeQuit(err, "error writing depfile '%s'", depFile) } +// Check if there are changes to the environment file, product variable file and +// soong_build binary, in which case no incremental will be performed. +func incrementalValid(config android.Config, configCacheFile string) (*ConfigCache, bool) { + var newConfigCache ConfigCache + data, err := os.ReadFile(shared.JoinPath(topDir, usedEnvFile)) + if err != nil { + // Clean build + if os.IsNotExist(err) { + data = []byte{} + } else { + maybeQuit(err, "") + } + } + + newConfigCache.EnvDepsHash, err = proptools.CalculateHash(data) + newConfigCache.ProductVariableFileTimestamp = getFileTimestamp(filepath.Join(topDir, cmdlineArgs.SoongVariables)) + newConfigCache.SoongBuildFileTimestamp = getFileTimestamp(filepath.Join(topDir, config.HostToolDir(), "soong_build")) + //TODO(b/344917959): out/soong/dexpreopt.config might need to be checked as well. + + file, err := os.Open(configCacheFile) + if err != nil && os.IsNotExist(err) { + return &newConfigCache, false + } + maybeQuit(err, "") + defer file.Close() + + var configCache ConfigCache + decoder := json.NewDecoder(file) + err = decoder.Decode(&configCache) + maybeQuit(err, "") + + return &newConfigCache, newConfigCache == configCache +} + +func getFileTimestamp(file string) int64 { + stat, err := os.Stat(file) + if err == nil { + return stat.ModTime().UnixMilli() + } else if !os.IsNotExist(err) { + maybeQuit(err, "") + } + return 0 +} + +func writeConfigCache(configCache *ConfigCache, configCacheFile string) { + file, err := os.Create(configCacheFile) + maybeQuit(err, "") + defer file.Close() + + encoder := json.NewEncoder(file) + err = encoder.Encode(*configCache) + maybeQuit(err, "") +} + // runSoongOnlyBuild runs the standard Soong build in a number of different modes. func runSoongOnlyBuild(ctx *android.Context, extraNinjaDeps []string) string { ctx.EventHandler.Begin("soong_build") @@ -319,8 +383,26 @@ func main() { ctx := newContext(configuration) android.StartBackgroundMetrics(configuration) + var configCache *ConfigCache + configFile := filepath.Join(topDir, ctx.Config().OutDir(), configCacheFile) + incremental := false + ctx.SetIncrementalEnabled(cmdlineArgs.IncrementalBuildActions) + if cmdlineArgs.IncrementalBuildActions { + configCache, incremental = incrementalValid(ctx.Config(), configFile) + } + ctx.SetIncrementalAnalysis(incremental) + ctx.Register() finalOutputFile := runSoongOnlyBuild(ctx, extraNinjaDeps) + + if ctx.GetIncrementalEnabled() { + data, err := shared.EnvFileContents(configuration.EnvDeps()) + maybeQuit(err, "") + configCache.EnvDepsHash, err = proptools.CalculateHash(data) + maybeQuit(err, "") + writeConfigCache(configCache, configFile) + } + writeMetrics(configuration, ctx.EventHandler, metricsDir) writeUsedEnvironmentFile(configuration) diff --git a/genrule/genrule.go b/genrule/genrule.go index 06a7e1891..b23530369 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -213,21 +213,7 @@ func (g *Module) GeneratedDeps() android.Paths { return g.outputDeps } -func (g *Module) OutputFiles(tag string) (android.Paths, error) { - if tag == "" { - return append(android.Paths{}, g.outputFiles...), nil - } - // otherwise, tag should match one of outputs - for _, outputFile := range g.outputFiles { - if outputFile.Rel() == tag { - return android.Paths{outputFile}, nil - } - } - return nil, fmt.Errorf("unsupported module reference tag %q", tag) -} - var _ android.SourceFileProducer = (*Module)(nil) -var _ android.OutputFileProducer = (*Module)(nil) func toolDepsMutator(ctx android.BottomUpMutatorContext) { if g, ok := ctx.Module().(*Module); ok { @@ -585,6 +571,19 @@ func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) { }) g.outputDeps = android.Paths{phonyFile} } + + g.setOutputFiles(ctx) +} + +func (g *Module) setOutputFiles(ctx android.ModuleContext) { + if len(g.outputFiles) == 0 { + return + } + ctx.SetOutputFiles(g.outputFiles, "") + // non-empty-string-tag should match one of the outputs + for _, files := range g.outputFiles { + ctx.SetOutputFiles(android.Paths{files}, files.Rel()) + } } // Collect information for opening IDE project files in java/jdeps.go. diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go index 1df887b3e..fba9aec65 100644 --- a/genrule/genrule_test.go +++ b/genrule/genrule_test.go @@ -1254,12 +1254,6 @@ func (t *testOutputProducer) GenerateAndroidBuildActions(ctx android.ModuleConte t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName())) } -func (t *testOutputProducer) OutputFiles(tag string) (android.Paths, error) { - return android.Paths{t.outputFile}, nil -} - -var _ android.OutputFileProducer = (*testOutputProducer)(nil) - type useSource struct { android.ModuleBase props struct { diff --git a/java/aar.go b/java/aar.go index 07392f6e5..3168d9bf4 100644 --- a/java/aar.go +++ b/java/aar.go @@ -831,12 +831,13 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) if a.usesLibrary.shouldDisableDexpreopt { a.dexpreopter.disableDexpreopt() } + aconfigTextFilePaths := getAconfigFilePaths(ctx) a.aapt.buildActions(ctx, aaptBuildActionOptions{ sdkContext: android.SdkContext(a), classLoaderContexts: a.classLoaderContexts, enforceDefaultTargetSdkVersion: false, - aconfigTextFiles: getAconfigFilePaths(ctx), + aconfigTextFiles: aconfigTextFilePaths, usesLibrary: &a.usesLibrary, }, ) @@ -906,6 +907,10 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) JniPackages: prebuiltJniPackages, }) } + + android.SetProvider(ctx, FlagsPackagesProvider, FlagsPackages{ + AconfigTextFiles: aconfigTextFilePaths, + }) } func (a *AndroidLibrary) IDEInfo(dpInfo *android.IdeInfo) { diff --git a/java/app.go b/java/app.go index a24099c28..739ef1a50 100644 --- a/java/app.go +++ b/java/app.go @@ -47,6 +47,13 @@ var ( }, "packageName") ) +type FlagsPackages struct { + // Paths to the aconfig dump output text files that are consumed by aapt2 + AconfigTextFiles android.Paths +} + +var FlagsPackagesProvider = blueprint.NewProvider[FlagsPackages]() + func RegisterAppBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("android_app", AndroidAppFactory) ctx.RegisterModuleType("android_test", AndroidTestFactory) @@ -478,18 +485,27 @@ func (a *AndroidApp) renameResourcesPackage() bool { } func getAconfigFilePaths(ctx android.ModuleContext) (aconfigTextFilePaths android.Paths) { - ctx.VisitDirectDepsWithTag(aconfigDeclarationTag, func(dep android.Module) { - if provider, ok := android.OtherModuleProvider(ctx, dep, android.AconfigDeclarationsProviderKey); ok { - aconfigTextFilePaths = append(aconfigTextFilePaths, provider.IntermediateDumpOutputPath) - } else { - ctx.ModuleErrorf("Only aconfig_declarations module type is allowed for "+ - "flags_packages property, but %s is not aconfig_declarations module type", - dep.Name(), - ) + ctx.VisitDirectDeps(func(dep android.Module) { + tag := ctx.OtherModuleDependencyTag(dep) + switch tag { + case staticLibTag: + if flagPackages, ok := android.OtherModuleProvider(ctx, dep, FlagsPackagesProvider); ok { + aconfigTextFilePaths = append(aconfigTextFilePaths, flagPackages.AconfigTextFiles...) + } + + case aconfigDeclarationTag: + if provider, ok := android.OtherModuleProvider(ctx, dep, android.AconfigDeclarationsProviderKey); ok { + aconfigTextFilePaths = append(aconfigTextFilePaths, provider.IntermediateDumpOutputPath) + } else { + ctx.ModuleErrorf("Only aconfig_declarations module type is allowed for "+ + "flags_packages property, but %s is not aconfig_declarations module type", + dep.Name(), + ) + } } }) - return aconfigTextFilePaths + return android.FirstUniquePaths(aconfigTextFilePaths) } func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) { @@ -544,6 +560,9 @@ func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) { // Use non final ids if we are doing optimized shrinking and are using R8. nonFinalIds := a.dexProperties.optimizedResourceShrinkingEnabled(ctx) && a.dexer.effectiveOptimizeEnabled() + + aconfigTextFilePaths := getAconfigFilePaths(ctx) + a.aapt.buildActions(ctx, aaptBuildActionOptions{ sdkContext: android.SdkContext(a), @@ -552,13 +571,17 @@ func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) { enforceDefaultTargetSdkVersion: a.enforceDefaultTargetSdkVersion(), forceNonFinalResourceIDs: nonFinalIds, extraLinkFlags: aaptLinkFlags, - aconfigTextFiles: getAconfigFilePaths(ctx), + aconfigTextFiles: aconfigTextFilePaths, usesLibrary: &a.usesLibrary, }, ) // apps manifests are handled by aapt, don't let Module see them a.properties.Manifest = nil + + android.SetProvider(ctx, FlagsPackagesProvider, FlagsPackages{ + AconfigTextFiles: aconfigTextFilePaths, + }) } func (a *AndroidApp) proguardBuildActions(ctx android.ModuleContext) { diff --git a/java/app_test.go b/java/app_test.go index 804949435..1a862fa54 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -4369,6 +4369,82 @@ func TestAppFlagsPackages(t *testing.T) { ) } +func TestAppFlagsPackagesPropagation(t *testing.T) { + ctx := testApp(t, ` + aconfig_declarations { + name: "foo", + package: "com.example.package.foo", + container: "com.android.foo", + srcs: [ + "foo.aconfig", + ], + } + aconfig_declarations { + name: "bar", + package: "com.example.package.bar", + container: "com.android.bar", + srcs: [ + "bar.aconfig", + ], + } + aconfig_declarations { + name: "baz", + package: "com.example.package.baz", + container: "com.android.baz", + srcs: [ + "baz.aconfig", + ], + } + android_library { + name: "foo_lib", + srcs: ["a.java"], + sdk_version: "current", + flags_packages: [ + "foo", + ], + } + android_library { + name: "bar_lib", + srcs: ["a.java"], + sdk_version: "current", + flags_packages: [ + "bar", + ], + } + android_app { + name: "baz_app", + srcs: ["a.java"], + sdk_version: "current", + flags_packages: [ + "baz", + ], + static_libs: [ + "bar_lib", + ], + libs: [ + "foo_lib", + ], + } + `) + + bazApp := ctx.ModuleForTests("baz_app", "android_common") + + // android_app module depends on aconfig_declarations listed in flags_packages + // and that of static libs, but not libs + aapt2LinkRule := bazApp.Rule("android/soong/java.aapt2Link") + linkInFlags := aapt2LinkRule.Args["inFlags"] + android.AssertStringDoesContain(t, + "aapt2 link command expected to pass feature flags arguments of flags_packages and that of its static libs", + linkInFlags, + "--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt", + ) + android.AssertStringDoesNotContain(t, + "aapt2 link command expected to not pass feature flags arguments of flags_packages of its libs", + linkInFlags, + "--feature-flags @out/soong/.intermediates/foo/intermediate.txt", + ) +} + // Test that dexpreopt is disabled if an optional_uses_libs exists, but does not provide an implementation. func TestNoDexpreoptOptionalUsesLibDoesNotHaveImpl(t *testing.T) { bp := ` diff --git a/java/base.go b/java/base.go index 49214d842..ee8df3e76 100644 --- a/java/base.go +++ b/java/base.go @@ -94,6 +94,9 @@ type CommonProperties struct { // if not blank, used as prefix to generate repackage rule Jarjar_prefix *string + // if set to true, skip the jarjar repackaging + Skip_jarjar_repackage *bool + // If not blank, set the java version passed to javac as -source and -target Java_version *string @@ -1109,11 +1112,13 @@ func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspath jarjarProviderData := j.collectJarJarRules(ctx) if jarjarProviderData != nil { android.SetProvider(ctx, JarJarProvider, *jarjarProviderData) - text := getJarJarRuleText(jarjarProviderData) - if text != "" { - ruleTextFile := android.PathForModuleOut(ctx, "repackaged-jarjar", "repackaging.txt") - android.WriteFileRule(ctx, ruleTextFile, text) - j.repackageJarjarRules = ruleTextFile + if !proptools.Bool(j.properties.Skip_jarjar_repackage) { + text := getJarJarRuleText(jarjarProviderData) + if text != "" { + ruleTextFile := android.PathForModuleOut(ctx, "repackaged-jarjar", "repackaging.txt") + android.WriteFileRule(ctx, ruleTextFile, text) + j.repackageJarjarRules = ruleTextFile + } } } diff --git a/java/java.go b/java/java.go index 08fb6782c..6fee7ce9a 100644 --- a/java/java.go +++ b/java/java.go @@ -1501,7 +1501,7 @@ func (j *TestHost) GenerateAndroidBuildActions(ctx android.ModuleContext) { InstalledFiles: j.data, OutputFile: j.outputFile, TestConfig: j.testConfig, - RequiredModuleNames: j.RequiredModuleNames(), + RequiredModuleNames: j.RequiredModuleNames(ctx), TestSuites: j.testProperties.Test_suites, IsHost: true, LocalSdkVersion: j.sdkVersion.String(), @@ -2285,10 +2285,10 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { al.stubsFlags(ctx, cmd, stubsDir) - migratingNullability := String(al.properties.Previous_api) != "" - if migratingNullability { - previousApi := android.PathForModuleSrc(ctx, String(al.properties.Previous_api)) - cmd.FlagWithInput("--migrate-nullness ", previousApi) + previousApi := String(al.properties.Previous_api) + if previousApi != "" { + previousApiFiles := android.PathsForModuleSrc(ctx, []string{previousApi}) + cmd.FlagForEachInput("--migrate-nullness ", previousApiFiles) } al.addValidation(ctx, cmd, al.validationPaths) diff --git a/java/lint.go b/java/lint.go index 82fac91cf..2eea07d31 100644 --- a/java/lint.go +++ b/java/lint.go @@ -319,25 +319,19 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.Ru cmd.FlagWithInput("@", android.PathForSource(ctx, "build/soong/java/lint_defaults.txt")) - if l.compileSdkKind == android.SdkPublic { - cmd.FlagForEachArg("--error_check ", l.extraMainlineLintErrors) - } else { - // TODO(b/268261262): Remove this branch. We're demoting NewApi to a warning due to pre-existing issues that need to be fixed. - cmd.FlagForEachArg("--warning_check ", l.extraMainlineLintErrors) - } + cmd.FlagForEachArg("--error_check ", l.extraMainlineLintErrors) cmd.FlagForEachArg("--disable_check ", l.properties.Lint.Disabled_checks) cmd.FlagForEachArg("--warning_check ", l.properties.Lint.Warning_checks) cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks) cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks) - // TODO(b/193460475): Re-enable strict updatability linting - //if l.GetStrictUpdatabilityLinting() { - // // Verify the module does not baseline issues that endanger safe updatability. - // if baselinePath := l.getBaselineFilepath(ctx); baselinePath.Valid() { - // cmd.FlagWithInput("--baseline ", baselinePath.Path()) - // cmd.FlagForEachArg("--disallowed_issues ", updatabilityChecks) - // } - //} + if l.GetStrictUpdatabilityLinting() { + // Verify the module does not baseline issues that endanger safe updatability. + if l.properties.Lint.Baseline_filename != nil { + cmd.FlagWithInput("--baseline ", android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename)) + cmd.FlagForEachArg("--disallowed_issues ", updatabilityChecks) + } + } return lintPaths{ projectXML: projectXMLPath, diff --git a/java/lint_test.go b/java/lint_test.go index 751b139e7..b51753f71 100644 --- a/java/lint_test.go +++ b/java/lint_test.go @@ -91,9 +91,8 @@ func TestJavaLintUsesCorrectBpConfig(t *testing.T) { t.Error("did not use the correct file for baseline") } - if !strings.Contains(*sboxProto.Commands[0].Command, "--warning_check NewApi") { - // TODO(b/268261262): Change this to check for --error_check - t.Error("should check NewApi warnings") + if !strings.Contains(*sboxProto.Commands[0].Command, "--error_check NewApi") { + t.Error("should check NewApi errors") } if !strings.Contains(*sboxProto.Commands[0].Command, "--error_check SomeCheck") { @@ -153,52 +152,55 @@ func TestJavaLintBypassUpdatableChecks(t *testing.T) { } } -// TODO(b/193460475): Re-enable this test -//func TestJavaLintStrictUpdatabilityLinting(t *testing.T) { -// bp := ` -// java_library { -// name: "foo", -// srcs: [ -// "a.java", -// ], -// static_libs: ["bar"], -// min_sdk_version: "29", -// sdk_version: "current", -// lint: { -// strict_updatability_linting: true, -// }, -// } -// -// java_library { -// name: "bar", -// srcs: [ -// "a.java", -// ], -// min_sdk_version: "29", -// sdk_version: "current", -// } -// ` -// fs := android.MockFS{ -// "lint-baseline.xml": nil, -// } -// -// result := android.GroupFixturePreparers(PrepareForTestWithJavaDefaultModules, fs.AddToFixture()). -// RunTestWithBp(t, bp) -// -// foo := result.ModuleForTests("foo", "android_common") -// sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto")) -// if !strings.Contains(*sboxProto.Commands[0].Command, -// "--baseline lint-baseline.xml --disallowed_issues NewApi") { -// t.Error("did not restrict baselining NewApi") -// } -// -// bar := result.ModuleForTests("bar", "android_common") -// sboxProto = android.RuleBuilderSboxProtoForTests(t, bar.Output("lint.sbox.textproto")) -// if !strings.Contains(*sboxProto.Commands[0].Command, -// "--baseline lint-baseline.xml --disallowed_issues NewApi") { -// t.Error("did not restrict baselining NewApi") -// } -//} +func TestJavaLintStrictUpdatabilityLinting(t *testing.T) { + bp := ` + java_library { + name: "foo", + srcs: [ + "a.java", + ], + static_libs: ["bar"], + min_sdk_version: "29", + sdk_version: "current", + lint: { + strict_updatability_linting: true, + baseline_filename: "lint-baseline.xml", + }, + } + + java_library { + name: "bar", + srcs: [ + "a.java", + ], + min_sdk_version: "29", + sdk_version: "current", + lint: { + baseline_filename: "lint-baseline.xml", + } + } + ` + fs := android.MockFS{ + "lint-baseline.xml": nil, + } + + result := android.GroupFixturePreparers(PrepareForTestWithJavaDefaultModules, fs.AddToFixture()). + RunTestWithBp(t, bp) + + foo := result.ModuleForTests("foo", "android_common") + sboxProto := android.RuleBuilderSboxProtoForTests(t, result.TestContext, foo.Output("lint.sbox.textproto")) + if !strings.Contains(*sboxProto.Commands[0].Command, + "--baseline lint-baseline.xml --disallowed_issues NewApi") { + t.Error("did not restrict baselining NewApi") + } + + bar := result.ModuleForTests("bar", "android_common") + sboxProto = android.RuleBuilderSboxProtoForTests(t, result.TestContext, bar.Output("lint.sbox.textproto")) + if !strings.Contains(*sboxProto.Commands[0].Command, + "--baseline lint-baseline.xml --disallowed_issues NewApi") { + t.Error("did not restrict baselining NewApi") + } +} func TestJavaLintDatabaseSelectionFull(t *testing.T) { testCases := []struct { diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go index 99fa092be..45b994498 100644 --- a/java/platform_compat_config.go +++ b/java/platform_compat_config.go @@ -61,6 +61,8 @@ type platformCompatConfig struct { installDirPath android.InstallPath configFile android.OutputPath metadataFile android.OutputPath + + installConfigFile android.InstallPath } func (p *platformCompatConfig) compatConfigMetadata() android.Path { @@ -106,8 +108,12 @@ func (p *platformCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleCon FlagWithOutput("--merged-config ", p.metadataFile) p.installDirPath = android.PathForModuleInstall(ctx, "etc", "compatconfig") + p.installConfigFile = android.PathForModuleInstall(ctx, "etc", "compatconfig", p.configFile.Base()) rule.Build(configFileName, "Extract compat/compat_config.xml and install it") +} +func (p *platformCompatConfig) FilesToInstall() android.InstallPaths { + return android.InstallPaths{p.installConfigFile} } func (p *platformCompatConfig) AndroidMkEntries() []android.AndroidMkEntries { @@ -266,7 +272,7 @@ func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.Singlet func (p *platformCompatConfigSingleton) MakeVars(ctx android.MakeVarsContext) { if p.metadata != nil { - ctx.Strict("INTERNAL_PLATFORM_MERGED_COMPAT_CONFIG", p.metadata.String()) + ctx.DistForGoal("droidcore", p.metadata) } } diff --git a/java/rro.go b/java/rro.go index 72170fc6d..0fc6e1c6f 100644 --- a/java/rro.go +++ b/java/rro.go @@ -150,12 +150,13 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC aaptLinkFlags = append(aaptLinkFlags, "--rename-overlay-category "+*r.overridableProperties.Category) } + aconfigTextFilePaths := getAconfigFilePaths(ctx) r.aapt.buildActions(ctx, aaptBuildActionOptions{ sdkContext: r, enforceDefaultTargetSdkVersion: false, extraLinkFlags: aaptLinkFlags, - aconfigTextFiles: getAconfigFilePaths(ctx), + aconfigTextFiles: aconfigTextFilePaths, }, ) @@ -176,6 +177,10 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC partition := rroPartition(ctx) r.installDir = android.PathForModuleInPartitionInstall(ctx, partition, "overlay", String(r.properties.Theme)) ctx.InstallFile(r.installDir, r.outputFile.Base(), r.outputFile) + + android.SetProvider(ctx, FlagsPackagesProvider, FlagsPackages{ + AconfigTextFiles: aconfigTextFilePaths, + }) } func (r *RuntimeResourceOverlay) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { diff --git a/java/sdk_library.go b/java/sdk_library.go index e9fa83ae7..c19b07bb6 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -3279,7 +3279,7 @@ func (module *sdkLibraryXml) implPath(ctx android.ModuleContext) string { // TODO(b/146468504): ApexVariationName() is only a soong module name, not apex name. // In most cases, this works fine. But when apex_name is set or override_apex is used // this can be wrong. - return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexInfo.ApexVariationName, implName) + return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexInfo.BaseApexName, implName) } partition := "system" if module.SocSpecific() { diff --git a/phony/phony.go b/phony/phony.go index 54692386a..b421176be 100644 --- a/phony/phony.go +++ b/phony/phony.go @@ -49,7 +49,7 @@ func PhonyFactory() android.Module { } func (p *phony) GenerateAndroidBuildActions(ctx android.ModuleContext) { - p.requiredModuleNames = ctx.RequiredModuleNames() + p.requiredModuleNames = ctx.RequiredModuleNames(ctx) p.hostRequiredModuleNames = ctx.HostRequiredModuleNames() p.targetRequiredModuleNames = ctx.TargetRequiredModuleNames() } diff --git a/rust/bindgen.go b/rust/bindgen.go index 83a6e9590..dbc369762 100644 --- a/rust/bindgen.go +++ b/rust/bindgen.go @@ -29,7 +29,7 @@ var ( defaultBindgenFlags = []string{""} // bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures. - bindgenClangVersion = "clang-r510928" + bindgenClangVersion = "clang-r522817" _ = pctx.VariableFunc("bindgenClangVersion", func(ctx android.PackageVarContext) string { if override := ctx.Config().Getenv("LLVM_BINDGEN_PREBUILTS_VERSION"); override != "" { diff --git a/rust/rust.go b/rust/rust.go index 5790dd6e4..7cd9df4c7 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -345,19 +345,6 @@ func (mod *Module) SubName() string { return mod.Properties.SubName } -func (mod *Module) IsVndk() bool { - // TODO(b/165791368) - return false -} - -func (mod *Module) IsVndkExt() bool { - return false -} - -func (mod *Module) IsVndkSp() bool { - return false -} - func (mod *Module) IsVndkPrebuiltLibrary() bool { // Rust modules do not provide VNDK prebuilts return false @@ -380,10 +367,6 @@ func (c *Module) IsLlndk() bool { return false } -func (c *Module) IsLlndkPublic() bool { - return false -} - func (mod *Module) KernelHeadersDecorator() bool { return false } diff --git a/scripts/Android.bp b/scripts/Android.bp index 80cd93579..91aa19560 100644 --- a/scripts/Android.bp +++ b/scripts/Android.bp @@ -292,6 +292,20 @@ python_binary_host { } python_binary_host { + name: "merge_json", + main: "merge_json.py", + srcs: [ + "merge_json.py", + ], +} + +python_binary_host { + name: "gen_build_prop", + main: "gen_build_prop.py", + srcs: ["gen_build_prop.py"], +} + +python_binary_host { name: "buildinfo", main: "buildinfo.py", srcs: ["buildinfo.py"], diff --git a/scripts/buildinfo.py b/scripts/buildinfo.py index e4fb0da09..3383bf76c 100755 --- a/scripts/buildinfo.py +++ b/scripts/buildinfo.py @@ -18,46 +18,78 @@ import argparse import contextlib +import json +import os import subprocess +TEST_KEY_DIR = "build/make/target/product/security" + +def get_build_variant(product_config): + if product_config["Eng"]: + return "eng" + elif product_config["Debuggable"]: + return "userdebug" + else: + return "user" + +def get_build_flavor(product_config): + build_flavor = product_config["DeviceProduct"] + "-" + get_build_variant(product_config) + if "address" in product_config.get("SanitizeDevice", []) and "_asan" not in build_flavor: + build_flavor += "_asan" + return build_flavor + +def get_build_keys(product_config): + default_cert = product_config.get("DefaultAppCertificate", "") + if default_cert == "" or default_cert == os.path.join(TEST_KEY_DIR, "testKey"): + return "test-keys" + return "dev-keys" + def parse_args(): """Parse commandline arguments.""" parser = argparse.ArgumentParser() - parser.add_argument('--use-vbmeta-digest-in-fingerprint', action='store_true') - parser.add_argument('--build-flavor', required=True) parser.add_argument('--build-hostname-file', required=True, type=argparse.FileType('r')), - parser.add_argument('--build-id', required=True) - parser.add_argument('--build-keys', required=True) parser.add_argument('--build-number-file', required=True, type=argparse.FileType('r')) parser.add_argument('--build-thumbprint-file', type=argparse.FileType('r')) - parser.add_argument('--build-type', required=True) parser.add_argument('--build-username', required=True) - parser.add_argument('--build-variant', required=True) - parser.add_argument('--cpu-abis', action='append', required=True) parser.add_argument('--date-file', required=True, type=argparse.FileType('r')) - parser.add_argument('--default-locale') - parser.add_argument('--default-wifi-channels', action='append', default=[]) - parser.add_argument('--device', required=True) - parser.add_argument("--display-build-number", action='store_true') - parser.add_argument('--platform-base-os', required=True) - parser.add_argument('--platform-display-version', required=True) - parser.add_argument('--platform-min-supported-target-sdk-version', required=True) parser.add_argument('--platform-preview-sdk-fingerprint-file', required=True, type=argparse.FileType('r')) - parser.add_argument('--platform-preview-sdk-version', required=True) - parser.add_argument('--platform-sdk-version', required=True) - parser.add_argument('--platform-security-patch', required=True) - parser.add_argument('--platform-version', required=True) - parser.add_argument('--platform-version-codename',required=True) - parser.add_argument('--platform-version-all-codenames', action='append', required=True) - parser.add_argument('--platform-version-known-codenames', required=True) - parser.add_argument('--platform-version-last-stable', required=True) - parser.add_argument('--product', required=True) - + parser.add_argument('--product-config', required=True, type=argparse.FileType('r')) parser.add_argument('--out', required=True, type=argparse.FileType('w')) - return parser.parse_args() + option = parser.parse_args() + + product_config = json.load(option.product_config) + build_flags = product_config["BuildFlags"] + + option.build_flavor = get_build_flavor(product_config) + option.build_keys = get_build_keys(product_config) + option.build_id = product_config["BuildId"] + option.build_type = product_config["BuildType"] + option.build_variant = get_build_variant(product_config) + option.cpu_abis = product_config["DeviceAbi"] + option.default_locale = None + if len(product_config.get("ProductLocales", [])) > 0: + option.default_locale = product_config["ProductLocales"][0] + option.default_wifi_channels = product_config.get("ProductDefaultWifiChannels", []) + option.device = product_config["DeviceName"] + option.display_build_number = product_config["DisplayBuildNumber"] + option.platform_base_os = product_config["Platform_base_os"] + option.platform_display_version = product_config["Platform_display_version_name"] + option.platform_min_supported_target_sdk_version = build_flags["RELEASE_PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION"] + option.platform_preview_sdk_version = product_config["Platform_preview_sdk_version"] + option.platform_sdk_version = product_config["Platform_sdk_version"] + option.platform_security_patch = product_config["Platform_security_patch"] + option.platform_version = product_config["Platform_version_name"] + option.platform_version_codename = product_config["Platform_sdk_codename"] + option.platform_version_all_codenames = product_config["Platform_version_active_codenames"] + option.platform_version_known_codenames = product_config["Platform_version_known_codenames"] + option.platform_version_last_stable = product_config["Platform_version_last_stable"] + option.product = product_config["DeviceProduct"] + option.use_vbmeta_digest_in_fingerprint = product_config["BoardUseVbmetaDigestInFingerprint"] + + return option def main(): option = parse_args() diff --git a/scripts/gen_build_prop.py b/scripts/gen_build_prop.py new file mode 100644 index 000000000..6c029061d --- /dev/null +++ b/scripts/gen_build_prop.py @@ -0,0 +1,558 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2024 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""A tool for generating {partition}/build.prop""" + +import argparse +import contextlib +import json +import subprocess +import sys + +def get_build_variant(product_config): + if product_config["Eng"]: + return "eng" + elif product_config["Debuggable"]: + return "userdebug" + else: + return "user" + +def get_build_flavor(product_config): + build_flavor = product_config["DeviceProduct"] + "-" + get_build_variant(product_config) + if "address" in product_config.get("SanitizeDevice", []) and "_asan" not in build_flavor: + build_flavor += "_asan" + return build_flavor + +def get_build_keys(product_config): + default_cert = product_config.get("DefaultAppCertificate", "") + if default_cert == "" or default_cert == os.path.join(TEST_KEY_DIR, "testKey"): + return "test-keys" + return "dev-keys" + +def parse_args(): + """Parse commandline arguments.""" + parser = argparse.ArgumentParser() + parser.add_argument("--build-fingerprint-file", required=True, type=argparse.FileType("r")) + parser.add_argument("--build-hostname-file", required=True, type=argparse.FileType("r")) + parser.add_argument("--build-number-file", required=True, type=argparse.FileType("r")) + parser.add_argument("--build-thumbprint-file", type=argparse.FileType("r")) + parser.add_argument("--build-username", required=True) + parser.add_argument("--date-file", required=True, type=argparse.FileType("r")) + parser.add_argument("--platform-preview-sdk-fingerprint-file", required=True, type=argparse.FileType("r")) + parser.add_argument("--prop-files", action="append", type=argparse.FileType("r"), default=[]) + parser.add_argument("--product-config", required=True, type=argparse.FileType("r")) + parser.add_argument("--partition", required=True) + parser.add_argument("--build-broken-dup-sysprop", action="store_true", default=False) + + parser.add_argument("--out", required=True, type=argparse.FileType("w")) + + args = parser.parse_args() + + # post process parse_args requiring manual handling + args.config = json.load(args.product_config) + config = args.config + + config["BuildFlavor"] = get_build_flavor(config) + config["BuildKeys"] = get_build_keys(config) + config["BuildVariant"] = get_build_variant(config) + + config["BuildFingerprint"] = args.build_fingerprint_file.read().strip() + config["BuildHostname"] = args.build_hostname_file.read().strip() + config["BuildNumber"] = args.build_number_file.read().strip() + config["BuildUsername"] = args.build_username + config["BuildVersionTags"] = config["BuildKeys"] + if config["BuildType"] == "debug": + config["BuildVersionTags"] = "debug," + config["BuildVersionTags"] + + raw_date = args.date_file.read().strip() + config["Date"] = subprocess.check_output(["date", "-d", f"@{raw_date}"], text=True).strip() + config["DateUtc"] = subprocess.check_output(["date", "-d", f"@{raw_date}", "+%s"], text=True).strip() + + # build_desc is human readable strings that describe this build. This has the same info as the + # build fingerprint. + # e.g. "aosp_cf_x86_64_phone-userdebug VanillaIceCream MAIN eng.20240319.143939 test-keys" + config["BuildDesc"] = f"{config['DeviceProduct']}-{config['BuildVariant']} " \ + f"{config['Platform_version_name']} {config['BuildId']} " \ + f"{config['BuildNumber']} {config['BuildVersionTags']}" + + config["PlatformPreviewSdkFingerprint"] = args.platform_preview_sdk_fingerprint_file.read().strip() + + if args.build_thumbprint_file: + config["BuildThumbprint"] = args.build_thumbprint_file.read().strip() + + append_additional_system_props(args) + append_additional_vendor_props(args) + append_additional_product_props(args) + + return args + +def generate_common_build_props(args): + print("####################################") + print("# from generate_common_build_props") + print("# These properties identify this partition image.") + print("####################################") + + config = args.config + partition = args.partition + + if partition == "system": + print(f"ro.product.{partition}.brand={config['SystemBrand']}") + print(f"ro.product.{partition}.device={config['SystemDevice']}") + print(f"ro.product.{partition}.manufacturer={config['SystemManufacturer']}") + print(f"ro.product.{partition}.model={config['SystemModel']}") + print(f"ro.product.{partition}.name={config['SystemName']}") + else: + print(f"ro.product.{partition}.brand={config['ProductBrand']}") + print(f"ro.product.{partition}.device={config['DeviceName']}") + print(f"ro.product.{partition}.manufacturer={config['ProductManufacturer']}") + print(f"ro.product.{partition}.model={config['ProductModel']}") + print(f"ro.product.{partition}.name={config['DeviceProduct']}") + + if partition != "system": + if config["ModelForAttestation"]: + print(f"ro.product.model_for_attestation={config['ModelForAttestation']}") + if config["BrandForAttestation"]: + print(f"ro.product.brand_for_attestation={config['BrandForAttestation']}") + if config["NameForAttestation"]: + print(f"ro.product.name_for_attestation={config['NameForAttestation']}") + if config["DeviceForAttestation"]: + print(f"ro.product.device_for_attestation={config['DeviceForAttestation']}") + if config["ManufacturerForAttestation"]: + print(f"ro.product.manufacturer_for_attestation={config['ManufacturerForAttestation']}") + + if config["ZygoteForce64"]: + if partition == "vendor": + print(f"ro.{partition}.product.cpu.abilist={config['DeviceAbiList64']}") + print(f"ro.{partition}.product.cpu.abilist32=") + print(f"ro.{partition}.product.cpu.abilist64={config['DeviceAbiList64']}") + else: + if partition == "system" or partition == "vendor" or partition == "odm": + print(f"ro.{partition}.product.cpu.abilist={config['DeviceAbiList']}") + print(f"ro.{partition}.product.cpu.abilist32={config['DeviceAbiList32']}") + print(f"ro.{partition}.product.cpu.abilist64={config['DeviceAbiList64']}") + + print(f"ro.{partition}.build.date={config['Date']}") + print(f"ro.{partition}.build.date.utc={config['DateUtc']}") + # Allow optional assignments for ARC forward-declarations (b/249168657) + # TODO: Remove any tag-related inconsistencies once the goals from + # go/arc-android-sigprop-changes have been achieved. + print(f"ro.{partition}.build.fingerprint?={config['BuildFingerprint']}") + print(f"ro.{partition}.build.id?={config['BuildId']}") + print(f"ro.{partition}.build.tags?={config['BuildVersionTags']}") + print(f"ro.{partition}.build.type={config['BuildVariant']}") + print(f"ro.{partition}.build.version.incremental={config['BuildNumber']}") + print(f"ro.{partition}.build.version.release={config['Platform_version_last_stable']}") + print(f"ro.{partition}.build.version.release_or_codename={config['Platform_version_name']}") + print(f"ro.{partition}.build.version.sdk={config['Platform_sdk_version']}") + +def generate_build_info(args): + print() + print("####################################") + print("# from gen_build_prop.py:generate_build_info") + print("####################################") + print("# begin build properties") + + config = args.config + build_flags = config["BuildFlags"] + + # The ro.build.id will be set dynamically by init, by appending the unique vbmeta digest. + if config["BoardUseVbmetaDigestInFingerprint"]: + print(f"ro.build.legacy.id={config['BuildId']}") + else: + print(f"ro.build.id?={config['BuildId']}") + + # ro.build.display.id is shown under Settings -> About Phone + if config["BuildVariant"] == "user": + # User builds should show: + # release build number or branch.buld_number non-release builds + + # Dev. branches should have DISPLAY_BUILD_NUMBER set + if config["DisplayBuildNumber"]: + print(f"ro.build.display.id?={config['BuildId']} {config['BuildNumber']} {config['BuildKeys']}") + else: + print(f"ro.build.display.id?={config['BuildId']} {config['BuildKeys']}") + else: + # Non-user builds should show detailed build information (See build desc above) + print(f"ro.build.display.id?={config['BuildDesc']}") + print(f"ro.build.version.incremental={config['BuildNumber']}") + print(f"ro.build.version.sdk={config['Platform_sdk_version']}") + print(f"ro.build.version.preview_sdk={config['Platform_preview_sdk_version']}") + print(f"ro.build.version.preview_sdk_fingerprint={config['PlatformPreviewSdkFingerprint']}") + print(f"ro.build.version.codename={config['Platform_sdk_codename']}") + print(f"ro.build.version.all_codenames={','.join(config['Platform_version_active_codenames'])}") + print(f"ro.build.version.known_codenames={config['Platform_version_known_codenames']}") + print(f"ro.build.version.release={config['Platform_version_last_stable']}") + print(f"ro.build.version.release_or_codename={config['Platform_version_name']}") + print(f"ro.build.version.release_or_preview_display={config['Platform_display_version_name']}") + print(f"ro.build.version.security_patch={config['Platform_security_patch']}") + print(f"ro.build.version.base_os={config['Platform_base_os']}") + print(f"ro.build.version.min_supported_target_sdk={build_flags['RELEASE_PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION']}") + print(f"ro.build.date={config['Date']}") + print(f"ro.build.date.utc={config['DateUtc']}") + print(f"ro.build.type={config['BuildVariant']}") + print(f"ro.build.user={config['BuildUsername']}") + print(f"ro.build.host={config['BuildHostname']}") + # TODO: Remove any tag-related optional property declarations once the goals + # from go/arc-android-sigprop-changes have been achieved. + print(f"ro.build.tags?={config['BuildVersionTags']}") + # ro.build.flavor are used only by the test harness to distinguish builds. + # Only add _asan for a sanitized build if it isn't already a part of the + # flavor (via a dedicated lunch config for example). + print(f"ro.build.flavor={config['BuildFlavor']}") + + # These values are deprecated, use "ro.product.cpu.abilist" + # instead (see below). + print(f"# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete,") + print(f"# use ro.product.cpu.abilist instead.") + print(f"ro.product.cpu.abi={config['DeviceAbi'][0]}") + if len(config["DeviceAbi"]) > 1: + print(f"ro.product.cpu.abi2={config['DeviceAbi'][1]}") + + if config["ProductLocales"]: + print(f"ro.product.locale={config['ProductLocales'][0]}") + print(f"ro.wifi.channels={' '.join(config['ProductDefaultWifiChannels'])}") + + print(f"# ro.build.product is obsolete; use ro.product.device") + print(f"ro.build.product={config['DeviceName']}") + + print(f"# Do not try to parse description or thumbprint") + print(f"ro.build.description?={config['BuildDesc']}") + if "build_thumbprint" in config: + print(f"ro.build.thumbprint={config['BuildThumbprint']}") + + print(f"# end build properties") + +def write_properties_from_file(file): + print() + print("####################################") + print(f"# from {file.name}") + print("####################################") + print(file.read(), end="") + +def write_properties_from_variable(name, props, build_broken_dup_sysprop): + print() + print("####################################") + print(f"# from variable {name}") + print("####################################") + + # Implement the legacy behavior when BUILD_BROKEN_DUP_SYSPROP is on. + # Optional assignments are all converted to normal assignments and + # when their duplicates the first one wins. + if build_broken_dup_sysprop: + processed_props = [] + seen_props = set() + for line in props: + line = line.replace("?=", "=") + key, value = line.split("=", 1) + if key in seen_props: + continue + seen_props.add(key) + processed_props.append(line) + props = processed_props + + for line in props: + print(line) + +def append_additional_system_props(args): + props = [] + + config = args.config + + # Add the product-defined properties to the build properties. + if config["PropertySplitEnabled"] or config["VendorImageFileSystemType"]: + if "PRODUCT_PROPERTY_OVERRIDES" in config: + props += config["PRODUCT_PROPERTY_OVERRIDES"] + + props.append(f"ro.treble.enabled={'true' if config['FullTreble'] else 'false'}") + # Set ro.llndk.api_level to show the maximum vendor API level that the LLNDK + # in the system partition supports. + if config["VendorApiLevel"]: + props.append(f"ro.llndk.api_level={config['VendorApiLevel']}") + + # Sets ro.actionable_compatible_property.enabled to know on runtime whether + # the allowed list of actionable compatible properties is enabled or not. + props.append("ro.actionable_compatible_property.enabled=true") + + # Enable core platform API violation warnings on userdebug and eng builds. + if config["BuildVariant"] != "user": + props.append("persist.debug.dalvik.vm.core_platform_api_policy=just-warn") + + # Define ro.sanitize.<name> properties for all global sanitizers. + for sanitize_target in config["SanitizeDevice"]: + props.append(f"ro.sanitize.{sanitize_target}=true") + + # Sets the default value of ro.postinstall.fstab.prefix to /system. + # Device board config should override the value to /product when needed by: + # + # PRODUCT_PRODUCT_PROPERTIES += ro.postinstall.fstab.prefix=/product + # + # It then uses ${ro.postinstall.fstab.prefix}/etc/fstab.postinstall to + # mount system_other partition. + props.append("ro.postinstall.fstab.prefix=/system") + + enable_target_debugging = True + if config["BuildVariant"] == "user" or config["BuildVariant"] == "userdebug": + # Target is secure in user builds. + props.append("ro.secure=1") + props.append("security.perf_harden=1") + + if config["BuildVariant"] == "user": + # Disable debugging in plain user builds. + props.append("ro.adb.secure=1") + enable_target_debugging = False + + # Disallow mock locations by default for user builds + props.append("ro.allow.mock.location=0") + else: + # Turn on checkjni for non-user builds. + props.append("ro.kernel.android.checkjni=1") + # Set device insecure for non-user builds. + props.append("ro.secure=0") + # Allow mock locations by default for non user builds + props.append("ro.allow.mock.location=1") + + if enable_target_debugging: + # Enable Dalvik lock contention logging. + props.append("dalvik.vm.lockprof.threshold=500") + + # Target is more debuggable and adbd is on by default + props.append("ro.debuggable=1") + else: + # Target is less debuggable and adbd is off by default + props.append("ro.debuggable=0") + + if config["BuildVariant"] == "eng": + if "ro.setupwizard.mode=ENABLED" in props: + # Don't require the setup wizard on eng builds + props = list(filter(lambda x: not x.startswith("ro.setupwizard.mode="), props)) + props.append("ro.setupwizard.mode=OPTIONAL") + + if not config["SdkBuild"]: + # To speedup startup of non-preopted builds, don't verify or compile the boot image. + props.append("dalvik.vm.image-dex2oat-filter=extract") + # b/323566535 + props.append("init.svc_debug.no_fatal.zygote=true") + + if config["SdkBuild"]: + props.append("xmpp.auto-presence=true") + props.append("ro.config.nocheckin=yes") + + props.append("net.bt.name=Android") + + # This property is set by flashing debug boot image, so default to false. + props.append("ro.force.debuggable=0") + + config["ADDITIONAL_SYSTEM_PROPERTIES"] = props + +def append_additional_vendor_props(args): + props = [] + + config = args.config + build_flags = config["BuildFlags"] + + # Add cpu properties for bionic and ART. + props.append(f"ro.bionic.arch={config['DeviceArch']}") + props.append(f"ro.bionic.cpu_variant={config['DeviceCpuVariantRuntime']}") + props.append(f"ro.bionic.2nd_arch={config['DeviceSecondaryArch']}") + props.append(f"ro.bionic.2nd_cpu_variant={config['DeviceSecondaryCpuVariantRuntime']}") + + props.append(f"persist.sys.dalvik.vm.lib.2=libart.so") + props.append(f"dalvik.vm.isa.{config['DeviceArch']}.variant={config['Dex2oatTargetCpuVariantRuntime']}") + if config["Dex2oatTargetInstructionSetFeatures"]: + props.append(f"dalvik.vm.isa.{config['DeviceArch']}.features={config['Dex2oatTargetInstructionSetFeatures']}") + + if config["DeviceSecondaryArch"]: + props.append(f"dalvik.vm.isa.{config['DeviceSecondaryArch']}.variant={config['SecondaryDex2oatCpuVariantRuntime']}") + if config["SecondaryDex2oatInstructionSetFeatures"]: + props.append(f"dalvik.vm.isa.{config['DeviceSecondaryArch']}.features={config['SecondaryDex2oatInstructionSetFeatures']}") + + # Although these variables are prefixed with TARGET_RECOVERY_, they are also needed under charger + # mode (via libminui). + if config["RecoveryDefaultRotation"]: + props.append(f"ro.minui.default_rotation={config['RecoveryDefaultRotation']}") + + if config["RecoveryOverscanPercent"]: + props.append(f"ro.minui.overscan_percent={config['RecoveryOverscanPercent']}") + + if config["RecoveryPixelFormat"]: + props.append(f"ro.minui.pixel_format={config['RecoveryPixelFormat']}") + + if "UseDynamicPartitions" in config: + props.append(f"ro.boot.dynamic_partitions={'true' if config['UseDynamicPartitions'] else 'false'}") + + if "RetrofitDynamicPartitions" in config: + props.append(f"ro.boot.dynamic_partitions_retrofit={'true' if config['RetrofitDynamicPartitions'] else 'false'}") + + if config["ShippingApiLevel"]: + props.append(f"ro.product.first_api_level={config['ShippingApiLevel']}") + + if config["ShippingVendorApiLevel"]: + props.append(f"ro.vendor.api_level={config['ShippingVendorApiLevel']}") + + if config["BuildVariant"] != "user" and config["BuildDebugfsRestrictionsEnabled"]: + props.append(f"ro.product.debugfs_restrictions.enabled=true") + + # Vendors with GRF must define BOARD_SHIPPING_API_LEVEL for the vendor API level. + # This must not be defined for the non-GRF devices. + # The values of the GRF properties will be verified by post_process_props.py + if config["BoardShippingApiLevel"]: + props.append(f"ro.board.first_api_level={config['ProductShippingApiLevel']}") + + # Build system set BOARD_API_LEVEL to show the api level of the vendor API surface. + # This must not be altered outside of build system. + if config["VendorApiLevel"]: + props.append(f"ro.board.api_level={config['VendorApiLevel']}") + + # RELEASE_BOARD_API_LEVEL_FROZEN is true when the vendor API surface is frozen. + if build_flags["RELEASE_BOARD_API_LEVEL_FROZEN"]: + props.append(f"ro.board.api_frozen=true") + + # Set build prop. This prop is read by ota_from_target_files when generating OTA, + # to decide if VABC should be disabled. + if config["DontUseVabcOta"]: + props.append(f"ro.vendor.build.dont_use_vabc=true") + + # Set the flag in vendor. So VTS would know if the new fingerprint format is in use when + # the system images are replaced by GSI. + if config["BoardUseVbmetaDigestInFingerprint"]: + props.append(f"ro.vendor.build.fingerprint_has_digest=1") + + props.append(f"ro.vendor.build.security_patch={config['VendorSecurityPatch']}") + props.append(f"ro.product.board={config['BootloaderBoardName']}") + props.append(f"ro.board.platform={config['BoardPlatform']}") + props.append(f"ro.hwui.use_vulkan={'true' if config['UsesVulkan'] else 'false'}") + + if config["ScreenDensity"]: + props.append(f"ro.sf.lcd_density={config['ScreenDensity']}") + + if "AbOtaUpdater" in config: + props.append(f"ro.build.ab_update={'true' if config['AbOtaUpdater'] else 'false'}") + if config["AbOtaUpdater"]: + props.append(f"ro.vendor.build.ab_ota_partitions={config['AbOtaPartitions']}") + + config["ADDITIONAL_VENDOR_PROPERTIES"] = props + +def append_additional_product_props(args): + props = [] + + config = args.config + + # Add the system server compiler filter if they are specified for the product. + if config["SystemServerCompilerFilter"]: + props.append(f"dalvik.vm.systemservercompilerfilter={config['SystemServerCompilerFilter']}") + + # Add the 16K developer args if it is defined for the product. + props.append(f"ro.product.build.16k_page.enabled={'true' if config['Product16KDeveloperOption'] else 'false'}") + + props.append(f"ro.build.characteristics={config['AAPTCharacteristics']}") + + if "AbOtaUpdater" in config and config["AbOtaUpdater"]: + props.append(f"ro.product.ab_ota_partitions={config['AbOtaPartitions']}") + + # Set this property for VTS to skip large page size tests on unsupported devices. + props.append(f"ro.product.cpu.pagesize.max={config['DeviceMaxPageSizeSupported']}") + + if config["NoBionicPageSizeMacro"]: + props.append(f"ro.product.build.no_bionic_page_size_macro=true") + + # If the value is "default", it will be mangled by post_process_props.py. + props.append(f"ro.dalvik.vm.enable_uffd_gc={config['EnableUffdGc']}") + + config["ADDITIONAL_PRODUCT_PROPERTIES"] = props + +def build_system_prop(args): + config = args.config + + # Order matters here. When there are duplicates, the last one wins. + # TODO(b/117892318): don't allow duplicates so that the ordering doesn't matter + variables = [ + "ADDITIONAL_SYSTEM_PROPERTIES", + "PRODUCT_SYSTEM_PROPERTIES", + # TODO(b/117892318): deprecate this + "PRODUCT_SYSTEM_DEFAULT_PROPERTIES", + ] + + if not config["PropertySplitEnabled"]: + variables += [ + "ADDITIONAL_VENDOR_PROPERTIES", + "PRODUCT_VENDOR_PROPERTIES", + ] + + build_prop(args, gen_build_info=True, gen_common_build_props=True, variables=variables) + +''' +def build_vendor_prop(args): + config = args.config + + # Order matters here. When there are duplicates, the last one wins. + # TODO(b/117892318): don't allow duplicates so that the ordering doesn't matter + variables = [] + if config["PropertySplitEnabled"]: + variables += [ + "ADDITIONAL_VENDOR_PROPERTIES", + "PRODUCT_VENDOR_PROPERTIES", + # TODO(b/117892318): deprecate this + "PRODUCT_DEFAULT_PROPERTY_OVERRIDES", + "PRODUCT_PROPERTY_OVERRIDES", + ] + + build_prop(args, gen_build_info=False, gen_common_build_props=True, variables=variables) + +def build_product_prop(args): + config = args.config + + # Order matters here. When there are duplicates, the last one wins. + # TODO(b/117892318): don't allow duplicates so that the ordering doesn't matter + variables = [ + "ADDITIONAL_PRODUCT_PROPERTIES", + "PRODUCT_PRODUCT_PROPERTIES", + ] + build_prop(args, gen_build_info=False, gen_common_build_props=True, variables=variables) +''' + +def build_prop(args, gen_build_info, gen_common_build_props, variables): + config = args.config + + if gen_common_build_props: + generate_common_build_props(args) + + if gen_build_info: + generate_build_info(args) + + for prop_file in args.prop_files: + write_properties_from_file(prop_file) + + for variable in variables: + if variable in config: + write_properties_from_variable(variable, config[variable], args.build_broken_dup_sysprop) + +def main(): + args = parse_args() + + with contextlib.redirect_stdout(args.out): + if args.partition == "system": + build_system_prop(args) + ''' + elif args.partition == "vendor": + build_vendor_prop(args) + elif args.partition == "product": + build_product_prop(args) + ''' + else: + sys.exit(f"not supported partition {args.partition}") + +if __name__ == "__main__": + main() diff --git a/scripts/merge_json.py b/scripts/merge_json.py new file mode 100644 index 000000000..7e2f6eb51 --- /dev/null +++ b/scripts/merge_json.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +# +# Copyright 2024 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +"""A tool for merging two or more JSON files.""" + +import argparse +import logging +import json +import sys + +def parse_args(): + """Parse commandline arguments.""" + + parser = argparse.ArgumentParser() + parser.add_argument("output", help="output JSON file", type=argparse.FileType("w")) + parser.add_argument("input", help="input JSON files", nargs="+", type=argparse.FileType("r")) + return parser.parse_args() + +def main(): + """Program entry point.""" + args = parse_args() + merged_dict = {} + has_error = False + logger = logging.getLogger(__name__) + + for json_file in args.input: + try: + data = json.load(json_file) + except json.JSONDecodeError as e: + logger.error(f"Error parsing JSON in file: {json_file.name}. Reason: {e}") + has_error = True + continue + + for key, value in data.items(): + if key not in merged_dict: + merged_dict[key] = value + elif merged_dict[key] == value: + logger.warning(f"Duplicate key '{key}' with identical values found.") + else: + logger.error(f"Conflicting values for key '{key}': {merged_dict[key]} != {value}") + has_error = True + + if has_error: + sys.exit(1) + + json.dump(merged_dict, args.output) + +if __name__ == "__main__": + main() diff --git a/snapshot/host_fake_snapshot.go b/snapshot/host_fake_snapshot.go index b416ebdd4..278247e10 100644 --- a/snapshot/host_fake_snapshot.go +++ b/snapshot/host_fake_snapshot.go @@ -129,12 +129,12 @@ func (c *hostFakeSingleton) GenerateBuildActions(ctx android.SingletonContext) { if !seen[outFile] { seen[outFile] = true outputs = append(outputs, WriteStringToFileRule(ctx, "", outFile)) - jsonData = append(jsonData, hostSnapshotFakeJsonFlags{*hostJsonDesc(module), false}) + jsonData = append(jsonData, hostSnapshotFakeJsonFlags{*hostJsonDesc(ctx, module), false}) } } }) // Update any module prebuilt information - for idx, _ := range jsonData { + for idx := range jsonData { if _, ok := prebuilts[jsonData[idx].ModuleName]; ok { // Prebuilt exists for this module jsonData[idx].Prebuilt = true diff --git a/snapshot/host_snapshot.go b/snapshot/host_snapshot.go index edcc16348..1ecab7ddc 100644 --- a/snapshot/host_snapshot.go +++ b/snapshot/host_snapshot.go @@ -101,7 +101,7 @@ func (f *hostSnapshot) CreateMetaData(ctx android.ModuleContext, fileName string // Create JSON file based on the direct dependencies ctx.VisitDirectDeps(func(dep android.Module) { - desc := hostJsonDesc(dep) + desc := hostJsonDesc(ctx, dep) if desc != nil { jsonData = append(jsonData, *desc) } @@ -209,7 +209,7 @@ func hostRelativePathString(m android.Module) string { // Create JSON description for given module, only create descriptions for binary modules // and rust_proc_macro modules which provide a valid HostToolPath -func hostJsonDesc(m android.Module) *SnapshotJsonFlags { +func hostJsonDesc(ctx android.ConfigAndErrorContext, m android.Module) *SnapshotJsonFlags { path := hostToolPath(m) relPath := hostRelativePathString(m) procMacro := false @@ -226,7 +226,7 @@ func hostJsonDesc(m android.Module) *SnapshotJsonFlags { props := &SnapshotJsonFlags{ ModuleStemName: moduleStem, Filename: path.String(), - Required: append(m.HostRequiredModuleNames(), m.RequiredModuleNames()...), + Required: append(m.HostRequiredModuleNames(), m.RequiredModuleNames(ctx)...), RelativeInstallPath: relPath, RustProcMacro: procMacro, CrateName: crateName, diff --git a/ui/build/config.go b/ui/build/config.go index feded1c85..8dddea584 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -85,6 +85,7 @@ type configImpl struct { skipMetricsUpload bool buildStartedTime int64 // For metrics-upload-only - manually specify a build-started time buildFromSourceStub bool + incrementalBuildActions bool ensureAllowlistIntegrity bool // For CI builds - make sure modules are mixed-built // From the product config @@ -811,6 +812,8 @@ func (c *configImpl) parseArgs(ctx Context, args []string) { } } else if arg == "--build-from-source-stub" { c.buildFromSourceStub = true + } else if arg == "--incremental-build-actions" { + c.incrementalBuildActions = true } else if strings.HasPrefix(arg, "--build-command=") { buildCmd := strings.TrimPrefix(arg, "--build-command=") // remove quotations @@ -1488,6 +1491,15 @@ func (c *configImpl) SoongVarsFile() string { } } +func (c *configImpl) SoongExtraVarsFile() string { + targetProduct, err := c.TargetProductOrErr() + if err != nil { + return filepath.Join(c.SoongOutDir(), "soong.extra.variables") + } else { + return filepath.Join(c.SoongOutDir(), "soong."+targetProduct+".extra.variables") + } +} + func (c *configImpl) SoongNinjaFile() string { targetProduct, err := c.TargetProductOrErr() if err != nil { diff --git a/ui/build/soong.go b/ui/build/soong.go index 2f3150d03..9a4583cdd 100644 --- a/ui/build/soong.go +++ b/ui/build/soong.go @@ -315,6 +315,9 @@ func bootstrapBlueprint(ctx Context, config Config) { if config.ensureAllowlistIntegrity { mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--ensure-allowlist-integrity") } + if config.incrementalBuildActions { + mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--incremental-build-actions") + } queryviewDir := filepath.Join(config.SoongOutDir(), "queryview") @@ -694,6 +697,7 @@ func runSoong(ctx Context, config Config) { } } distFile(ctx, config, config.SoongVarsFile(), "soong") + distFile(ctx, config, config.SoongExtraVarsFile(), "soong") if !config.SkipKati() { distGzipFile(ctx, config, config.SoongAndroidMk(), "soong") diff --git a/ui/build/test_build.go b/ui/build/test_build.go index 24ad08284..687ad6f61 100644 --- a/ui/build/test_build.go +++ b/ui/build/test_build.go @@ -64,7 +64,8 @@ func testForDanglingRules(ctx Context, config Config) { outDir := config.OutDir() modulePathsDir := filepath.Join(outDir, ".module_paths") rawFilesDir := filepath.Join(outDir, "soong", "raw") - variablesFilePath := filepath.Join(outDir, "soong", "soong.variables") + variablesFilePath := config.SoongVarsFile() + extraVariablesFilePath := config.SoongExtraVarsFile() // dexpreopt.config is an input to the soong_docs action, which runs the // soong_build primary builder. However, this file is created from $(shell) @@ -95,6 +96,7 @@ func testForDanglingRules(ctx Context, config Config) { if strings.HasPrefix(line, modulePathsDir) || strings.HasPrefix(line, rawFilesDir) || line == variablesFilePath || + line == extraVariablesFilePath || line == dexpreoptConfigFilePath || line == buildDatetimeFilePath || line == bpglob || |