diff options
49 files changed, 1348 insertions, 630 deletions
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index 317f5c434..e8cad7d7b 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -4,3 +4,4 @@ bpfmt = true [Hook Scripts] do_not_use_DO_NOT_MERGE = ${REPO_ROOT}/build/soong/scripts/check_do_not_merge.sh ${PREUPLOAD_COMMIT} +aosp_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "." diff --git a/aconfig/codegen/cc_aconfig_library.go b/aconfig/codegen/cc_aconfig_library.go index d5291fce9..ec0a6b6cd 100644 --- a/aconfig/codegen/cc_aconfig_library.go +++ b/aconfig/codegen/cc_aconfig_library.go @@ -22,6 +22,7 @@ import ( "github.com/google/blueprint/proptools" "fmt" + "strconv" "strings" ) @@ -87,11 +88,13 @@ func (this *CcAconfigLibraryCallbacks) GeneratorDeps(ctx cc.DepsContext, deps cc if mode != "force-read-only" { deps.SharedLibs = append(deps.SharedLibs, baseLibDep) - deps.SharedLibs = append(deps.SharedLibs, libAconfigStorageReadApiCcDep) - deps.SharedLibs = append(deps.SharedLibs, libLogDep) - - deps.StaticLibs = append(deps.StaticLibs, libBaseDep) } + + // TODO: after storage migration is over, don't add these in force-read-only-mode. + deps.SharedLibs = append(deps.SharedLibs, libAconfigStorageReadApiCcDep) + deps.SharedLibs = append(deps.SharedLibs, libBaseDep) + deps.SharedLibs = append(deps.SharedLibs, libLogDep) + // TODO: It'd be really nice if we could reexport this library and not make everyone do it. return deps @@ -153,6 +156,7 @@ func (this *CcAconfigLibraryCallbacks) GeneratorBuildActions(ctx cc.ModuleContex Args: map[string]string{ "gendir": this.generatedDir.String(), "mode": mode, + "debug": strconv.FormatBool(ctx.Config().ReleaseReadFromNewStorageCc()), }, }) diff --git a/aconfig/codegen/cc_aconfig_library_test.go b/aconfig/codegen/cc_aconfig_library_test.go index 2e7fdc2c1..cf9ffbd33 100644 --- a/aconfig/codegen/cc_aconfig_library_test.go +++ b/aconfig/codegen/cc_aconfig_library_test.go @@ -249,6 +249,22 @@ func TestForceReadOnly(t *testing.T) { aconfig_declarations: "my_aconfig_declarations", mode: "force-read-only", } + + + cc_library { + name: "libbase", + srcs: ["libbase.cc"], + } + + cc_library { + name: "liblog", + srcs: ["liblog.cc"], + } + + cc_library { + name: "libaconfig_storage_read_api_cc", + srcs: ["libaconfig_storage_read_api_cc.cc"], + } `)) module := result.ModuleForTests("my_cc_aconfig_library", "android_arm64_armv8-a_shared").Module() diff --git a/aconfig/codegen/init.go b/aconfig/codegen/init.go index 73a89514d..6182e14d4 100644 --- a/aconfig/codegen/init.go +++ b/aconfig/codegen/init.go @@ -49,11 +49,12 @@ var ( ` && ${aconfig} create-cpp-lib` + ` --mode ${mode}` + ` --cache ${in}` + - ` --out ${gendir}`, + ` --out ${gendir}` + + ` --allow-instrumentation ${debug}`, CommandDeps: []string{ "$aconfig", }, - }, "gendir", "mode") + }, "gendir", "mode", "debug") // For rust_aconfig_library: Generate Rust library rustRule = pctx.AndroidStaticRule("rust_aconfig_library", diff --git a/android/apex_contributions.go b/android/apex_contributions.go index dd09fbf44..f5c50d386 100644 --- a/android/apex_contributions.go +++ b/android/apex_contributions.go @@ -15,8 +15,6 @@ package android import ( - "strings" - "github.com/google/blueprint" "github.com/google/blueprint/proptools" ) @@ -115,15 +113,6 @@ func (a *allApexContributions) DepsMutator(ctx BottomUpMutatorContext) { func (a *allApexContributions) SetPrebuiltSelectionInfoProvider(ctx BaseModuleContext) { addContentsToProvider := func(p *PrebuiltSelectionInfoMap, m *apexContributions) { for _, content := range m.Contents() { - // Coverage builds for TARGET_RELEASE=foo should always build from source, - // even if TARGET_RELEASE=foo uses prebuilt mainline modules. - // This is necessary because the checked-in prebuilts were generated with - // instrumentation turned off. - // - // Skip any prebuilt contents in coverage builds - if strings.HasPrefix(content, "prebuilt_") && (ctx.Config().JavaCoverageEnabled() || ctx.DeviceConfig().NativeCoverageEnabled()) { - continue - } if !ctx.OtherModuleExists(content) && !ctx.Config().AllowMissingDependencies() { ctx.ModuleErrorf("%s listed in apex_contributions %s does not exist\n", content, m.Name()) } diff --git a/android/config.go b/android/config.go index 75d135fc0..f6711e61f 100644 --- a/android/config.go +++ b/android/config.go @@ -229,6 +229,11 @@ func (c Config) ReleaseNdkAbiMonitored() bool { return c.config.productVariables.GetBuildFlagBool("RELEASE_NDK_ABI_MONITORED") } +// Enable read flag from new storage, for C/C++ +func (c Config) ReleaseReadFromNewStorageCc() bool { + return c.config.productVariables.GetBuildFlagBool("RELEASE_READ_FROM_NEW_STORAGE_CC") +} + func (c Config) ReleaseHiddenApiExportableStubs() bool { return c.config.productVariables.GetBuildFlagBool("RELEASE_HIDDEN_API_EXPORTABLE_STUBS") || Bool(c.config.productVariables.HiddenapiExportableStubs) @@ -813,12 +818,12 @@ func (c *config) GetenvWithDefault(key string, defaultValue string) string { } func (c *config) IsEnvTrue(key string) bool { - value := c.Getenv(key) + value := strings.ToLower(c.Getenv(key)) return value == "1" || value == "y" || value == "yes" || value == "on" || value == "true" } func (c *config) IsEnvFalse(key string) bool { - value := c.Getenv(key) + value := strings.ToLower(c.Getenv(key)) return value == "0" || value == "n" || value == "no" || value == "off" || value == "false" } @@ -2099,6 +2104,7 @@ var ( "RELEASE_APEX_CONTRIBUTIONS_IPSEC", "RELEASE_APEX_CONTRIBUTIONS_MEDIA", "RELEASE_APEX_CONTRIBUTIONS_MEDIAPROVIDER", + "RELEASE_APEX_CONTRIBUTIONS_MODULE_METADATA", "RELEASE_APEX_CONTRIBUTIONS_NETWORKSTACKGOOGLE", "RELEASE_APEX_CONTRIBUTIONS_NEURALNETWORKS", "RELEASE_APEX_CONTRIBUTIONS_ONDEVICEPERSONALIZATION", diff --git a/android/module.go b/android/module.go index 5fe379c8a..effca0346 100644 --- a/android/module.go +++ b/android/module.go @@ -2142,13 +2142,13 @@ func (e configurationEvalutor) PropertyErrorf(property string, fmt string, args func (e configurationEvalutor) EvaluateConfiguration(condition proptools.ConfigurableCondition, property string) proptools.ConfigurableValue { ctx := e.ctx m := e.m - switch condition.FunctionName { + switch condition.FunctionName() { case "release_variable": - if len(condition.Args) != 1 { - ctx.OtherModulePropertyErrorf(m, property, "release_variable requires 1 argument, found %d", len(condition.Args)) + if condition.NumArgs() != 1 { + ctx.OtherModulePropertyErrorf(m, property, "release_variable requires 1 argument, found %d", condition.NumArgs()) return proptools.ConfigurableValueUndefined() } - if v, ok := ctx.Config().productVariables.BuildFlags[condition.Args[0]]; ok { + if v, ok := ctx.Config().productVariables.BuildFlags[condition.Arg(0)]; ok { return proptools.ConfigurableValueString(v) } return proptools.ConfigurableValueUndefined() @@ -2157,12 +2157,12 @@ func (e configurationEvalutor) EvaluateConfiguration(condition proptools.Configu ctx.OtherModulePropertyErrorf(m, property, "TODO(b/323382414): Product variables are not yet supported in selects") return proptools.ConfigurableValueUndefined() case "soong_config_variable": - if len(condition.Args) != 2 { - ctx.OtherModulePropertyErrorf(m, property, "soong_config_variable requires 2 arguments, found %d", len(condition.Args)) + if condition.NumArgs() != 2 { + ctx.OtherModulePropertyErrorf(m, property, "soong_config_variable requires 2 arguments, found %d", condition.NumArgs()) return proptools.ConfigurableValueUndefined() } - namespace := condition.Args[0] - variable := condition.Args[1] + namespace := condition.Arg(0) + variable := condition.Arg(1) if n, ok := ctx.Config().productVariables.VendorVars[namespace]; ok { if v, ok := n[variable]; ok { return proptools.ConfigurableValueString(v) @@ -2170,8 +2170,8 @@ func (e configurationEvalutor) EvaluateConfiguration(condition proptools.Configu } return proptools.ConfigurableValueUndefined() case "arch": - if len(condition.Args) != 0 { - ctx.OtherModulePropertyErrorf(m, property, "arch requires no arguments, found %d", len(condition.Args)) + if condition.NumArgs() != 0 { + ctx.OtherModulePropertyErrorf(m, property, "arch requires no arguments, found %d", condition.NumArgs()) return proptools.ConfigurableValueUndefined() } if !m.base().ArchReady() { @@ -2180,8 +2180,8 @@ func (e configurationEvalutor) EvaluateConfiguration(condition proptools.Configu } return proptools.ConfigurableValueString(m.base().Arch().ArchType.Name) case "os": - if len(condition.Args) != 0 { - ctx.OtherModulePropertyErrorf(m, property, "os requires no arguments, found %d", len(condition.Args)) + if condition.NumArgs() != 0 { + ctx.OtherModulePropertyErrorf(m, property, "os requires no arguments, found %d", condition.NumArgs()) return proptools.ConfigurableValueUndefined() } // the arch mutator runs after the os mutator, we can just use this to enforce that os is ready. @@ -2194,8 +2194,8 @@ func (e configurationEvalutor) EvaluateConfiguration(condition proptools.Configu // We currently don't have any other boolean variables (we should add support for typing // the soong config variables), so add this fake one for testing the boolean select // functionality. - if len(condition.Args) != 0 { - ctx.OtherModulePropertyErrorf(m, property, "boolean_var_for_testing requires 0 arguments, found %d", len(condition.Args)) + if condition.NumArgs() != 0 { + ctx.OtherModulePropertyErrorf(m, property, "boolean_var_for_testing requires 0 arguments, found %d", condition.NumArgs()) return proptools.ConfigurableValueUndefined() } diff --git a/android/module_context.go b/android/module_context.go index d3e2770cb..dea22bab4 100644 --- a/android/module_context.go +++ b/android/module_context.go @@ -476,6 +476,7 @@ func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, e executable: executable, effectiveLicenseFiles: &licenseFiles, partition: fullInstallPath.partition, + skipInstall: m.skipInstall(), } m.packagingSpecs = append(m.packagingSpecs, spec) return spec @@ -599,6 +600,7 @@ func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, src symlinkTarget: relPath, executable: false, partition: fullInstallPath.partition, + skipInstall: m.skipInstall(), }) return fullInstallPath @@ -640,6 +642,7 @@ func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name str symlinkTarget: absPath, executable: false, partition: fullInstallPath.partition, + skipInstall: m.skipInstall(), }) return fullInstallPath diff --git a/android/mutator.go b/android/mutator.go index 75ba65048..9cfdb60dc 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -293,15 +293,14 @@ type BottomUpMutatorContext interface { // WalkDeps, etc. AddInterVariantDependency(tag blueprint.DependencyTag, from, to blueprint.Module) - // ReplaceDependencies replaces all dependencies on the identical variant of the module with the - // specified name with the current variant of this module. Replacements don't take effect until - // after the mutator pass is finished. + // ReplaceDependencies finds all the variants of the module with the specified name, then + // replaces all dependencies onto those variants with the current variant of this module. + // Replacements don't take effect until after the mutator pass is finished. ReplaceDependencies(string) - // ReplaceDependencies replaces all dependencies on the identical variant of the module with the - // specified name with the current variant of this module as long as the supplied predicate returns - // true. - // + // ReplaceDependenciesIf finds all the variants of the module with the specified name, then + // replaces all dependencies onto those variants with the current variant of this module + // as long as the supplied predicate returns true. // Replacements don't take effect until after the mutator pass is finished. ReplaceDependenciesIf(string, blueprint.ReplaceDependencyPredicate) @@ -595,11 +594,16 @@ func (a *androidTransitionMutator) IncomingTransition(bpctx blueprint.IncomingTr func (a *androidTransitionMutator) Mutate(ctx blueprint.BottomUpMutatorContext, variation string) { if am, ok := ctx.Module().(Module); ok { + if variation != "" { + // TODO: this should really be checking whether the TransitionMutator affected this module, not + // the empty variant, but TransitionMutator has no concept of skipping a module. + base := am.base() + base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, a.name) + base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variation) + } + mctx := bottomUpMutatorContextFactory(ctx, am, a.finalPhase) defer bottomUpMutatorContextPool.Put(mctx) - base := am.base() - base.commonProperties.DebugMutators = append(base.commonProperties.DebugMutators, a.name) - base.commonProperties.DebugVariations = append(base.commonProperties.DebugVariations, variation) a.mutator.Mutate(mctx, variation) } } diff --git a/android/packaging.go b/android/packaging.go index a8fb28d30..66772183c 100644 --- a/android/packaging.go +++ b/android/packaging.go @@ -43,6 +43,11 @@ type PackagingSpec struct { effectiveLicenseFiles *Paths partition string + + // Whether this packaging spec represents an installation of the srcPath (i.e. this struct + // is created via InstallFile or InstallSymlink) or a simple packaging (i.e. created via + // PackageFile). + skipInstall bool } // Get file name of installed package @@ -74,6 +79,10 @@ func (p *PackagingSpec) Partition() string { return p.partition } +func (p *PackagingSpec) SkipInstall() bool { + return p.skipInstall +} + type PackageModule interface { Module packagingBase() *PackagingBase diff --git a/android/paths.go b/android/paths.go index 2b33f67ce..39b660cce 100644 --- a/android/paths.go +++ b/android/paths.go @@ -277,6 +277,7 @@ type WritablePath interface { type genPathProvider interface { genPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleGenPath + genPathWithExtAndTrimExt(ctx ModuleOutPathContext, subdir, ext string, trimExt string) ModuleGenPath } type objPathProvider interface { objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath @@ -295,6 +296,16 @@ func GenPathWithExt(ctx ModuleOutPathContext, subdir string, p Path, ext string) return PathForModuleGen(ctx) } +// GenPathWithExtAndTrimExt derives a new file path in ctx's generated sources directory +// from the current path, but with the new extension and trim the suffix. +func GenPathWithExtAndTrimExt(ctx ModuleOutPathContext, subdir string, p Path, ext string, trimExt string) ModuleGenPath { + if path, ok := p.(genPathProvider); ok { + return path.genPathWithExtAndTrimExt(ctx, subdir, ext, trimExt) + } + ReportPathErrorf(ctx, "Tried to create generated file from unsupported path: %s(%s)", reflect.TypeOf(p).Name(), p) + return PathForModuleGen(ctx) +} + // ObjPathWithExt derives a new file path in ctx's object directory from the // current path, but with the new extension. func ObjPathWithExt(ctx ModuleOutPathContext, subdir string, p Path, ext string) ModuleObjPath { @@ -1507,6 +1518,17 @@ func (p SourcePath) genPathWithExt(ctx ModuleOutPathContext, subdir, ext string) return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext)) } +func (p SourcePath) genPathWithExtAndTrimExt(ctx ModuleOutPathContext, subdir, ext string, trimExt string) ModuleGenPath { + // If Trim_extension being set, force append Output_extension without replace original extension. + if trimExt != "" { + if ext != "" { + return PathForModuleGen(ctx, subdir, strings.TrimSuffix(p.path, trimExt)+"."+ext) + } + return PathForModuleGen(ctx, subdir, strings.TrimSuffix(p.path, trimExt)) + } + return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext)) +} + func (p SourcePath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath { return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext)) } @@ -1594,6 +1616,17 @@ func (p ModuleGenPath) genPathWithExt(ctx ModuleOutPathContext, subdir, ext stri return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext)) } +func (p ModuleGenPath) genPathWithExtAndTrimExt(ctx ModuleOutPathContext, subdir, ext string, trimExt string) ModuleGenPath { + // If Trim_extension being set, force append Output_extension without replace original extension. + if trimExt != "" { + if ext != "" { + return PathForModuleGen(ctx, subdir, strings.TrimSuffix(p.path, trimExt)+"."+ext) + } + return PathForModuleGen(ctx, subdir, strings.TrimSuffix(p.path, trimExt)) + } + return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext)) +} + func (p ModuleGenPath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath { return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext)) } diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go index 2574ed487..575b9266c 100644 --- a/android/prebuilt_test.go +++ b/android/prebuilt_test.go @@ -610,45 +610,3 @@ func TestPrebuiltErrorCannotListBothSourceAndPrebuiltInContributions(t *testing. } `, selectMainlineModuleContritbutions) } - -// Test that apex_contributions of prebuilt modules are ignored in coverage builds -func TestSourceIsSelectedInCoverageBuilds(t *testing.T) { - prebuiltMainlineContributions := GroupFixturePreparers( - FixtureModifyProductVariables(func(variables FixtureProductVariables) { - variables.BuildFlags = map[string]string{ - "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_prebuilt_apex_contributions", - } - }), - FixtureMergeEnv(map[string]string{ - "EMMA_INSTRUMENT_FRAMEWORK": "true", - }), - ) - bp := ` - source { - name: "foo", - } - prebuilt { - name: "foo", - srcs: ["prebuilt_file"], - } - apex_contributions { - name: "my_prebuilt_apex_contributions", - api_domain: "my_mainline_module", - contents: [ - "prebuilt_foo", - ], - } - all_apex_contributions { - name: "all_apex_contributions", - } - ` - ctx := GroupFixturePreparers( - PrepareForTestWithArchMutator, - PrepareForTestWithPrebuilts, - FixtureRegisterWithContext(registerTestPrebuiltModules), - prebuiltMainlineContributions).RunTestWithBp(t, bp) - source := ctx.ModuleForTests("foo", "android_common").Module() - AssertBoolEquals(t, "Source should be preferred in coverage builds", true, !source.IsHideFromMake()) - prebuilt := ctx.ModuleForTests("prebuilt_foo", "android_common").Module() - AssertBoolEquals(t, "Prebuilt should not be preferred in coverage builds", false, !prebuilt.IsHideFromMake()) -} diff --git a/android/selects_test.go b/android/selects_test.go index f912ce626..d9499a500 100644 --- a/android/selects_test.go +++ b/android/selects_test.go @@ -28,6 +28,7 @@ func TestSelects(t *testing.T) { name string bp string provider selectsTestProvider + providers map[string]selectsTestProvider vendorVars map[string]map[string]string expectedError string }{ @@ -411,6 +412,42 @@ func TestSelects(t *testing.T) { }, }, { + name: "defaults applied to multiple modules", + bp: ` + my_module_type { + name: "foo2", + defaults: ["bar"], + my_string_list: select(soong_config_variable("my_namespace", "my_variable"), { + "a": ["a1"], + default: ["b1"], + }), + } + my_module_type { + name: "foo", + defaults: ["bar"], + my_string_list: select(soong_config_variable("my_namespace", "my_variable"), { + "a": ["a1"], + default: ["b1"], + }), + } + my_defaults { + name: "bar", + my_string_list: select(soong_config_variable("my_namespace", "my_variable2"), { + "a": ["a2"], + default: ["b2"], + }), + } + `, + providers: map[string]selectsTestProvider{ + "foo": { + my_string_list: &[]string{"b2", "b1"}, + }, + "foo2": { + my_string_list: &[]string{"b2", "b1"}, + }, + }, + }, + { name: "Replacing string list", bp: ` my_module_type { @@ -596,6 +633,61 @@ func TestSelects(t *testing.T) { }, expectedError: "Expected all branches of a select on condition boolean_var_for_testing\\(\\) to have type bool, found string", }, + { + name: "Assigning select to nonconfigurable bool", + bp: ` + my_module_type { + name: "foo", + my_nonconfigurable_bool: select(arch(), { + "x86_64": true, + default: false, + }), + } + `, + expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_bool"`, + }, + { + name: "Assigning select to nonconfigurable string", + bp: ` + my_module_type { + name: "foo", + my_nonconfigurable_string: select(arch(), { + "x86_64": "x86!", + default: "unknown!", + }), + } + `, + expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string"`, + }, + { + name: "Assigning appended selects to nonconfigurable string", + bp: ` + my_module_type { + name: "foo", + my_nonconfigurable_string: select(arch(), { + "x86_64": "x86!", + default: "unknown!", + }) + select(os(), { + "darwin": "_darwin!", + default: "unknown!", + }), + } + `, + expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string"`, + }, + { + name: "Assigning select to nonconfigurable string list", + bp: ` + my_module_type { + name: "foo", + my_nonconfigurable_string_list: select(arch(), { + "x86_64": ["foo", "bar"], + default: ["baz", "qux"], + }), + } + `, + expectedError: `can't assign select statement to non-configurable property "my_nonconfigurable_string_list"`, + }, } for _, tc := range testCases { @@ -617,10 +709,19 @@ func TestSelects(t *testing.T) { result := fixtures.RunTestWithBp(t, tc.bp) if tc.expectedError == "" { - m := result.ModuleForTests("foo", "android_arm64_armv8-a") - p, _ := OtherModuleProvider(result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey) - if !reflect.DeepEqual(p, tc.provider) { - t.Errorf("Expected:\n %q\ngot:\n %q", tc.provider.String(), p.String()) + if len(tc.providers) == 0 { + tc.providers = map[string]selectsTestProvider{ + "foo": tc.provider, + } + } + + for moduleName := range tc.providers { + expected := tc.providers[moduleName] + m := result.ModuleForTests(moduleName, "android_arm64_armv8-a") + p, _ := OtherModuleProvider(result.testContext.OtherModuleProviderAdaptor(), m.Module(), selectsTestProviderKey) + if !reflect.DeepEqual(p, expected) { + t.Errorf("Expected:\n %q\ngot:\n %q", expected.String(), p.String()) + } } } }) @@ -628,11 +729,14 @@ func TestSelects(t *testing.T) { } type selectsTestProvider struct { - my_bool *bool - my_string *string - my_string_list *[]string - my_paths *[]string - replacing_string_list *[]string + my_bool *bool + my_string *string + my_string_list *[]string + my_paths *[]string + replacing_string_list *[]string + my_nonconfigurable_bool *bool + my_nonconfigurable_string *string + my_nonconfigurable_string_list []string } func (p *selectsTestProvider) String() string { @@ -644,23 +748,42 @@ func (p *selectsTestProvider) String() string { if p.my_string != nil { myStringStr = *p.my_string } + myNonconfigurableStringStr := "nil" + if p.my_string != nil { + myNonconfigurableStringStr = *p.my_nonconfigurable_string + } return fmt.Sprintf(`selectsTestProvider { my_bool: %v, my_string: %s, my_string_list: %s, my_paths: %s, replacing_string_list %s, -}`, myBoolStr, myStringStr, p.my_string_list, p.my_paths, p.replacing_string_list) + my_nonconfigurable_bool: %v, + my_nonconfigurable_string: %s, + my_nonconfigurable_string_list: %s, +}`, + myBoolStr, + myStringStr, + p.my_string_list, + p.my_paths, + p.replacing_string_list, + p.my_nonconfigurable_bool, + myNonconfigurableStringStr, + p.my_nonconfigurable_string_list, + ) } var selectsTestProviderKey = blueprint.NewProvider[selectsTestProvider]() type selectsMockModuleProperties struct { - My_bool proptools.Configurable[bool] - My_string proptools.Configurable[string] - My_string_list proptools.Configurable[[]string] - My_paths proptools.Configurable[[]string] `android:"path"` - Replacing_string_list proptools.Configurable[[]string] `android:"replace_instead_of_append,arch_variant"` + My_bool proptools.Configurable[bool] + My_string proptools.Configurable[string] + My_string_list proptools.Configurable[[]string] + My_paths proptools.Configurable[[]string] `android:"path"` + Replacing_string_list proptools.Configurable[[]string] `android:"replace_instead_of_append,arch_variant"` + My_nonconfigurable_bool *bool + My_nonconfigurable_string *string + My_nonconfigurable_string_list []string } type selectsMockModule struct { @@ -671,11 +794,14 @@ type selectsMockModule struct { func (p *selectsMockModule) GenerateAndroidBuildActions(ctx ModuleContext) { SetProvider(ctx, selectsTestProviderKey, selectsTestProvider{ - my_bool: p.properties.My_bool.Get(ctx), - my_string: p.properties.My_string.Get(ctx), - my_string_list: p.properties.My_string_list.Get(ctx), - my_paths: p.properties.My_paths.Get(ctx), - replacing_string_list: p.properties.Replacing_string_list.Get(ctx), + my_bool: p.properties.My_bool.Get(ctx), + my_string: p.properties.My_string.Get(ctx), + my_string_list: p.properties.My_string_list.Get(ctx), + my_paths: p.properties.My_paths.Get(ctx), + replacing_string_list: p.properties.Replacing_string_list.Get(ctx), + my_nonconfigurable_bool: p.properties.My_nonconfigurable_bool, + my_nonconfigurable_string: p.properties.My_nonconfigurable_string, + my_nonconfigurable_string_list: p.properties.My_nonconfigurable_string_list, }) } diff --git a/apex/apex_test.go b/apex/apex_test.go index 3e284b186..1be10483f 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -3671,34 +3671,13 @@ func ensureExactDeapexedContents(t *testing.T, ctx *android.TestContext, moduleN func vndkLibrariesTxtFiles(vers ...string) (result string) { for _, v := range vers { - if v == "current" { - for _, txt := range []string{"vndkcore", "vndksp", "vndkprivate", "vndkproduct"} { - result += ` - ` + txt + `_libraries_txt { - name: "` + txt + `.libraries.txt", - insert_vndk_version: true, - } - ` - } + for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate", "vndkproduct"} { result += ` - llndk_libraries_txt { - name: "llndk.libraries.txt", - } - llndk_libraries_txt_for_apex { - name: "llndk.libraries.txt.apex", - stem: "llndk.libraries.txt", - insert_vndk_version: true, - } - ` - } else { - for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate", "vndkproduct"} { - result += ` prebuilt_etc { name: "` + txt + `.libraries.` + v + `.txt", src: "dummy.txt", } ` - } } } return diff --git a/bin/build-flag b/bin/build-flag new file mode 100755 index 000000000..dc404bc97 --- /dev/null +++ b/bin/build-flag @@ -0,0 +1,28 @@ +#!/bin/bash -eu +# +# Copyright 2017 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. + +source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../../make/shell_utils.sh +require_top + +# Save the current PWD for use in soong_ui +export ORIGINAL_PWD=${PWD} +export TOP=$(gettop) +source ${TOP}/build/soong/scripts/microfactory.bash + +soong_build_go build-flag android/soong/cmd/release_config/build_flag + +cd ${TOP} +exec "$(getoutdir)/build-flag" "$@" diff --git a/cc/builder.go b/cc/builder.go index 845176e09..e78b8c0de 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -855,8 +855,8 @@ func transformObjToDynamicBinary(ctx android.ModuleContext, // into a single .ldump sAbi dump file func transformDumpToLinkedDump(ctx android.ModuleContext, sAbiDumps android.Paths, soFile android.Path, baseName string, exportedIncludeDirs []string, symbolFile android.OptionalPath, - excludedSymbolVersions, excludedSymbolTags []string, - api string) android.Path { + excludedSymbolVersions, excludedSymbolTags, includedSymbolTags []string, + api string, isLlndk bool) android.Path { outputFile := android.PathForModuleOut(ctx, baseName+".lsdump") @@ -874,6 +874,12 @@ func transformDumpToLinkedDump(ctx android.ModuleContext, sAbiDumps android.Path for _, tag := range excludedSymbolTags { symbolFilterStr += " --exclude-symbol-tag " + tag } + for _, tag := range includedSymbolTags { + symbolFilterStr += " --include-symbol-tag " + tag + } + if isLlndk { + symbolFilterStr += " --symbol-tag-policy MatchTagOnly" + } apiLevelsJson := android.GetApiLevelsJson(ctx) implicits = append(implicits, apiLevelsJson) symbolFilterStr += " --api-map " + apiLevelsJson.String() @@ -50,6 +50,7 @@ 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() ctx.BottomUp("version", versionMutator).Parallel() diff --git a/cc/library.go b/cc/library.go index 44bbdfcaf..a436649d0 100644 --- a/cc/library.go +++ b/cc/library.go @@ -1249,28 +1249,29 @@ func (library *libraryDecorator) llndkIncludeDirsForAbiCheck(ctx ModuleContext, func (library *libraryDecorator) linkLlndkSAbiDumpFiles(ctx ModuleContext, deps PathDeps, sAbiDumpFiles android.Paths, soFile android.Path, libFileName string, - excludeSymbolVersions, excludeSymbolTags []string) android.Path { + excludeSymbolVersions, excludeSymbolTags []string, + vendorApiLevel string) android.Path { // NDK symbols in version 34 are LLNDK symbols. Those in version 35 are not. - // TODO(b/314010764): Add parameters to read LLNDK symbols from the symbol file. return transformDumpToLinkedDump(ctx, sAbiDumpFiles, soFile, libFileName+".llndk", library.llndkIncludeDirsForAbiCheck(ctx, deps), android.OptionalPathForModuleSrc(ctx, library.Properties.Llndk.Symbol_file), append([]string{"*_PLATFORM", "*_PRIVATE"}, excludeSymbolVersions...), append([]string{"platform-only"}, excludeSymbolTags...), - "34") + []string{"llndk=" + vendorApiLevel}, "34", true /* isLlndk */) } func (library *libraryDecorator) linkApexSAbiDumpFiles(ctx ModuleContext, deps PathDeps, sAbiDumpFiles android.Paths, soFile android.Path, libFileName string, - excludeSymbolVersions, excludeSymbolTags []string, sdkVersion string) android.Path { + excludeSymbolVersions, excludeSymbolTags []string, + sdkVersion string) android.Path { return transformDumpToLinkedDump(ctx, sAbiDumpFiles, soFile, libFileName+".apex", library.exportedIncludeDirsForAbiCheck(ctx), android.OptionalPathForModuleSrc(ctx, library.Properties.Stubs.Symbol_file), append([]string{"*_PLATFORM", "*_PRIVATE"}, excludeSymbolVersions...), append([]string{"platform-only"}, excludeSymbolTags...), - sdkVersion) + []string{"apex", "systemapi"}, sdkVersion, false /* isLlndk */) } func getRefAbiDumpFile(ctx android.ModuleInstallPathContext, @@ -1397,18 +1398,19 @@ func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, deps PathD android.OptionalPathForModuleSrc(ctx, library.symbolFileForAbiCheck(ctx)), headerAbiChecker.Exclude_symbol_versions, headerAbiChecker.Exclude_symbol_tags, - currSdkVersion) + []string{} /* includeSymbolTags */, currSdkVersion, false /* isLlndk */) var llndkDump, apexVariantDump android.Path tags := classifySourceAbiDump(ctx) for _, tag := range tags { - if tag == llndkLsdumpTag { + if tag == llndkLsdumpTag && currVendorVersion != "" { if llndkDump == nil { // TODO(b/323447559): Evaluate if replacing sAbiDumpFiles with implDump is faster llndkDump = library.linkLlndkSAbiDumpFiles(ctx, deps, objs.sAbiDumpFiles, soFile, fileName, headerAbiChecker.Exclude_symbol_versions, - headerAbiChecker.Exclude_symbol_tags) + headerAbiChecker.Exclude_symbol_tags, + currVendorVersion) } addLsdumpPath(string(tag) + ":" + llndkDump.String()) } else if tag == apexLsdumpTag { diff --git a/cc/linker.go b/cc/linker.go index 9686697c8..56a68b2ce 100644 --- a/cc/linker.go +++ b/cc/linker.go @@ -330,6 +330,7 @@ func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps { deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Vendor.Exclude_static_libs) deps.HeaderLibs = append(deps.HeaderLibs, linker.Properties.Target.Vendor.Header_libs...) deps.HeaderLibs = removeListFromList(deps.HeaderLibs, linker.Properties.Target.Vendor.Exclude_header_libs) + deps.ReexportHeaderLibHeaders = removeListFromList(deps.ReexportHeaderLibHeaders, linker.Properties.Target.Vendor.Exclude_header_libs) deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Vendor.Exclude_static_libs) deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Vendor.Exclude_static_libs) deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Target.Vendor.Exclude_runtime_libs) @@ -342,6 +343,7 @@ func (linker *baseLinker) linkerDeps(ctx DepsContext, deps Deps) Deps { deps.StaticLibs = append(deps.StaticLibs, linker.Properties.Target.Product.Static_libs...) deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Product.Exclude_static_libs) deps.HeaderLibs = removeListFromList(deps.HeaderLibs, linker.Properties.Target.Product.Exclude_header_libs) + deps.ReexportHeaderLibHeaders = removeListFromList(deps.ReexportHeaderLibHeaders, linker.Properties.Target.Product.Exclude_header_libs) deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Product.Exclude_static_libs) deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Product.Exclude_static_libs) deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Target.Product.Exclude_runtime_libs) diff --git a/cc/llndk_library.go b/cc/llndk_library.go index 9e727a10b..ae9da9851 100644 --- a/cc/llndk_library.go +++ b/cc/llndk_library.go @@ -16,12 +16,12 @@ package cc import ( "android/soong/android" + "android/soong/etc" "strings" ) var ( llndkLibrarySuffix = ".llndk" - llndkHeadersSuffix = ".llndk" ) // Holds properties to describe a stub shared library based on the provided version file. @@ -78,3 +78,138 @@ func makeLlndkVars(ctx android.MakeVarsContext) { ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES", strings.Join(android.SortedKeys(movedToApexLlndkLibraries), " ")) } + +func init() { + RegisterLlndkLibraryTxtType(android.InitRegistrationContext) +} + +func RegisterLlndkLibraryTxtType(ctx android.RegistrationContext) { + ctx.RegisterParallelSingletonModuleType("llndk_libraries_txt", llndkLibrariesTxtFactory) +} + +type llndkLibrariesTxtModule struct { + android.SingletonModuleBase + + outputFile android.OutputPath + moduleNames []string + fileNames []string +} + +var _ etc.PrebuiltEtcModule = &llndkLibrariesTxtModule{} +var _ android.OutputFileProducer = &llndkLibrariesTxtModule{} + +// llndk_libraries_txt is a singleton module whose content is a list of LLNDK libraries +// generated by Soong but can be referenced by other modules. +// For example, apex_vndk can depend on these files as prebuilt. +// Make uses LLNDK_LIBRARIES to determine which libraries to install. +// HWASAN is only part of the LL-NDK in builds in which libc depends on HWASAN. +// Therefore, by removing the library here, we cause it to only be installed if libc +// depends on it. +func llndkLibrariesTxtFactory() android.SingletonModule { + m := &llndkLibrariesTxtModule{} + android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) + return m +} + +func (txt *llndkLibrariesTxtModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { + filename := txt.Name() + + txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath + + installPath := android.PathForModuleInstall(ctx, "etc") + ctx.InstallFile(installPath, filename, txt.outputFile) +} + +func (txt *llndkLibrariesTxtModule) GenerateSingletonBuildActions(ctx android.SingletonContext) { + ctx.VisitAllModules(func(m android.Module) { + if c, ok := m.(*Module); ok && c.VendorProperties.IsLLNDK && !c.Header() && !c.IsVndkPrebuiltLibrary() { + filename, err := getVndkFileName(c) + if err != nil { + ctx.ModuleErrorf(m, "%s", err) + } + + if !strings.HasPrefix(ctx.ModuleName(m), "libclang_rt.hwasan") { + txt.moduleNames = append(txt.moduleNames, ctx.ModuleName(m)) + } + txt.fileNames = append(txt.fileNames, filename) + } + }) + txt.moduleNames = android.SortedUniqueStrings(txt.moduleNames) + txt.fileNames = android.SortedUniqueStrings(txt.fileNames) + + android.WriteFileRule(ctx, txt.outputFile, strings.Join(txt.fileNames, "\n")) +} + +func (txt *llndkLibrariesTxtModule) AndroidMkEntries() []android.AndroidMkEntries { + return []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 *llndkLibrariesTxtModule) MakeVars(ctx android.MakeVarsContext) { + ctx.Strict("LLNDK_LIBRARIES", strings.Join(txt.moduleNames, " ")) +} + +// PrebuiltEtcModule interface +func (txt *llndkLibrariesTxtModule) OutputFile() android.OutputPath { + return txt.outputFile +} + +// PrebuiltEtcModule interface +func (txt *llndkLibrariesTxtModule) BaseDir() string { + return "etc" +} + +// PrebuiltEtcModule interface +func (txt *llndkLibrariesTxtModule) SubDir() string { + return "" +} + +func (txt *llndkLibrariesTxtModule) OutputFiles(tag string) (android.Paths, error) { + return android.Paths{txt.outputFile}, nil +} + +func llndkMutator(mctx android.BottomUpMutatorContext) { + m, ok := mctx.Module().(*Module) + if !ok { + return + } + + if shouldSkipLlndkMutator(m) { + return + } + + lib, isLib := m.linker.(*libraryDecorator) + prebuiltLib, isPrebuiltLib := m.linker.(*prebuiltLibraryLinker) + + if m.InVendorOrProduct() && isLib && lib.hasLLNDKStubs() { + m.VendorProperties.IsLLNDK = true + } + if m.InVendorOrProduct() && isPrebuiltLib && prebuiltLib.hasLLNDKStubs() { + m.VendorProperties.IsLLNDK = true + } + + if m.IsVndkPrebuiltLibrary() && !m.IsVndk() { + m.VendorProperties.IsLLNDK = true + } +} + +// Check for modules that mustn't be LLNDK +func shouldSkipLlndkMutator(m *Module) bool { + if !m.Enabled() { + return true + } + if !m.Device() { + return true + } + if m.Target().NativeBridge == android.NativeBridgeEnabled { + return true + } + return false +} diff --git a/cc/prebuilt.go b/cc/prebuilt.go index cbb5d58db..e9f790f73 100644 --- a/cc/prebuilt.go +++ b/cc/prebuilt.go @@ -177,7 +177,7 @@ func (p *prebuiltLibraryLinker) link(ctx ModuleContext, implicits = append(implicits, importLibOutputFile) ctx.Build(pctx, android.BuildParams{ - Rule: android.Cp, + Rule: android.CpExecutable, Description: "prebuilt import library", Input: importLibSrc, Output: importLibOutputFile, @@ -188,7 +188,7 @@ func (p *prebuiltLibraryLinker) link(ctx ModuleContext, } ctx.Build(pctx, android.BuildParams{ - Rule: android.Cp, + Rule: android.CpExecutable, Description: "prebuilt shared library", Implicits: implicits, Input: in, diff --git a/cc/sanitize.go b/cc/sanitize.go index db046ec58..a0cbb5127 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -55,7 +55,6 @@ var ( // higher number of "optimized out" stack variables. // b/112437883. "-instcombine-lower-dbg-declare=0", - "-hwasan-use-after-scope=1", "-dom-tree-reachability-max-bbs-to-explore=128", } @@ -82,7 +81,8 @@ var ( "-fno-sanitize-recover=integer,undefined"} hwasanGlobalOptions = []string{"heap_history_size=1023", "stack_history_size=512", "export_memory_stats=0", "max_malloc_fill_size=131072", "malloc_fill_byte=0"} - memtagStackCommonFlags = []string{"-march=armv8-a+memtag", "-mllvm", "-dom-tree-reachability-max-bbs-to-explore=128"} + memtagStackCommonFlags = []string{"-march=armv8-a+memtag"} + memtagStackLlvmFlags = []string{"-dom-tree-reachability-max-bbs-to-explore=128"} hostOnlySanitizeFlags = []string{"-fno-sanitize-recover=all"} deviceOnlySanitizeFlags = []string{"-fsanitize-trap=all"} @@ -176,11 +176,11 @@ func (t SanitizerType) name() string { func (t SanitizerType) registerMutators(ctx android.RegisterMutatorsContext) { switch t { - case cfi, Hwasan, Asan, tsan, Fuzzer, scs: + case cfi, Hwasan, Asan, tsan, Fuzzer, scs, Memtag_stack: sanitizer := &sanitizerSplitMutator{t} ctx.TopDown(t.variationName()+"_markapexes", sanitizer.markSanitizableApexesMutator) ctx.Transition(t.variationName(), sanitizer) - case Memtag_heap, Memtag_stack, Memtag_globals, intOverflow: + case Memtag_heap, Memtag_globals, intOverflow: // do nothing default: panic(fmt.Errorf("unknown SanitizerType %d", t)) @@ -407,6 +407,7 @@ func init() { android.RegisterMakeVarsProvider(pctx, cfiMakeVarsProvider) android.RegisterMakeVarsProvider(pctx, hwasanMakeVarsProvider) + android.RegisterMakeVarsProvider(pctx, memtagStackMakeVarsProvider) } func (sanitize *sanitize) props() []interface{} { @@ -683,10 +684,14 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { s.Diag.Cfi = nil } - // 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. - if (ctx.inRamdisk() || ctx.inVendorRamdisk() || ctx.inRecovery()) && !strings.HasPrefix(ctx.ModuleDir(), "bionic/libc") { - s.Hwaddress = 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. + if !strings.HasPrefix(ctx.ModuleDir(), "bionic/libc") { + s.Hwaddress = nil + } + // Memtag stack in ramdisk makes pKVM unhappy. + s.Memtag_stack = nil } if ctx.staticBinary() { @@ -879,6 +884,13 @@ func (s *sanitize) flags(ctx ModuleContext, flags Flags) Flags { flags.Local.CFlags = append(flags.Local.CFlags, memtagStackCommonFlags...) flags.Local.AsFlags = append(flags.Local.AsFlags, memtagStackCommonFlags...) flags.Local.LdFlags = append(flags.Local.LdFlags, memtagStackCommonFlags...) + + for _, flag := range memtagStackLlvmFlags { + flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", flag) + } + for _, flag := range memtagStackLlvmFlags { + flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm,"+flag) + } } if (Bool(sanProps.Memtag_heap) || Bool(sanProps.Memtag_stack) || Bool(sanProps.Memtag_globals)) && ctx.binary() { @@ -1303,6 +1315,8 @@ func (s *sanitizerSplitMutator) Mutate(mctx android.BottomUpMutatorContext, vari hwasanStaticLibs(mctx.Config()).add(c, c.Module().Name()) } else if s.sanitizer == cfi { cfiStaticLibs(mctx.Config()).add(c, c.Module().Name()) + } else if s.sanitizer == Memtag_stack { + memtagStackStaticLibs(mctx.Config()).add(c, c.Module().Name()); } } } else if c.IsSanitizerEnabled(s.sanitizer) { @@ -1715,6 +1729,14 @@ func hwasanStaticLibs(config android.Config) *sanitizerStaticLibsMap { }).(*sanitizerStaticLibsMap) } +var memtagStackStaticLibsKey = android.NewOnceKey("memtagStackStaticLibs") + +func memtagStackStaticLibs(config android.Config) *sanitizerStaticLibsMap { + return config.Once(memtagStackStaticLibsKey, func() interface{} { + return newSanitizerStaticLibsMap(Memtag_stack) + }).(*sanitizerStaticLibsMap) +} + func enableMinimalRuntime(sanitize *sanitize) bool { if sanitize.isSanitizerEnabled(Asan) { return false @@ -1761,3 +1783,7 @@ func cfiMakeVarsProvider(ctx android.MakeVarsContext) { func hwasanMakeVarsProvider(ctx android.MakeVarsContext) { hwasanStaticLibs(ctx.Config()).exportToMake(ctx) } + +func memtagStackMakeVarsProvider(ctx android.MakeVarsContext) { + memtagStackStaticLibs(ctx.Config()).exportToMake(ctx) +} diff --git a/cc/testing.go b/cc/testing.go index 20c435aca..4b4e866d4 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -554,6 +554,7 @@ var PrepareForTestWithCcBuildComponents = android.GroupFixturePreparers( ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory) RegisterVndkLibraryTxtTypes(ctx) + RegisterLlndkLibraryTxtType(ctx) }), // Additional files needed in tests that disallow non-existent source files. @@ -570,17 +571,17 @@ var PrepareForTestWithCcDefaultModules = android.GroupFixturePreparers( // Additional files needed in tests that disallow non-existent source. android.MockFS{ - "defaults/cc/common/libc.map.txt": nil, - "defaults/cc/common/libdl.map.txt": nil, - "defaults/cc/common/libft2.map.txt": nil, - "defaults/cc/common/libm.map.txt": nil, - "defaults/cc/common/ndk_libc++_shared": nil, - "defaults/cc/common/crtbegin_so.c": nil, - "defaults/cc/common/crtbegin.c": nil, - "defaults/cc/common/crtend_so.c": nil, - "defaults/cc/common/crtend.c": nil, - "defaults/cc/common/crtbrand.c": nil, - "external/compiler-rt/lib/cfi/cfi_blocklist.txt": nil, + "defaults/cc/common/libc.map.txt": nil, + "defaults/cc/common/libdl.map.txt": nil, + "defaults/cc/common/libft2.map.txt": nil, + "defaults/cc/common/libm.map.txt": nil, + "defaults/cc/common/ndk_libc++_shared": nil, + "defaults/cc/common/crtbegin_so.c": nil, + "defaults/cc/common/crtbegin.c": nil, + "defaults/cc/common/crtend_so.c": nil, + "defaults/cc/common/crtend.c": nil, + "defaults/cc/common/crtbrand.c": nil, + "external/compiler-rt/lib/cfi/cfi_blocklist.txt": nil, "defaults/cc/common/libclang_rt.ubsan_minimal.android_arm64.a": nil, "defaults/cc/common/libclang_rt.ubsan_minimal.android_arm.a": nil, @@ -702,6 +703,7 @@ func CreateTestContext(config android.Config) *android.TestContext { ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory) RegisterVndkLibraryTxtTypes(ctx) + RegisterLlndkLibraryTxtType(ctx) ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators) android.RegisterPrebuiltMutators(ctx) diff --git a/cc/vndk.go b/cc/vndk.go index 14b44b643..50e6d4b96 100644 --- a/cc/vndk.go +++ b/cc/vndk.go @@ -219,7 +219,6 @@ func vndkIsVndkDepAllowed(from *vndkdep, to *vndkdep) error { type moduleListerFunc func(ctx android.SingletonContext) (moduleNames, fileNames []string) var ( - llndkLibraries = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsLLNDK && !m.Header() }) 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 }) @@ -378,19 +377,12 @@ func VndkMutator(mctx android.BottomUpMutatorContext) { prebuiltLib, isPrebuiltLib := m.linker.(*prebuiltLibraryLinker) if m.InVendorOrProduct() && isLib && lib.hasLLNDKStubs() { - m.VendorProperties.IsLLNDK = true m.VendorProperties.IsVNDKPrivate = Bool(lib.Properties.Llndk.Private) } if m.InVendorOrProduct() && isPrebuiltLib && prebuiltLib.hasLLNDKStubs() { - m.VendorProperties.IsLLNDK = true m.VendorProperties.IsVNDKPrivate = Bool(prebuiltLib.Properties.Llndk.Private) } - if m.IsVndkPrebuiltLibrary() && !m.IsVndk() { - m.VendorProperties.IsLLNDK = true - // TODO(b/280697209): copy "llndk.private" flag to vndk_prebuilt_shared - } - if (isLib && lib.buildShared()) || (isPrebuiltLib && prebuiltLib.buildShared()) { if m.vndkdep != nil && m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() { processVndkLibrary(mctx, m) @@ -404,8 +396,6 @@ func init() { } func RegisterVndkLibraryTxtTypes(ctx android.RegistrationContext) { - ctx.RegisterParallelSingletonModuleType("llndk_libraries_txt", llndkLibrariesTxtFactory) - ctx.RegisterParallelSingletonModuleType("llndk_libraries_txt_for_apex", llndkLibrariesTxtApexOnlyFactory) ctx.RegisterParallelSingletonModuleType("vndksp_libraries_txt", vndkSPLibrariesTxtFactory) ctx.RegisterParallelSingletonModuleType("vndkcore_libraries_txt", vndkCoreLibrariesTxtFactory) ctx.RegisterParallelSingletonModuleType("vndkprivate_libraries_txt", vndkPrivateLibrariesTxtFactory) @@ -435,25 +425,6 @@ type VndkLibrariesTxtProperties struct { var _ etc.PrebuiltEtcModule = &vndkLibrariesTxt{} var _ android.OutputFileProducer = &vndkLibrariesTxt{} -// llndk_libraries_txt is a singleton module whose content is a list of LLNDK libraries -// generated by Soong. -// Make uses LLNDK_LIBRARIES to determine which libraries to install. -// HWASAN is only part of the LLNDK in builds in which libc depends on HWASAN. -// Therefore, by removing the library here, we cause it to only be installed if libc -// depends on it. -func llndkLibrariesTxtFactory() android.SingletonModule { - return newVndkLibrariesWithMakeVarFilter(llndkLibraries, "LLNDK_LIBRARIES", "libclang_rt.hwasan") -} - -// llndk_libraries_txt_for_apex is a singleton module that provide the same LLNDK libraries list -// with the llndk_libraries_txt, but skips setting make variable LLNDK_LIBRARIES. So, it must not -// be used without installing llndk_libraries_txt singleton. -// We include llndk_libraries_txt by default to install the llndk.libraries.txt file to system/etc. -// This singleton module is to install the llndk.libraries.<ver>.txt file to vndk apex. -func llndkLibrariesTxtApexOnlyFactory() android.SingletonModule { - return newVndkLibrariesWithMakeVarFilter(llndkLibraries, "", "libclang_rt.hwasan") -} - // 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. diff --git a/cmd/release_config/build_flag/main.go b/cmd/release_config/build_flag/main.go index 6f909af86..56c49d883 100644 --- a/cmd/release_config/build_flag/main.go +++ b/cmd/release_config/build_flag/main.go @@ -1,10 +1,12 @@ package main import ( + "cmp" "flag" "fmt" "os" "path/filepath" + "slices" "strings" rc_lib "android/soong/cmd/release_config/release_config_lib" @@ -36,6 +38,16 @@ type Flags struct { // Disable warning messages quiet bool + + // Show all release configs + allReleases bool + + // Call get_build_var PRODUCT_RELEASE_CONFIG_MAPS to get the + // product-specific map directories. + useGetBuildVar bool + + // Panic on errors. + debug bool } type CommandFunc func(*rc_lib.ReleaseConfigs, Flags, string, []string) error @@ -60,6 +72,14 @@ func GetMapDir(path string) (string, error) { return "", fmt.Errorf("Could not determine directory from %s", path) } +func MarshalFlagDefaultValue(config *rc_lib.ReleaseConfig, name string) (ret string, err error) { + fa, ok := config.FlagArtifacts[name] + if !ok { + return "", fmt.Errorf("%s not found in %s", name, config.Name) + } + return rc_lib.MarshalValue(fa.Traces[0].Value), nil +} + func MarshalFlagValue(config *rc_lib.ReleaseConfig, name string) (ret string, err error) { fa, ok := config.FlagArtifacts[name] if !ok { @@ -68,19 +88,41 @@ func MarshalFlagValue(config *rc_lib.ReleaseConfig, name string) (ret string, er return rc_lib.MarshalValue(fa.Value), nil } +// Returns a list of ReleaseConfig objects for which to process flags. func GetReleaseArgs(configs *rc_lib.ReleaseConfigs, commonFlags Flags) ([]*rc_lib.ReleaseConfig, error) { var all bool - relFlags := flag.NewFlagSet("set", flag.ExitOnError) - relFlags.BoolVar(&all, "all", false, "Display all flags") + relFlags := flag.NewFlagSet("releaseFlags", flag.ExitOnError) + relFlags.BoolVar(&all, "all", false, "Display all releases") relFlags.Parse(commonFlags.targetReleases) var ret []*rc_lib.ReleaseConfig - if all { + if all || commonFlags.allReleases { + sortMap := map[string]int{ + "trunk_staging": 0, + "trunk_food": 10, + "trunk": 20, + // Anything not listed above, uses this for key 1 in the sort. + "-default": 100, + } + for _, config := range configs.ReleaseConfigs { ret = append(ret, config) } + slices.SortFunc(ret, func(a, b *rc_lib.ReleaseConfig) int { + mapValue := func(v *rc_lib.ReleaseConfig) int { + if v, ok := sortMap[v.Name]; ok { + return v + } + return sortMap["-default"] + } + if n := cmp.Compare(mapValue(a), mapValue(b)); n != 0 { + return n + } + return cmp.Compare(a.Name, b.Name) + }) return ret, nil } for _, arg := range relFlags.Args() { + // Return releases in the order that they were given. config, err := configs.GetReleaseConfig(arg) if err != nil { return nil, err @@ -92,12 +134,17 @@ func GetReleaseArgs(configs *rc_lib.ReleaseConfigs, commonFlags Flags) ([]*rc_li func GetCommand(configs *rc_lib.ReleaseConfigs, commonFlags Flags, cmd string, args []string) error { isTrace := cmd == "trace" + isSet := cmd == "set" + var all bool - getFlags := flag.NewFlagSet("set", flag.ExitOnError) + getFlags := flag.NewFlagSet("get", flag.ExitOnError) getFlags.BoolVar(&all, "all", false, "Display all flags") getFlags.Parse(args) args = getFlags.Args() + if isSet { + commonFlags.allReleases = true + } releaseConfigList, err := GetReleaseArgs(configs, commonFlags) if err != nil { return err @@ -113,21 +160,72 @@ func GetCommand(configs *rc_lib.ReleaseConfigs, commonFlags Flags, cmd string, a } } - showName := len(releaseConfigList) > 1 || len(args) > 1 - for _, config := range releaseConfigList { - var configName string - if len(releaseConfigList) > 1 { - configName = fmt.Sprintf("%s.", config.Name) - } + var maxVariableNameLen, maxReleaseNameLen int + var releaseNameFormat, variableNameFormat string + valueFormat := "%s" + showReleaseName := len(releaseConfigList) > 1 + showVariableName := len(args) > 1 + if showVariableName { for _, arg := range args { - val, err := MarshalFlagValue(config, arg) - if err != nil { - return err + maxVariableNameLen = max(len(arg), maxVariableNameLen) + } + variableNameFormat = fmt.Sprintf("%%-%ds ", maxVariableNameLen) + valueFormat = "'%s'" + } + if showReleaseName { + for _, config := range releaseConfigList { + maxReleaseNameLen = max(len(config.Name), maxReleaseNameLen) + } + releaseNameFormat = fmt.Sprintf("%%-%ds ", maxReleaseNameLen) + valueFormat = "'%s'" + } + + outputOneLine := func(variable, release, value, valueFormat string) { + var outStr string + if showVariableName { + outStr += fmt.Sprintf(variableNameFormat, variable) + } + if showReleaseName { + outStr += fmt.Sprintf(releaseNameFormat, release) + } + outStr += fmt.Sprintf(valueFormat, value) + fmt.Println(outStr) + } + + for _, arg := range args { + if _, ok := configs.FlagArtifacts[arg]; !ok { + return fmt.Errorf("%s is not a defined build flag", arg) + } + } + + for _, arg := range args { + for _, config := range releaseConfigList { + if isSet { + // If this is from the set command, format the output as: + // <default> "" + // trunk_staging "" + // trunk "" + // + // ap1a "" + // ... + switch { + case config.Name == "trunk_staging": + defaultValue, err := MarshalFlagDefaultValue(config, arg) + if err != nil { + return err + } + outputOneLine(arg, "<default>", defaultValue, valueFormat) + case config.AconfigFlagsOnly: + continue + case config.Name == "trunk": + fmt.Println() + } } - if showName { - fmt.Printf("%s%s=%s\n", configName, arg, val) + val, err := MarshalFlagValue(config, arg) + if err == nil { + outputOneLine(arg, config.Name, val, valueFormat) } else { - fmt.Printf("%s\n", val) + outputOneLine(arg, config.Name, "REDACTED", "%s") } if isTrace { for _, trace := range config.FlagArtifacts[arg].Traces { @@ -160,6 +258,9 @@ func SetCommand(configs *rc_lib.ReleaseConfigs, commonFlags Flags, cmd string, a if err != nil { return err } + if release.AconfigFlagsOnly { + return fmt.Errorf("%s does not allow build flag overrides", targetRelease) + } flagArtifact, ok := release.FlagArtifacts[name] if !ok { return fmt.Errorf("Unknown build flag %s", name) @@ -177,53 +278,79 @@ func SetCommand(configs *rc_lib.ReleaseConfigs, commonFlags Flags, cmd string, a Value: rc_lib.UnmarshalValue(value), } flagPath := filepath.Join(valueDir, "flag_values", targetRelease, fmt.Sprintf("%s.textproto", name)) - return rc_lib.WriteMessage(flagPath, flagValue) + err = rc_lib.WriteMessage(flagPath, flagValue) + if err != nil { + return err + } + + // Reload the release configs. + configs, err = rc_lib.ReadReleaseConfigMaps(commonFlags.maps, commonFlags.targetReleases[0], commonFlags.useGetBuildVar) + if err != nil { + return err + } + err = GetCommand(configs, commonFlags, cmd, args[0:1]) + if err != nil { + return err + } + fmt.Printf("Updated: %s\n", flagPath) + return nil } func main() { - var err error var commonFlags Flags var configs *rc_lib.ReleaseConfigs + topDir, err := rc_lib.GetTopDir() - outEnv := os.Getenv("OUT_DIR") - if outEnv == "" { - outEnv = "out" - } // Handle the common arguments - flag.StringVar(&commonFlags.top, "top", ".", "path to top of workspace") + flag.StringVar(&commonFlags.top, "top", topDir, "path to top of workspace") flag.BoolVar(&commonFlags.quiet, "quiet", false, "disable warning messages") flag.Var(&commonFlags.maps, "map", "path to a release_config_map.textproto. may be repeated") - flag.StringVar(&commonFlags.outDir, "out_dir", rc_lib.GetDefaultOutDir(), "basepath for the output. Multiple formats are created") + flag.StringVar(&commonFlags.outDir, "out-dir", rc_lib.GetDefaultOutDir(), "basepath for the output. Multiple formats are created") flag.Var(&commonFlags.targetReleases, "release", "TARGET_RELEASE for this build") + flag.BoolVar(&commonFlags.allReleases, "all-releases", false, "operate on all releases. (Ignored for set command)") + flag.BoolVar(&commonFlags.useGetBuildVar, "use-get-build-var", true, "use get_build_var PRODUCT_RELEASE_CONFIG_MAPS to get needed maps") + flag.BoolVar(&commonFlags.debug, "debug", false, "turn on debugging output for errors") flag.Parse() + errorExit := func(err error) { + if commonFlags.debug { + panic(err) + } + fmt.Fprintf(os.Stderr, "%s\n", err) + os.Exit(1) + } + if commonFlags.quiet { rc_lib.DisableWarnings() } if len(commonFlags.targetReleases) == 0 { - commonFlags.targetReleases = rc_lib.StringList{"trunk_staging"} + release, ok := os.LookupEnv("TARGET_RELEASE") + if ok { + commonFlags.targetReleases = rc_lib.StringList{release} + } else { + commonFlags.targetReleases = rc_lib.StringList{"trunk_staging"} + } } if err = os.Chdir(commonFlags.top); err != nil { - panic(err) + errorExit(err) } // Get the current state of flagging. relName := commonFlags.targetReleases[0] if relName == "--all" || relName == "-all" { - // If the users said `--release --all`, grab trunk staging for simplicity. - relName = "trunk_staging" + commonFlags.allReleases = true } - configs, err = rc_lib.ReadReleaseConfigMaps(commonFlags.maps, relName) + configs, err = rc_lib.ReadReleaseConfigMaps(commonFlags.maps, relName, commonFlags.useGetBuildVar) if err != nil { - panic(err) + errorExit(err) } if cmd, ok := commandMap[flag.Arg(0)]; ok { args := flag.Args() if err = cmd(configs, commonFlags, args[0], args[1:]); err != nil { - panic(err) + errorExit(err) } } } diff --git a/cmd/release_config/crunch_flags/main.go b/cmd/release_config/crunch_flags/main.go index 29290a414..4d763c8d7 100644 --- a/cmd/release_config/crunch_flags/main.go +++ b/cmd/release_config/crunch_flags/main.go @@ -15,18 +15,30 @@ import ( "google.golang.org/protobuf/proto" ) -// When a flag declaration has an initial value that is a string, the default workflow is PREBUILT. -// If the flag name starts with any of prefixes in manualFlagNamePrefixes, it is MANUAL. -var manualFlagNamePrefixes []string = []string{ - "RELEASE_ACONFIG_", - "RELEASE_PLATFORM_", -} +var ( + // When a flag declaration has an initial value that is a string, the default workflow is PREBUILT. + // If the flag name starts with any of prefixes in manualFlagNamePrefixes, it is MANUAL. + manualFlagNamePrefixes []string = []string{ + "RELEASE_ACONFIG_", + "RELEASE_PLATFORM_", + "RELEASE_BUILD_FLAGS_", + } + + // Set `aconfig_flags_only: true` in these release configs. + aconfigFlagsOnlyConfigs map[string]bool = map[string]bool{ + "trunk_food": true, + } + + // Default namespace value. This is intentionally invalid. + defaultFlagNamespace string = "android_UNKNOWN" -var defaultFlagNamespace string = "android_UNKNOWN" + // What is the current name for "next". + nextName string = "ap3a" +) func RenameNext(name string) string { if name == "next" { - return "ap3a" + return nextName } return name } @@ -102,10 +114,13 @@ func ProcessBuildFlags(dir string, namespaceMap map[string]string) error { description = "" continue } - declValue := matches[declRegexp.SubexpIndex("value")] declName := matches[declRegexp.SubexpIndex("name")] - container := rc_proto.Container(rc_proto.Container_value[matches[declRegexp.SubexpIndex("container")]]) + declValue := matches[declRegexp.SubexpIndex("value")] description = strings.TrimSpace(description) + containers := []string{strings.ToLower(matches[declRegexp.SubexpIndex("container")])} + if containers[0] == "all" { + containers = []string{"product", "system", "system_ext", "vendor"} + } var namespace string var ok bool if namespace, ok = namespaceMap[declName]; !ok { @@ -115,7 +130,7 @@ func ProcessBuildFlags(dir string, namespaceMap map[string]string) error { Name: proto.String(declName), Namespace: proto.String(namespace), Description: proto.String(description), - Container: &container, + Containers: containers, } description = "" // Most build flags are `workflow: PREBUILT`. @@ -202,6 +217,9 @@ func ProcessBuildConfigs(dir, name string, paths []string, releaseProto *rc_prot fmt.Printf("%s: Unexpected value %s=%s\n", path, valName, valValue) } if flagValue != nil { + if releaseProto.GetAconfigFlagsOnly() { + return fmt.Errorf("%s does not allow build flag overrides", RenameNext(name)) + } valPath := filepath.Join(dir, "flag_values", RenameNext(name), fmt.Sprintf("%s.textproto", valName)) err := WriteFile(valPath, flagValue) if err != nil { @@ -213,6 +231,12 @@ func ProcessBuildConfigs(dir, name string, paths []string, releaseProto *rc_prot return err } +var ( + allContainers = func() []string { + return []string{"product", "system", "system_ext", "vendor"} + }() +) + func ProcessReleaseConfigMap(dir string, descriptionMap map[string]string) error { path := filepath.Join(dir, "release_config_map.mk") if _, err := os.Stat(path); err != nil { @@ -235,16 +259,16 @@ func ProcessReleaseConfigMap(dir string, descriptionMap map[string]string) error return err } cleanDir := strings.TrimLeft(dir, "../") - var defaultContainer rc_proto.Container + var defaultContainers []string switch { case strings.HasPrefix(cleanDir, "build/") || cleanDir == "vendor/google_shared/build": - defaultContainer = rc_proto.Container(rc_proto.Container_ALL) + defaultContainers = allContainers case cleanDir == "vendor/google/release": - defaultContainer = rc_proto.Container(rc_proto.Container_ALL) + defaultContainers = allContainers default: - defaultContainer = rc_proto.Container(rc_proto.Container_VENDOR) + defaultContainers = []string{"vendor"} } - releaseConfigMap := &rc_proto.ReleaseConfigMap{DefaultContainer: &defaultContainer} + releaseConfigMap := &rc_proto.ReleaseConfigMap{DefaultContainers: defaultContainers} // If we find a description for the directory, include it. if description, ok := descriptionMap[cleanDir]; ok { releaseConfigMap.Description = proto.String(description) @@ -276,6 +300,9 @@ func ProcessReleaseConfigMap(dir string, descriptionMap map[string]string) error releaseConfig := &rc_proto.ReleaseConfig{ Name: proto.String(RenameNext(name)), } + if aconfigFlagsOnlyConfigs[name] { + releaseConfig.AconfigFlagsOnly = proto.Bool(true) + } configFiles := config[configRegexp.SubexpIndex("files")] files := strings.Split(strings.ReplaceAll(configFiles, "$(local_dir)", dir+"/"), " ") configInherits := config[configRegexp.SubexpIndex("inherits")] @@ -302,15 +329,26 @@ func main() { var dirs rc_lib.StringList var namespacesFile string var descriptionsFile string + var debug bool + defaultTopDir, err := rc_lib.GetTopDir() - flag.StringVar(&top, "top", ".", "path to top of workspace") + flag.StringVar(&top, "top", defaultTopDir, "path to top of workspace") flag.Var(&dirs, "dir", "directory to process, relative to the top of the workspace") flag.StringVar(&namespacesFile, "namespaces", "", "location of file with 'flag_name namespace' information") flag.StringVar(&descriptionsFile, "descriptions", "", "location of file with 'directory description' information") + flag.BoolVar(&debug, "debug", false, "turn on debugging output for errors") flag.Parse() + errorExit := func(err error) { + if debug { + panic(err) + } + fmt.Fprintf(os.Stderr, "%s\n", err) + os.Exit(1) + } + if err = os.Chdir(top); err != nil { - panic(err) + errorExit(err) } if len(dirs) == 0 { dirs = rc_lib.StringList{"build/release", "vendor/google_shared/build/release", "vendor/google/release"} @@ -320,12 +358,12 @@ func main() { if namespacesFile != "" { data, err := os.ReadFile(namespacesFile) if err != nil { - panic(err) + errorExit(err) } for idx, line := range strings.Split(string(data), "\n") { fields := strings.Split(line, " ") if len(fields) > 2 { - panic(fmt.Errorf("line %d: too many fields: %s", idx, line)) + errorExit(fmt.Errorf("line %d: too many fields: %s", idx, line)) } namespaceMap[fields[0]] = fields[1] } @@ -337,7 +375,7 @@ func main() { if descriptionsFile != "" { data, err := os.ReadFile(descriptionsFile) if err != nil { - panic(err) + errorExit(err) } for _, line := range strings.Split(string(data), "\n") { if strings.TrimSpace(line) != "" { @@ -351,12 +389,12 @@ func main() { for _, dir := range dirs { err = ProcessBuildFlags(dir, namespaceMap) if err != nil { - panic(err) + errorExit(err) } err = ProcessReleaseConfigMap(dir, descriptionMap) if err != nil { - panic(err) + errorExit(err) } } } diff --git a/cmd/release_config/release_config/main.go b/cmd/release_config/release_config/main.go index 22e72a560..101dbe381 100644 --- a/cmd/release_config/release_config/main.go +++ b/cmd/release_config/release_config/main.go @@ -34,6 +34,8 @@ func main() { var json, pb, textproto bool var product string var allMake bool + var useBuildVar bool + var guard bool defaultRelease := os.Getenv("TARGET_RELEASE") if defaultRelease == "" { @@ -50,6 +52,9 @@ func main() { flag.BoolVar(&json, "json", true, "write artifacts as json") flag.BoolVar(&pb, "pb", true, "write artifacts as binary protobuf") flag.BoolVar(&allMake, "all_make", true, "write makefiles for all release configs") + flag.BoolVar(&useBuildVar, "use_get_build_var", false, "use get_build_var PRODUCT_RELEASE_CONFIG_MAPS") + flag.BoolVar(&guard, "guard", true, "whether to guard with RELEASE_BUILD_FLAGS_IN_PROTOBUF") + flag.Parse() if quiet { @@ -59,7 +64,7 @@ func main() { if err = os.Chdir(top); err != nil { panic(err) } - configs, err = rc_lib.ReadReleaseConfigMaps(releaseConfigMapPaths, targetRelease) + configs, err = rc_lib.ReadReleaseConfigMaps(releaseConfigMapPaths, targetRelease, useBuildVar) if err != nil { panic(err) } @@ -67,26 +72,27 @@ func main() { if err != nil { panic(err) } - releaseName := config.Name err = os.MkdirAll(outputDir, 0775) if err != nil { panic(err) } - if err = config.WritePartitionBuildFlags(outputDir, product, targetRelease); err != nil { - panic(err) - } - - if allMake { + makefilePath := filepath.Join(outputDir, fmt.Sprintf("release_config-%s-%s.mk", product, targetRelease)) + useProto, ok := config.FlagArtifacts["RELEASE_BUILD_FLAGS_IN_PROTOBUF"] + if guard && (!ok || rc_lib.MarshalValue(useProto.Value) == "") { + // We were told to guard operation and either we have no build flag, or it is False. + // Write an empty file so that release_config.mk will use the old process. + os.WriteFile(makefilePath, []byte{}, 0644) + } else if allMake { + // Write one makefile per release config, using the canonical release name. for k, _ := range configs.ReleaseConfigs { - makefilePath := filepath.Join(outputDir, fmt.Sprintf("release_config-%s-%s.mk", product, k)) + makefilePath = filepath.Join(outputDir, fmt.Sprintf("release_config-%s-%s.mk", product, k)) err = configs.WriteMakefile(makefilePath, k) if err != nil { panic(err) } } } else { - makefilePath := filepath.Join(outputDir, fmt.Sprintf("release_config-%s-%s.mk", product, releaseName)) err = configs.WriteMakefile(makefilePath, targetRelease) if err != nil { panic(err) @@ -110,4 +116,8 @@ func main() { panic(err) } } + if err = config.WritePartitionBuildFlags(outputDir, product, targetRelease); err != nil { + panic(err) + } + } diff --git a/cmd/release_config/release_config_lib/flag_value.go b/cmd/release_config/release_config_lib/flag_value.go index e155e7782..59021e260 100644 --- a/cmd/release_config/release_config_lib/flag_value.go +++ b/cmd/release_config/release_config_lib/flag_value.go @@ -52,6 +52,9 @@ func UnmarshalValue(str string) *rc_proto.Value { } func MarshalValue(value *rc_proto.Value) string { + if value == nil { + return "" + } switch val := value.Val.(type) { case *rc_proto.Value_UnspecifiedValue: // Value was never set. diff --git a/cmd/release_config/release_config_lib/flag_value_test.go b/cmd/release_config/release_config_lib/flag_value_test.go index aaa4cafeb..8a98baf6a 100644 --- a/cmd/release_config/release_config_lib/flag_value_test.go +++ b/cmd/release_config/release_config_lib/flag_value_test.go @@ -24,7 +24,7 @@ import ( "google.golang.org/protobuf/proto" ) -type testCaseFlagValue struct { +type testCaseFlagValueFactory struct { protoPath string name string data []byte @@ -32,14 +32,14 @@ type testCaseFlagValue struct { err error } -func (tc testCaseFlagValue) assertProtoEqual(t *testing.T, expected, actual proto.Message) { +func (tc testCaseFlagValueFactory) assertProtoEqual(t *testing.T, expected, actual proto.Message) { if !proto.Equal(expected, actual) { t.Errorf("Expected %q found %q", expected, actual) } } -func TestFlagValue(t *testing.T) { - testCases := []testCaseFlagValue{ +func TestFlagValueFactory(t *testing.T) { + testCases := []testCaseFlagValueFactory{ { name: "stringVal", protoPath: "build/release/flag_values/test/RELEASE_FOO.textproto", @@ -65,3 +65,50 @@ func TestFlagValue(t *testing.T) { tc.assertProtoEqual(t, &tc.expected, &actual.proto) } } + +type testCaseMarshalValue struct { + name string + value *rc_proto.Value + expected string +} + +func TestMarshalValue(t *testing.T) { + testCases := []testCaseMarshalValue{ + { + name: "nil", + value: nil, + expected: "", + }, + { + name: "unspecified", + value: &rc_proto.Value{}, + expected: "", + }, + { + name: "false", + value: &rc_proto.Value{Val: &rc_proto.Value_BoolValue{false}}, + expected: "", + }, + { + name: "true", + value: &rc_proto.Value{Val: &rc_proto.Value_BoolValue{true}}, + expected: "true", + }, + { + name: "string", + value: &rc_proto.Value{Val: &rc_proto.Value_StringValue{"BAR"}}, + expected: "BAR", + }, + { + name: "obsolete", + value: &rc_proto.Value{Val: &rc_proto.Value_Obsolete{true}}, + expected: " #OBSOLETE", + }, + } + for _, tc := range testCases { + actual := MarshalValue(tc.value) + if actual != tc.expected { + t.Errorf("Expected %q found %q", tc.expected, actual) + } + } +} diff --git a/cmd/release_config/release_config_lib/release_config.go b/cmd/release_config/release_config_lib/release_config.go index a7a05ae6a..f25cc6e66 100644 --- a/cmd/release_config/release_config_lib/release_config.go +++ b/cmd/release_config/release_config_lib/release_config.go @@ -62,6 +62,10 @@ type ReleaseConfig struct { // The names of release configs that we inherit InheritNames []string + // True if this release config only allows inheritance and aconfig flag + // overrides. Build flag value overrides are an error. + AconfigFlagsOnly bool + // Unmarshalled flag artifacts FlagArtifacts FlagArtifacts @@ -86,7 +90,13 @@ func (config *ReleaseConfig) InheritConfig(iConfig *ReleaseConfig) error { if !ok { return fmt.Errorf("Could not inherit flag %s from %s", name, iConfig.Name) } - if len(fa.Traces) > 1 { + if name == "RELEASE_ACONFIG_VALUE_SETS" { + if len(fa.Traces) > 0 { + myFa.Traces = append(myFa.Traces, fa.Traces...) + myFa.Value = &rc_proto.Value{Val: &rc_proto.Value_StringValue{ + myFa.Value.GetStringValue() + " " + fa.Value.GetStringValue()}} + } + } else if len(fa.Traces) > 1 { // A value was assigned. Set our value. myFa.Traces = append(myFa.Traces, fa.Traces[1:]...) myFa.Value = fa.Value @@ -107,27 +117,7 @@ func (config *ReleaseConfig) GenerateReleaseConfig(configs *ReleaseConfigs) erro // Start with only the flag declarations. config.FlagArtifacts = configs.FlagArtifacts.Clone() - // Add RELEASE_ACONFIG_VALUE_SETS - workflowManual := rc_proto.Workflow(rc_proto.Workflow_MANUAL) - container := rc_proto.Container(rc_proto.Container_ALL) - releaseAconfigValueSets := FlagArtifact{ - FlagDeclaration: &rc_proto.FlagDeclaration{ - Name: proto.String("RELEASE_ACONFIG_VALUE_SETS"), - Namespace: proto.String("android_UNKNOWN"), - Description: proto.String("Aconfig value sets assembled by release-config"), - Workflow: &workflowManual, - Container: &container, - Value: &rc_proto.Value{Val: &rc_proto.Value_StringValue{""}}, - }, - DeclarationIndex: -1, - Traces: []*rc_proto.Tracepoint{ - &rc_proto.Tracepoint{ - Source: proto.String("$release-config"), - Value: &rc_proto.Value{Val: &rc_proto.Value_StringValue{""}}, - }, - }, - } - config.FlagArtifacts["RELEASE_ACONFIG_VALUE_SETS"] = &releaseAconfigValueSets + releaseAconfigValueSets := config.FlagArtifacts["RELEASE_ACONFIG_VALUE_SETS"] // Generate any configs we need to inherit. This will detect loops in // the config. @@ -156,30 +146,28 @@ func (config *ReleaseConfig) GenerateReleaseConfig(configs *ReleaseConfigs) erro } contributionsToApply = append(contributionsToApply, config.Contributions...) - myAconfigValueSets := strings.Split(releaseAconfigValueSets.Value.GetStringValue(), " ") - myAconfigValueSetsMap := map[string]bool{} - for _, v := range myAconfigValueSets { - myAconfigValueSetsMap[v] = true - } + workflowManual := rc_proto.Workflow(rc_proto.Workflow_MANUAL) myDirsMap := make(map[int]bool) for _, contrib := range contributionsToApply { - if len(contrib.proto.AconfigValueSets) > 0 { - contribAconfigValueSets := []string{} - for _, v := range contrib.proto.AconfigValueSets { - if _, ok := myAconfigValueSetsMap[v]; !ok { - contribAconfigValueSets = append(contribAconfigValueSets, v) - myAconfigValueSetsMap[v] = true - } - } - myAconfigValueSets = append(myAconfigValueSets, contribAconfigValueSets...) - releaseAconfigValueSets.Traces = append( - releaseAconfigValueSets.Traces, - &rc_proto.Tracepoint{ - Source: proto.String(contrib.path), - Value: &rc_proto.Value{Val: &rc_proto.Value_StringValue{strings.Join(contribAconfigValueSets, " ")}}, - }) + contribAconfigValueSets := []string{} + // Gather the aconfig_value_sets from this contribution, allowing duplicates for simplicity. + for _, v := range contrib.proto.AconfigValueSets { + contribAconfigValueSets = append(contribAconfigValueSets, v) } + contribAconfigValueSetsString := strings.Join(contribAconfigValueSets, " ") + releaseAconfigValueSets.Value = &rc_proto.Value{Val: &rc_proto.Value_StringValue{ + releaseAconfigValueSets.Value.GetStringValue() + " " + contribAconfigValueSetsString}} + releaseAconfigValueSets.Traces = append( + releaseAconfigValueSets.Traces, + &rc_proto.Tracepoint{ + Source: proto.String(contrib.path), + Value: &rc_proto.Value{Val: &rc_proto.Value_StringValue{contribAconfigValueSetsString}}, + }) + myDirsMap[contrib.DeclarationIndex] = true + if config.AconfigFlagsOnly && len(contrib.FlagValues) > 0 { + return fmt.Errorf("%s does not allow build flag overrides", config.Name) + } for _, value := range contrib.FlagValues { name := *value.proto.Name fa, ok := config.FlagArtifacts[name] @@ -203,6 +191,16 @@ func (config *ReleaseConfig) GenerateReleaseConfig(configs *ReleaseConfigs) erro } } } + // Now remove any duplicates from the actual value of RELEASE_ACONFIG_VALUE_SETS + myAconfigValueSets := []string{} + myAconfigValueSetsMap := map[string]bool{} + for _, v := range strings.Split(releaseAconfigValueSets.Value.GetStringValue(), " ") { + if myAconfigValueSetsMap[v] { + continue + } + myAconfigValueSetsMap[v] = true + myAconfigValueSets = append(myAconfigValueSets, v) + } releaseAconfigValueSets.Value = &rc_proto.Value{Val: &rc_proto.Value_StringValue{strings.TrimSpace(strings.Join(myAconfigValueSets, " "))}} directories := []string{} @@ -214,30 +212,16 @@ func (config *ReleaseConfig) GenerateReleaseConfig(configs *ReleaseConfigs) erro // Now build the per-partition artifacts config.PartitionBuildFlags = make(map[string]*rc_proto.FlagArtifacts) - addPartitionArtifact := func(container string, artifact *rc_proto.FlagArtifact) { - if _, ok := config.PartitionBuildFlags[container]; !ok { - config.PartitionBuildFlags[container] = &rc_proto.FlagArtifacts{} - } - config.PartitionBuildFlags[container].FlagArtifacts = append(config.PartitionBuildFlags[container].FlagArtifacts, artifact) - } for _, v := range config.FlagArtifacts { - container := strings.ToLower(rc_proto.Container_name[int32(v.FlagDeclaration.GetContainer())]) artifact, err := v.MarshalWithoutTraces() if err != nil { return err } - switch container { - case "all": - for cVal, cName := range rc_proto.Container_name { - // Skip unspecified, and "ALL", but place the flag in the rest. - if cVal == 0 || cName == "ALL" { - continue - } - cName = strings.ToLower(cName) - addPartitionArtifact(cName, artifact) + for _, container := range v.FlagDeclaration.Containers { + if _, ok := config.PartitionBuildFlags[container]; !ok { + config.PartitionBuildFlags[container] = &rc_proto.FlagArtifacts{} } - default: - addPartitionArtifact(container, artifact) + config.PartitionBuildFlags[container].FlagArtifacts = append(config.PartitionBuildFlags[container].FlagArtifacts, artifact) } } config.ReleaseConfigArtifact = &rc_proto.ReleaseConfigArtifact{ diff --git a/cmd/release_config/release_config_lib/release_configs.go b/cmd/release_config/release_config_lib/release_configs.go index 3204b1873..34294002c 100644 --- a/cmd/release_config/release_config_lib/release_configs.go +++ b/cmd/release_config/release_config_lib/release_configs.go @@ -95,7 +95,7 @@ func (configs *ReleaseConfigs) WriteArtifact(outDir, product, format string) err } func ReleaseConfigsFactory() (c *ReleaseConfigs) { - return &ReleaseConfigs{ + configs := ReleaseConfigs{ Aliases: make(map[string]*string), FlagArtifacts: make(map[string]*FlagArtifact), ReleaseConfigs: make(map[string]*ReleaseConfig), @@ -103,6 +103,21 @@ func ReleaseConfigsFactory() (c *ReleaseConfigs) { configDirs: []string{}, configDirIndexes: make(ReleaseConfigDirMap), } + workflowManual := rc_proto.Workflow(rc_proto.Workflow_MANUAL) + releaseAconfigValueSets := FlagArtifact{ + FlagDeclaration: &rc_proto.FlagDeclaration{ + Name: proto.String("RELEASE_ACONFIG_VALUE_SETS"), + Namespace: proto.String("android_UNKNOWN"), + Description: proto.String("Aconfig value sets assembled by release-config"), + Workflow: &workflowManual, + Containers: []string{"system", "system_ext", "product", "vendor"}, + Value: &rc_proto.Value{Val: &rc_proto.Value_UnspecifiedValue{false}}, + }, + DeclarationIndex: -1, + Traces: []*rc_proto.Tracepoint{}, + } + configs.FlagArtifacts["RELEASE_ACONFIG_VALUE_SETS"] = &releaseAconfigValueSets + return &configs } func ReleaseConfigMapFactory(protoPath string) (m *ReleaseConfigMap) { @@ -117,9 +132,17 @@ func ReleaseConfigMapFactory(protoPath string) (m *ReleaseConfigMap) { } func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex int) error { + if _, err := os.Stat(path); err != nil { + return fmt.Errorf("%s does not exist\n", path) + } m := ReleaseConfigMapFactory(path) - if m.proto.DefaultContainer == nil { - return fmt.Errorf("Release config map %s lacks default_container", path) + if m.proto.DefaultContainers == nil { + return fmt.Errorf("Release config map %s lacks default_containers", path) + } + for _, container := range m.proto.DefaultContainers { + if !validContainer(container) { + return fmt.Errorf("Release config map %s has invalid container %s", path, container) + } } dir := filepath.Dir(path) // Record any aliases, checking for duplicates. @@ -138,9 +161,16 @@ func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex err = WalkTextprotoFiles(dir, "flag_declarations", func(path string, d fs.DirEntry, err error) error { flagDeclaration := FlagDeclarationFactory(path) // Container must be specified. - if flagDeclaration.Container == nil { - flagDeclaration.Container = m.proto.DefaultContainer + if flagDeclaration.Containers == nil { + flagDeclaration.Containers = m.proto.DefaultContainers + } else { + for _, container := range flagDeclaration.Containers { + if !validContainer(container) { + return fmt.Errorf("Flag declaration %s has invalid container %s", path, container) + } + } } + // TODO: once we have namespaces initialized, we can throw an error here. if flagDeclaration.Namespace == nil { flagDeclaration.Namespace = proto.String("android_UNKNOWN") @@ -151,6 +181,9 @@ func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex } m.FlagDeclarations = append(m.FlagDeclarations, *flagDeclaration) name := *flagDeclaration.Name + if name == "RELEASE_ACONFIG_VALUE_SETS" { + return fmt.Errorf("%s: %s is a reserved build flag", path, name) + } if def, ok := configs.FlagArtifacts[name]; !ok { configs.FlagArtifacts[name] = &FlagArtifact{FlagDeclaration: flagDeclaration, DeclarationIndex: ConfigDirIndex} } else if !proto.Equal(def.FlagDeclaration, flagDeclaration) { @@ -161,7 +194,7 @@ func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex FlagValue{path: path, proto: rc_proto.FlagValue{ Name: proto.String(name), Value: flagDeclaration.Value}}) if configs.FlagArtifacts[name].Redacted { - return fmt.Errorf("%s may not be redacted by default.", *flagDeclaration.Name) + return fmt.Errorf("%s may not be redacted by default.", name) } return nil }) @@ -188,12 +221,18 @@ func (configs *ReleaseConfigs) LoadReleaseConfigMap(path string, ConfigDirIndex if fmt.Sprintf("%s.textproto", *flagValue.proto.Name) != filepath.Base(path) { return fmt.Errorf("%s incorrectly sets value for flag %s", path, *flagValue.proto.Name) } + if *flagValue.proto.Name == "RELEASE_ACONFIG_VALUE_SETS" { + return fmt.Errorf("%s: %s is a reserved build flag", path, *flagValue.proto.Name) + } releaseConfigContribution.FlagValues = append(releaseConfigContribution.FlagValues, flagValue) return nil }) if err2 != nil { return err2 } + if releaseConfigContribution.proto.GetAconfigFlagsOnly() { + config.AconfigFlagsOnly = true + } m.ReleaseConfigContributions[name] = releaseConfigContribution config.Contributions = append(config.Contributions, releaseConfigContribution) return nil @@ -253,19 +292,12 @@ func (configs *ReleaseConfigs) WriteMakefile(outFile, targetRelease string) erro flag := myFlagArtifacts[name] decl := flag.FlagDeclaration - // cName := strings.ToLower(rc_proto.Container_name[decl.GetContainer()]) - cName := strings.ToLower(decl.Container.String()) - if cName == strings.ToLower(rc_proto.Container_ALL.String()) { - partitions["product"] = append(partitions["product"], name) - partitions["system"] = append(partitions["system"], name) - partitions["system_ext"] = append(partitions["system_ext"], name) - partitions["vendor"] = append(partitions["vendor"], name) - } else { - partitions[cName] = append(partitions[cName], name) + for _, container := range decl.Containers { + partitions[container] = append(partitions[container], name) } value := MarshalValue(flag.Value) makeVars[name] = value - addVar(name, "PARTITIONS", cName) + addVar(name, "PARTITIONS", strings.Join(decl.Containers, " ")) addVar(name, "DEFAULT", MarshalValue(decl.Value)) addVar(name, "VALUE", value) addVar(name, "DECLARED_IN", *flag.Traces[0].Source) @@ -360,15 +392,20 @@ func (configs *ReleaseConfigs) GenerateReleaseConfigs(targetRelease string) erro return nil } -func ReadReleaseConfigMaps(releaseConfigMapPaths StringList, targetRelease string) (*ReleaseConfigs, error) { +func ReadReleaseConfigMaps(releaseConfigMapPaths StringList, targetRelease string, useBuildVar bool) (*ReleaseConfigs, error) { var err error if len(releaseConfigMapPaths) == 0 { - releaseConfigMapPaths = GetDefaultMapPaths() + releaseConfigMapPaths, err = GetDefaultMapPaths(useBuildVar) + if err != nil { + return nil, err + } if len(releaseConfigMapPaths) == 0 { return nil, fmt.Errorf("No maps found") } - fmt.Printf("No --map argument provided. Using: --map %s\n", strings.Join(releaseConfigMapPaths, " --map ")) + if !useBuildVar { + warnf("No --map argument provided. Using: --map %s\n", strings.Join(releaseConfigMapPaths, " --map ")) + } } configs := ReleaseConfigsFactory() @@ -382,6 +419,8 @@ func ReadReleaseConfigMaps(releaseConfigMapPaths StringList, targetRelease strin mapsRead[configDir] = true configs.configDirIndexes[configDir] = idx configs.configDirs = append(configs.configDirs, configDir) + // Force the path to be the textproto path, so that both the scl and textproto formats can coexist. + releaseConfigMapPath = filepath.Join(configDir, "release_config_map.textproto") err = configs.LoadReleaseConfigMap(releaseConfigMapPath, idx) if err != nil { return nil, err diff --git a/cmd/release_config/release_config_lib/util.go b/cmd/release_config/release_config_lib/util.go index 86940da68..c0ea7897b 100644 --- a/cmd/release_config/release_config_lib/util.go +++ b/cmd/release_config/release_config_lib/util.go @@ -19,14 +19,19 @@ import ( "fmt" "io/fs" "os" + "os/exec" "path/filepath" + "regexp" "strings" "google.golang.org/protobuf/encoding/prototext" "google.golang.org/protobuf/proto" ) -var disableWarnings bool +var ( + disableWarnings bool + containerRegexp, _ = regexp.Compile("^[a-z][a-z0-9]*([._][a-z][a-z0-9]*)*$") +) type StringList []string @@ -123,11 +128,15 @@ func DisableWarnings() { func warnf(format string, args ...any) (n int, err error) { if !disableWarnings { - return fmt.Printf(format, args...) + return fmt.Fprintf(os.Stderr, format, args...) } return 0, nil } +func validContainer(container string) bool { + return containerRegexp.MatchString(container) +} + // Returns the default value for release config artifacts. func GetDefaultOutDir() string { outEnv := os.Getenv("OUT_DIR") @@ -137,22 +146,64 @@ func GetDefaultOutDir() string { return filepath.Join(outEnv, "soong", "release-config") } +// Find the top of the workspace. +// +// This mirrors the logic in build/envsetup.sh's gettop(). +func GetTopDir() (topDir string, err error) { + workingDir, err := os.Getwd() + if err != nil { + return + } + topFile := "build/make/core/envsetup.mk" + for topDir = workingDir; topDir != "/"; topDir = filepath.Dir(topDir) { + if _, err = os.Stat(filepath.Join(topDir, topFile)); err == nil { + return filepath.Rel(workingDir, topDir) + } + } + return "", fmt.Errorf("Unable to locate top of workspace") +} + // Return the default list of map files to use. -func GetDefaultMapPaths() StringList { - var defaultMapPaths StringList - defaultLocations := StringList{ +func GetDefaultMapPaths(queryMaps bool) (defaultMapPaths StringList, err error) { + var defaultLocations StringList + workingDir, err := os.Getwd() + if err != nil { + return + } + defer func() { + os.Chdir(workingDir) + }() + topDir, err := GetTopDir() + os.Chdir(topDir) + + defaultLocations = StringList{ "build/release/release_config_map.textproto", "vendor/google_shared/build/release/release_config_map.textproto", "vendor/google/release/release_config_map.textproto", } for _, path := range defaultLocations { - if _, err := os.Stat(path); err == nil { + if _, err = os.Stat(path); err == nil { defaultMapPaths = append(defaultMapPaths, path) } } - prodMaps := os.Getenv("PRODUCT_RELEASE_CONFIG_MAPS") - if prodMaps != "" { + + var prodMaps string + if queryMaps { + getBuildVar := exec.Command("build/soong/soong_ui.bash", "--dumpvar-mode", "PRODUCT_RELEASE_CONFIG_MAPS") + var stdout strings.Builder + getBuildVar.Stdin = strings.NewReader("") + getBuildVar.Stdout = &stdout + err = getBuildVar.Run() + if err != nil { + return + } + prodMaps = stdout.String() + } else { + prodMaps = os.Getenv("PRODUCT_RELEASE_CONFIG_MAPS") + } + prodMaps = strings.TrimSpace(prodMaps) + if len(prodMaps) > 0 { defaultMapPaths = append(defaultMapPaths, strings.Split(prodMaps, " ")...) } - return defaultMapPaths + return } 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 ca2005c4b..dded97566 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 @@ -98,76 +98,6 @@ func (Workflow) EnumDescriptor() ([]byte, []int) { return file_build_flags_src_proto_rawDescGZIP(), []int{0} } -type Container int32 - -const ( - Container_UNSPECIFIED_container Container = 0 - // All containers - Container_ALL Container = 1 - // Specific containers - Container_PRODUCT Container = 2 - Container_SYSTEM Container = 3 - Container_SYSTEM_EXT Container = 4 - Container_VENDOR Container = 5 -) - -// Enum value maps for Container. -var ( - Container_name = map[int32]string{ - 0: "UNSPECIFIED_container", - 1: "ALL", - 2: "PRODUCT", - 3: "SYSTEM", - 4: "SYSTEM_EXT", - 5: "VENDOR", - } - Container_value = map[string]int32{ - "UNSPECIFIED_container": 0, - "ALL": 1, - "PRODUCT": 2, - "SYSTEM": 3, - "SYSTEM_EXT": 4, - "VENDOR": 5, - } -) - -func (x Container) Enum() *Container { - p := new(Container) - *p = x - return p -} - -func (x Container) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Container) Descriptor() protoreflect.EnumDescriptor { - return file_build_flags_src_proto_enumTypes[1].Descriptor() -} - -func (Container) Type() protoreflect.EnumType { - return &file_build_flags_src_proto_enumTypes[1] -} - -func (x Container) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Do not use. -func (x *Container) UnmarshalJSON(b []byte) error { - num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) - if err != nil { - return err - } - *x = Container(num) - return nil -} - -// Deprecated: Use Container.Descriptor instead. -func (Container) EnumDescriptor() ([]byte, []int) { - return file_build_flags_src_proto_rawDescGZIP(), []int{1} -} - type Value struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -298,7 +228,7 @@ type FlagDeclaration struct { Workflow *Workflow `protobuf:"varint,205,opt,name=workflow,enum=android.release_config_proto.Workflow" json:"workflow,omitempty"` // The container for this flag. This overrides any default container given // in the release_config_map message. - Container *Container `protobuf:"varint,206,opt,name=container,enum=android.release_config_proto.Container" json:"container,omitempty"` + Containers []string `protobuf:"bytes,206,rep,name=containers" json:"containers,omitempty"` } func (x *FlagDeclaration) Reset() { @@ -368,11 +298,11 @@ func (x *FlagDeclaration) GetWorkflow() Workflow { return Workflow_UNSPECIFIED_workflow } -func (x *FlagDeclaration) GetContainer() Container { - if x != nil && x.Container != nil { - return *x.Container +func (x *FlagDeclaration) GetContainers() []string { + if x != nil { + return x.Containers } - return Container_UNSPECIFIED_container + return nil } type FlagValue struct { @@ -457,6 +387,8 @@ type ReleaseConfig struct { // List of names of the aconfig_value_set soong module(s) for this // contribution. AconfigValueSets []string `protobuf:"bytes,3,rep,name=aconfig_value_sets,json=aconfigValueSets" json:"aconfig_value_sets,omitempty"` + // Only aconfig flags are allowed in this release config. + AconfigFlagsOnly *bool `protobuf:"varint,4,opt,name=aconfig_flags_only,json=aconfigFlagsOnly" json:"aconfig_flags_only,omitempty"` } func (x *ReleaseConfig) Reset() { @@ -512,6 +444,13 @@ func (x *ReleaseConfig) GetAconfigValueSets() []string { return nil } +func (x *ReleaseConfig) GetAconfigFlagsOnly() bool { + if x != nil && x.AconfigFlagsOnly != nil { + return *x.AconfigFlagsOnly + } + return false +} + // Any aliases. These are used for continuous integration builder config. type ReleaseAlias struct { state protoimpl.MessageState @@ -581,7 +520,7 @@ type ReleaseConfigMap struct { // Description of this map and its intended use. Description *string `protobuf:"bytes,2,opt,name=description" json:"description,omitempty"` // The default container for flags declared here. - DefaultContainer *Container `protobuf:"varint,3,opt,name=default_container,json=defaultContainer,enum=android.release_config_proto.Container" json:"default_container,omitempty"` + DefaultContainers []string `protobuf:"bytes,3,rep,name=default_containers,json=defaultContainers" json:"default_containers,omitempty"` } func (x *ReleaseConfigMap) Reset() { @@ -630,11 +569,11 @@ func (x *ReleaseConfigMap) GetDescription() string { return "" } -func (x *ReleaseConfigMap) GetDefaultContainer() Container { - if x != nil && x.DefaultContainer != nil { - return *x.DefaultContainer +func (x *ReleaseConfigMap) GetDefaultContainers() []string { + if x != nil { + return x.DefaultContainers } - return Container_UNSPECIFIED_container + return nil } var File_build_flags_src_proto protoreflect.FileDescriptor @@ -653,7 +592,7 @@ var file_build_flags_src_proto_rawDesc = []byte{ 0x6c, 0x75, 0x65, 0x18, 0xca, 0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a, 0x08, 0x6f, 0x62, 0x73, 0x6f, 0x6c, 0x65, 0x74, 0x65, 0x18, 0xcb, 0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x08, 0x6f, 0x62, - 0x73, 0x6f, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x05, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x22, 0xbd, 0x02, + 0x73, 0x6f, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x05, 0x0a, 0x03, 0x76, 0x61, 0x6c, 0x22, 0x96, 0x02, 0x0a, 0x10, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x64, 0x65, 0x63, 0x6c, 0x61, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, @@ -668,59 +607,50 @@ var file_build_flags_src_proto_rawDesc = []byte{ 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 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, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x08, 0x77, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x46, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x18, 0xce, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 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, 0x63, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x4a, - 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x06, 0x08, 0xcf, 0x01, 0x10, 0xd0, 0x01, 0x22, 0x79, 0x0a, - 0x0a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0xc9, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x23, 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, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1b, 0x0a, 0x08, 0x72, - 0x65, 0x64, 0x61, 0x63, 0x74, 0x65, 0x64, 0x18, 0xca, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, - 0x72, 0x65, 0x64, 0x61, 0x63, 0x74, 0x65, 0x64, 0x22, 0x6e, 0x0a, 0x0e, 0x72, 0x65, 0x6c, 0x65, - 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, - 0x0a, 0x08, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x08, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 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, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x53, 0x65, 0x74, 0x73, 0x22, 0x3b, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x65, - 0x61, 0x73, 0x65, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, - 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xd3, 0x01, 0x0a, 0x12, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, - 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6d, 0x61, 0x70, 0x12, 0x45, 0x0a, 0x07, - 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 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, 0x72, 0x65, 0x6c, - 0x65, 0x61, 0x73, 0x65, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x52, 0x07, 0x61, 0x6c, 0x69, 0x61, - 0x73, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x54, 0x0a, 0x11, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x27, 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, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x10, 0x64, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2a, 0x4a, 0x0a, 0x08, 0x77, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x18, 0x0a, 0x14, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x10, - 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x41, 0x55, 0x4e, 0x43, 0x48, 0x10, 0x01, 0x12, 0x0c, 0x0a, - 0x08, 0x50, 0x52, 0x45, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x4d, - 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x10, 0x03, 0x2a, 0x64, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x15, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x10, 0x00, 0x12, - 0x07, 0x0a, 0x03, 0x41, 0x4c, 0x4c, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x4f, 0x44, - 0x55, 0x43, 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x10, - 0x03, 0x12, 0x0e, 0x0a, 0x0a, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x5f, 0x45, 0x58, 0x54, 0x10, - 0x04, 0x12, 0x0a, 0x0a, 0x06, 0x56, 0x45, 0x4e, 0x44, 0x4f, 0x52, 0x10, 0x05, 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, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x1f, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0xce, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x06, + 0x08, 0xcf, 0x01, 0x10, 0xd0, 0x01, 0x22, 0x79, 0x0a, 0x0a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0xc9, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 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, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1b, 0x0a, 0x08, 0x72, 0x65, 0x64, 0x61, 0x63, 0x74, 0x65, 0x64, + 0x18, 0xca, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x64, 0x61, 0x63, 0x74, 0x65, + 0x64, 0x22, 0x9c, 0x01, 0x0a, 0x0e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x68, 0x65, + 0x72, 0x69, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x68, 0x65, + 0x72, 0x69, 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, 0x03, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x10, 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x65, + 0x74, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x66, 0x6c, + 0x61, 0x67, 0x73, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, + 0x61, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x4f, 0x6e, 0x6c, 0x79, + 0x22, 0x3b, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x61, 0x6c, 0x69, 0x61, + 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xac, 0x01, + 0x0a, 0x12, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x5f, 0x6d, 0x61, 0x70, 0x12, 0x45, 0x0a, 0x07, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 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, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x61, 0x6c, 0x69, + 0x61, 0x73, 0x52, 0x07, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2d, 0x0a, + 0x12, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11, 0x64, 0x65, 0x66, 0x61, 0x75, + 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x2a, 0x4a, 0x0a, 0x08, + 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x18, 0x0a, 0x14, 0x55, 0x4e, 0x53, 0x50, + 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x41, 0x55, 0x4e, 0x43, 0x48, 0x10, 0x01, 0x12, 0x0c, + 0x0a, 0x08, 0x50, 0x52, 0x45, 0x42, 0x55, 0x49, 0x4c, 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, + 0x4d, 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x10, 0x03, 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 ( @@ -735,30 +665,27 @@ func file_build_flags_src_proto_rawDescGZIP() []byte { return file_build_flags_src_proto_rawDescData } -var file_build_flags_src_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_build_flags_src_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_build_flags_src_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_build_flags_src_proto_goTypes = []interface{}{ (Workflow)(0), // 0: android.release_config_proto.workflow - (Container)(0), // 1: android.release_config_proto.container - (*Value)(nil), // 2: android.release_config_proto.value - (*FlagDeclaration)(nil), // 3: android.release_config_proto.flag_declaration - (*FlagValue)(nil), // 4: android.release_config_proto.flag_value - (*ReleaseConfig)(nil), // 5: android.release_config_proto.release_config - (*ReleaseAlias)(nil), // 6: android.release_config_proto.release_alias - (*ReleaseConfigMap)(nil), // 7: android.release_config_proto.release_config_map + (*Value)(nil), // 1: android.release_config_proto.value + (*FlagDeclaration)(nil), // 2: android.release_config_proto.flag_declaration + (*FlagValue)(nil), // 3: android.release_config_proto.flag_value + (*ReleaseConfig)(nil), // 4: android.release_config_proto.release_config + (*ReleaseAlias)(nil), // 5: android.release_config_proto.release_alias + (*ReleaseConfigMap)(nil), // 6: android.release_config_proto.release_config_map } var file_build_flags_src_proto_depIdxs = []int32{ - 2, // 0: android.release_config_proto.flag_declaration.value:type_name -> android.release_config_proto.value + 1, // 0: android.release_config_proto.flag_declaration.value:type_name -> android.release_config_proto.value 0, // 1: android.release_config_proto.flag_declaration.workflow:type_name -> android.release_config_proto.workflow - 1, // 2: android.release_config_proto.flag_declaration.container:type_name -> android.release_config_proto.container - 2, // 3: android.release_config_proto.flag_value.value:type_name -> android.release_config_proto.value - 6, // 4: android.release_config_proto.release_config_map.aliases:type_name -> android.release_config_proto.release_alias - 1, // 5: android.release_config_proto.release_config_map.default_container:type_name -> android.release_config_proto.container - 6, // [6:6] is the sub-list for method output_type - 6, // [6:6] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name + 1, // 2: android.release_config_proto.flag_value.value:type_name -> android.release_config_proto.value + 5, // 3: android.release_config_proto.release_config_map.aliases:type_name -> android.release_config_proto.release_alias + 4, // [4:4] is the sub-list for method output_type + 4, // [4:4] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name } func init() { file_build_flags_src_proto_init() } @@ -851,7 +778,7 @@ func file_build_flags_src_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_build_flags_src_proto_rawDesc, - NumEnums: 2, + NumEnums: 1, NumMessages: 6, NumExtensions: 0, NumServices: 0, diff --git a/cmd/release_config/release_config_proto/build_flags_src.proto b/cmd/release_config/release_config_proto/build_flags_src.proto index 92edc2a66..0ef1a5ffa 100644 --- a/cmd/release_config/release_config_proto/build_flags_src.proto +++ b/cmd/release_config/release_config_proto/build_flags_src.proto @@ -53,19 +53,6 @@ enum workflow { MANUAL = 3; } -enum container { - UNSPECIFIED_container = 0; - - // All containers - ALL = 1; - - // Specific containers - PRODUCT = 2; - SYSTEM = 3; - SYSTEM_EXT = 4; - VENDOR = 5; -} - message value { oneof val { bool unspecified_value = 200; @@ -100,7 +87,7 @@ message flag_declaration { // The container for this flag. This overrides any default container given // in the release_config_map message. - optional container container = 206; + repeated string containers = 206; // The package associated with this flag. // (when Gantry is ready for it) optional string package = 207; @@ -132,6 +119,9 @@ message release_config { // List of names of the aconfig_value_set soong module(s) for this // contribution. repeated string aconfig_value_sets = 3; + + // Only aconfig flags are allowed in this release config. + optional bool aconfig_flags_only = 4; } // Any aliases. These are used for continuous integration builder config. @@ -152,7 +142,7 @@ message release_config_map { optional string description = 2; // The default container for flags declared here. - optional container default_container = 3; + repeated string default_containers = 3; // If needed, we can add these fields instead of hardcoding the location. // Flag declarations: `flag_declarations/*.textproto` diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go index d1c1d853e..025ba27aa 100644 --- a/etc/prebuilt_etc.go +++ b/etc/prebuilt_etc.go @@ -55,6 +55,9 @@ func RegisterPrebuiltEtcBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("prebuilt_usr_share", PrebuiltUserShareFactory) ctx.RegisterModuleType("prebuilt_usr_share_host", PrebuiltUserShareHostFactory) ctx.RegisterModuleType("prebuilt_usr_hyphendata", PrebuiltUserHyphenDataFactory) + ctx.RegisterModuleType("prebuilt_usr_keylayout", PrebuiltUserKeyLayoutFactory) + ctx.RegisterModuleType("prebuilt_usr_keychars", PrebuiltUserKeyCharsFactory) + ctx.RegisterModuleType("prebuilt_usr_idc", PrebuiltUserIdcFactory) ctx.RegisterModuleType("prebuilt_font", PrebuiltFontFactory) ctx.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory) ctx.RegisterModuleType("prebuilt_dsp", PrebuiltDSPFactory) @@ -609,6 +612,39 @@ func PrebuiltUserHyphenDataFactory() android.Module { return module } +// prebuilt_usr_keylayout is for a prebuilt artifact that is installed in +// <partition>/usr/keylayout/<sub_dir> directory. +func PrebuiltUserKeyLayoutFactory() android.Module { + module := &PrebuiltEtc{} + InitPrebuiltEtcModule(module, "usr/keylayout") + // This module is device-only + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) + android.InitDefaultableModule(module) + return module +} + +// prebuilt_usr_keychars is for a prebuilt artifact that is installed in +// <partition>/usr/keychars/<sub_dir> directory. +func PrebuiltUserKeyCharsFactory() android.Module { + module := &PrebuiltEtc{} + InitPrebuiltEtcModule(module, "usr/keychars") + // This module is device-only + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) + android.InitDefaultableModule(module) + return module +} + +// prebuilt_usr_idc is for a prebuilt artifact that is installed in +// <partition>/usr/idc/<sub_dir> directory. +func PrebuiltUserIdcFactory() android.Module { + module := &PrebuiltEtc{} + InitPrebuiltEtcModule(module, "usr/idc") + // This module is device-only + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) + android.InitDefaultableModule(module) + return module +} + // prebuilt_font installs a font in <partition>/fonts directory. func PrebuiltFontFactory() android.Module { module := &PrebuiltEtc{} diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go index dd9958caf..3ee234069 100644 --- a/etc/prebuilt_etc_test.go +++ b/etc/prebuilt_etc_test.go @@ -287,6 +287,48 @@ func TestPrebuiltPrebuiltUserHyphenDataInstallDirPath(t *testing.T) { android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath) } +func TestPrebuiltPrebuiltUserKeyLayoutInstallDirPath(t *testing.T) { + result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` + prebuilt_usr_keylayout { + name: "foo.conf", + src: "foo.conf", + sub_dir: "bar", + } + `) + + p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) + expected := "out/soong/target/product/test_device/system/usr/keylayout/bar" + android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath) +} + +func TestPrebuiltPrebuiltUserKeyCharsInstallDirPath(t *testing.T) { + result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` + prebuilt_usr_keychars { + name: "foo.conf", + src: "foo.conf", + sub_dir: "bar", + } + `) + + p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) + expected := "out/soong/target/product/test_device/system/usr/keychars/bar" + android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath) +} + +func TestPrebuiltPrebuiltUserIdcInstallDirPath(t *testing.T) { + result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` + prebuilt_usr_idc { + name: "foo.conf", + src: "foo.conf", + sub_dir: "bar", + } + `) + + p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) + expected := "out/soong/target/product/test_device/system/usr/idc/bar" + android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath) +} + func TestPrebuiltFontInstallDirPath(t *testing.T) { result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` prebuilt_font { diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go index 3a5071d34..121504867 100644 --- a/filesystem/filesystem_test.go +++ b/filesystem/filesystem_test.go @@ -299,43 +299,6 @@ func TestAvbAddHashFooter(t *testing.T) { cmd, "--include_descriptors_from_image ") } -func TestFileSystemShouldInstallCoreVariantIfTargetBuildAppsIsSet(t *testing.T) { - context := android.GroupFixturePreparers( - fixture, - android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { - variables.Unbundled_build_apps = []string{"bar"} - }), - ) - result := context.RunTestWithBp(t, ` - android_system_image { - name: "myfilesystem", - deps: [ - "libfoo", - ], - linker_config_src: "linker.config.json", - } - - cc_library { - name: "libfoo", - shared_libs: [ - "libbar", - ], - stl: "none", - } - - cc_library { - name: "libbar", - sdk_version: "9", - stl: "none", - } - `) - - inputs := result.ModuleForTests("myfilesystem", "android_common").Output("myfilesystem.img").Implicits - android.AssertStringListContains(t, "filesystem should have libbar even for unbundled build", - inputs.Strings(), - "out/soong/.intermediates/libbar/android_arm64_armv8-a_shared/libbar.so") -} - func TestFileSystemWithCoverageVariants(t *testing.T) { context := android.GroupFixturePreparers( fixture, diff --git a/genrule/genrule.go b/genrule/genrule.go index 43f4fe5ee..4ff82e6a6 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -714,13 +714,13 @@ func NewGenSrcs() *Module { rule := getSandboxedRuleBuilder(ctx, android.NewRuleBuilder(pctx, ctx).Sbox(genDir, nil)) for _, in := range shard { - outFile := android.GenPathWithExt(ctx, finalSubDir, in, String(properties.Output_extension)) + outFile := android.GenPathWithExtAndTrimExt(ctx, finalSubDir, in, String(properties.Output_extension), String(properties.Trim_extension)) // If sharding is enabled, then outFile is the path to the output file in // the shard directory, and copyTo is the path to the output file in the // final directory. if len(shards) > 1 { - shardFile := android.GenPathWithExt(ctx, genSubDir, in, String(properties.Output_extension)) + shardFile := android.GenPathWithExtAndTrimExt(ctx, genSubDir, in, String(properties.Output_extension), String(properties.Trim_extension)) copyTo = append(copyTo, outFile) outFile = shardFile } @@ -786,6 +786,9 @@ type genSrcsProperties struct { // Additional files needed for build that are not tooling related. Data []string `android:"path"` + + // Trim the matched extension for each input file, and it should start with ".". + Trim_extension *string } const defaultShardSize = 50 diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go index 2dc6a7954..1df887b3e 100644 --- a/genrule/genrule_test.go +++ b/genrule/genrule_test.go @@ -894,6 +894,155 @@ func TestGenSrcsWithSrcsFromExternalPackage(t *testing.T) { ) } +func TestGenSrcsWithTrimExtAndOutpuExtension(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForGenRuleTest, + android.FixtureMergeMockFs(android.MockFS{ + "external-protos/path/Android.bp": []byte(` + filegroup { + name: "external-protos", + srcs: [ + "baz.a.b.c.proto/baz.a.b.c.proto", + "bar.a.b.c.proto", + "qux.ext.a.b.c.proto", + ], + } + `), + "package-dir/Android.bp": []byte(` + gensrcs { + name: "module-name", + cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)", + srcs: [ + "src/foo.a.b.c.proto", + ":external-protos", + ], + + trim_extension: ".a.b.c.proto", + output_extension: "proto.h", + } + `), + }), + ).RunTest(t) + + exportedIncludeDir := "out/soong/.intermediates/package-dir/module-name/gen/gensrcs" + gen := result.Module("module-name", "").(*Module) + + android.AssertPathsRelativeToTopEquals( + t, + "include path", + []string{exportedIncludeDir}, + gen.exportedIncludeDirs, + ) + android.AssertPathsRelativeToTopEquals( + t, + "files", + []string{ + exportedIncludeDir + "/package-dir/src/foo.proto.h", + exportedIncludeDir + "/external-protos/path/baz.a.b.c.proto/baz.proto.h", + exportedIncludeDir + "/external-protos/path/bar.proto.h", + exportedIncludeDir + "/external-protos/path/qux.ext.proto.h", + }, + gen.outputFiles, + ) +} + +func TestGenSrcsWithTrimExtButNoOutpuExtension(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForGenRuleTest, + android.FixtureMergeMockFs(android.MockFS{ + "external-protos/path/Android.bp": []byte(` + filegroup { + name: "external-protos", + srcs: [ + "baz.a.b.c.proto/baz.a.b.c.proto", + "bar.a.b.c.proto", + "qux.ext.a.b.c.proto", + ], + } + `), + "package-dir/Android.bp": []byte(` + gensrcs { + name: "module-name", + cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)", + srcs: [ + "src/foo.a.b.c.proto", + ":external-protos", + ], + + trim_extension: ".a.b.c.proto", + } + `), + }), + ).RunTest(t) + + exportedIncludeDir := "out/soong/.intermediates/package-dir/module-name/gen/gensrcs" + gen := result.Module("module-name", "").(*Module) + + android.AssertPathsRelativeToTopEquals( + t, + "include path", + []string{exportedIncludeDir}, + gen.exportedIncludeDirs, + ) + android.AssertPathsRelativeToTopEquals( + t, + "files", + []string{ + exportedIncludeDir + "/package-dir/src/foo", + exportedIncludeDir + "/external-protos/path/baz.a.b.c.proto/baz", + exportedIncludeDir + "/external-protos/path/bar", + exportedIncludeDir + "/external-protos/path/qux.ext", + }, + gen.outputFiles, + ) +} + +func TestGenSrcsWithOutpuExtension(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForGenRuleTest, + android.FixtureMergeMockFs(android.MockFS{ + "external-protos/path/Android.bp": []byte(` + filegroup { + name: "external-protos", + srcs: ["baz/baz.a.b.c.proto", "bar.a.b.c.proto"], + } + `), + "package-dir/Android.bp": []byte(` + gensrcs { + name: "module-name", + cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)", + srcs: [ + "src/foo.a.b.c.proto", + ":external-protos", + ], + + output_extension: "proto.h", + } + `), + }), + ).RunTest(t) + + exportedIncludeDir := "out/soong/.intermediates/package-dir/module-name/gen/gensrcs" + gen := result.Module("module-name", "").(*Module) + + android.AssertPathsRelativeToTopEquals( + t, + "include path", + []string{exportedIncludeDir}, + gen.exportedIncludeDirs, + ) + android.AssertPathsRelativeToTopEquals( + t, + "files", + []string{ + exportedIncludeDir + "/package-dir/src/foo.a.b.c.proto.h", + exportedIncludeDir + "/external-protos/path/baz/baz.a.b.c.proto.h", + exportedIncludeDir + "/external-protos/path/bar.a.b.c.proto.h", + }, + gen.outputFiles, + ) +} + func TestPrebuiltTool(t *testing.T) { testcases := []struct { name string diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go index 0ebab4d8c..07bc5c163 100644 --- a/java/classpath_fragment.go +++ b/java/classpath_fragment.go @@ -151,10 +151,14 @@ func configuredJarListToClasspathJars(ctx android.ModuleContext, configuredJars return jars } +func (c *ClasspathFragmentBase) outputFilename() string { + return strings.ToLower(c.classpathType.String()) + ".pb" +} + func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.ModuleContext, configuredJars android.ConfiguredJarList, jars []classpathJar) { generateProto := proptools.BoolDefault(c.properties.Generate_classpaths_proto, true) if generateProto { - outputFilename := strings.ToLower(c.classpathType.String()) + ".pb" + outputFilename := c.outputFilename() c.outputFilepath = android.PathForModuleOut(ctx, outputFilename).OutputPath c.installDirPath = android.PathForModuleInstall(ctx, "etc", "classpaths") @@ -181,6 +185,10 @@ func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.M android.SetProvider(ctx, ClasspathFragmentProtoContentInfoProvider, classpathProtoInfo) } +func (c *ClasspathFragmentBase) installClasspathProto(ctx android.ModuleContext) android.InstallPath { + return ctx.InstallFile(c.installDirPath, c.outputFilename(), c.outputFilepath) +} + func writeClasspathsTextproto(ctx android.ModuleContext, output android.WritablePath, jars []classpathJar) { var content strings.Builder diff --git a/java/droidstubs.go b/java/droidstubs.go index ffd3caf99..24caf6f37 100644 --- a/java/droidstubs.go +++ b/java/droidstubs.go @@ -604,6 +604,11 @@ func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *a } } +// AndroidPlusUpdatableJar is the name of some extra jars added into `module-lib` and +// `system-server` directories that contain all the APIs provided by the platform and updatable +// modules because the `android.jar` files do not. See b/337836752. +const AndroidPlusUpdatableJar = "android-plus-updatable.jar" + func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) { if len(d.properties.Api_levels_annotations_dirs) == 0 { ctx.PropertyErrorf("api_levels_annotations_dirs", @@ -614,25 +619,58 @@ func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *an filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar") + // TODO: Avoid the duplication of API surfaces, reuse apiScope. + // Add all relevant --android-jar-pattern patterns for Metalava. + // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines + // an actual file present on disk (in the order the patterns were passed). For system APIs for + // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs + // for older releases. Similarly, module-lib falls back to system API. + var sdkDirs []string + switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") { + case "system-server": + sdkDirs = []string{"system-server", "module-lib", "system", "public"} + case "module-lib": + sdkDirs = []string{"module-lib", "system", "public"} + case "system": + sdkDirs = []string{"system", "public"} + case "public": + sdkDirs = []string{"public"} + default: + ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes) + return + } + + // Use the first item in the sdkDirs array as that is the sdk type for the target API levels + // being generated but has the advantage over `Api_levels_sdk_type` as it has been validated. + extensionsPattern := fmt.Sprintf(`/extensions/[0-9]+/%s/.*\.jar`, sdkDirs[0]) + var dirs []string var extensions_dir string ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) { if t, ok := m.(*ExportedDroiddocDir); ok { - extRegex := regexp.MustCompile(t.dir.String() + `/extensions/[0-9]+/public/.*\.jar`) + extRegex := regexp.MustCompile(t.dir.String() + extensionsPattern) // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps; // ideally this should be read from prebuiltApis.properties.Extensions_* for _, dep := range t.deps { + // Check to see if it matches an extension first. + depBase := dep.Base() if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil { if extensions_dir == "" { extensions_dir = t.dir.String() + "/extensions" } cmd.Implicit(dep) - } - if dep.Base() == filename { + } else if depBase == filename { + // Check to see if it matches a dessert release for an SDK, e.g. Android, Car, Wear, etc.. cmd.Implicit(dep) - } - if filename != "android.jar" && dep.Base() == "android.jar" { + } else if depBase == AndroidPlusUpdatableJar && d.properties.Extensions_info_file != nil { + // The output api-versions.xml has been requested to include information on SDK + // extensions. That means it also needs to include + // so + // The module-lib and system-server directories should use `android-plus-updatable.jar` + // instead of `android.jar`. See AndroidPlusUpdatableJar for more information. + cmd.Implicit(dep) + } else if filename != "android.jar" && depBase == "android.jar" { // Metalava implicitly searches these patterns: // prebuilts/tools/common/api-versions/android-%/android.jar // prebuilts/sdk/%/public/android.jar @@ -650,29 +688,25 @@ func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *an } }) - // Add all relevant --android-jar-pattern patterns for Metalava. - // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines - // an actual file present on disk (in the order the patterns were passed). For system APIs for - // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs - // for older releases. Similarly, module-lib falls back to system API. - var sdkDirs []string - switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") { - case "system-server": - sdkDirs = []string{"system-server", "module-lib", "system", "public"} - case "module-lib": - sdkDirs = []string{"module-lib", "system", "public"} - case "system": - sdkDirs = []string{"system", "public"} - case "public": - sdkDirs = []string{"public"} - default: - ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes) - return - } - + // Generate the list of --android-jar-pattern options. The order matters so the first one which + // matches will be the one that is used for a specific api level.. for _, sdkDir := range sdkDirs { for _, dir := range dirs { - cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, filename)) + addPattern := func(jarFilename string) { + cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, jarFilename)) + } + + if sdkDir == "module-lib" || sdkDir == "system-server" { + // The module-lib and system-server android.jars do not include the updatable modules (as + // doing so in the source would introduce dependency cycles and the prebuilts have to + // match the sources). So, instead an additional `android-plus-updatable.jar` will be used + // that does include the updatable modules and this pattern will match that. This pattern + // is added in addition to the following pattern to decouple this change from the change + // to add the `android-plus-updatable.jar`. + addPattern(AndroidPlusUpdatableJar) + } + + addPattern(filename) } } @@ -1322,7 +1356,7 @@ func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) { // use a strict naming convention var ( droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{ - //public is commented out since the core libraries use public in their java_sdk_library names + // public is commented out since the core libraries use public in their java_sdk_library names "intracore": android.SdkIntraCore, "intra.core": android.SdkIntraCore, "system_server": android.SdkSystemServer, diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index 4db426e0d..b3c9ce50f 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -221,6 +221,7 @@ func (b *platformBootclasspathModule) generateClasspathProtoBuildActions(ctx and // ART and platform boot jars must have a corresponding entry in DEX2OATBOOTCLASSPATH classpathJars := configuredJarListToClasspathJars(ctx, configuredJars, BOOTCLASSPATH, DEX2OATBOOTCLASSPATH) b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars) + b.classpathFragmentBase().installClasspathProto(ctx) } func (b *platformBootclasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList { diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go index b291e708b..bad2cf1cf 100644 --- a/java/systemserver_classpath_fragment.go +++ b/java/systemserver_classpath_fragment.go @@ -69,6 +69,7 @@ func (p *platformSystemServerClasspathModule) GenerateAndroidBuildActions(ctx an configuredJars = configuredJars.AppendList(&standaloneConfiguredJars) classpathJars = append(classpathJars, standaloneClasspathJars...) p.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars) + p.classpathFragmentBase().installClasspathProto(ctx) } func (p *platformSystemServerClasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList { diff --git a/python/scripts/precompile_python.py b/python/scripts/precompile_python.py index 07b8fe97b..b3cf950d9 100644 --- a/python/scripts/precompile_python.py +++ b/python/scripts/precompile_python.py @@ -30,6 +30,7 @@ def process_one_file(name, infile, outzip): # Date was chosen to be the same as # https://cs.android.com/android/platform/superproject/main/+/main:build/soong/jar/jar.go;l=36;drc=2863e4535eb65e15f955dc8ed48fa99b1d2a1db5 info = zipfile.ZipInfo(filename=name, date_time=(2008, 1, 1, 0, 0, 0)) + info.compress_type = zipfile.ZIP_DEFLATED if not info.filename.endswith('.py'): outzip.writestr(info, infile.read()) diff --git a/rust/config/global.go b/rust/config/global.go index ba085600b..03333b80c 100644 --- a/rust/config/global.go +++ b/rust/config/global.go @@ -53,6 +53,9 @@ var ( "--color=always", "-Z dylib-lto", "-Z link-native-libraries=no", + + // cfg flag to indicate that we are building in AOSP with Soong + "--cfg soong", } LinuxHostGlobalLinkFlags = []string{ diff --git a/rust/project_json.go b/rust/project_json.go index ad9b69020..05fc09b3a 100644 --- a/rust/project_json.go +++ b/rust/project_json.go @@ -96,7 +96,7 @@ func (singleton *projectGeneratorSingleton) mergeDependencies(ctx android.Single var childId int cInfo, known := singleton.knownCrates[rChild.Name()] if !known { - childId, ok = singleton.addCrate(ctx, rChild, make(map[string]int)) + childId, ok = singleton.addCrate(ctx, rChild) if !ok { return } @@ -128,7 +128,8 @@ func isModuleSupported(ctx android.SingletonContext, module android.Module) (*Mo // addCrate adds a crate to singleton.project.Crates ensuring that required // dependencies are also added. It returns the index of the new crate in // singleton.project.Crates -func (singleton *projectGeneratorSingleton) addCrate(ctx android.SingletonContext, rModule *Module, deps map[string]int) (int, bool) { +func (singleton *projectGeneratorSingleton) addCrate(ctx android.SingletonContext, rModule *Module) (int, bool) { + deps := make(map[string]int) rootModule, err := rModule.compiler.checkedCrateRootPath() if err != nil { return 0, false @@ -180,7 +181,7 @@ func (singleton *projectGeneratorSingleton) appendCrateAndDependencies(ctx andro if cInfo, ok := singleton.knownCrates[module.Name()]; ok { // If we have a new device variant, override the old one if !cInfo.Device && rModule.Device() { - singleton.addCrate(ctx, rModule, cInfo.Deps) + singleton.addCrate(ctx, rModule) return } crate := singleton.project.Crates[cInfo.Idx] @@ -188,7 +189,7 @@ func (singleton *projectGeneratorSingleton) appendCrateAndDependencies(ctx andro singleton.project.Crates[cInfo.Idx] = crate return } - singleton.addCrate(ctx, rModule, make(map[string]int)) + singleton.addCrate(ctx, rModule) } func (singleton *projectGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) { diff --git a/scripts/run-soong-tests-with-go-tools.sh b/scripts/run-soong-tests-with-go-tools.sh index 93c622ea4..1fbb1fc77 100755 --- a/scripts/run-soong-tests-with-go-tools.sh +++ b/scripts/run-soong-tests-with-go-tools.sh @@ -74,6 +74,6 @@ for dir in "${go_modules[@]}"; do (cd "$dir"; eval ${network_jail} -- ${GOROOT}/bin/go build ./... eval ${network_jail} -- ${GOROOT}/bin/go test ./... - eval ${network_jail} -- ${GOROOT}/bin/go test -race -short ./... + eval ${network_jail} -- ${GOROOT}/bin/go test -race -timeout 20m -short ./... ) done diff --git a/tradefed_modules/test_module_config.go b/tradefed_modules/test_module_config.go index 9127f67a9..b2d563129 100644 --- a/tradefed_modules/test_module_config.go +++ b/tradefed_modules/test_module_config.go @@ -160,35 +160,17 @@ func (m *testModuleConfigModule) GenerateAndroidBuildActions(ctx android.ModuleC } -// Any test suites in base should not be repeated in the derived class, except "general-tests". -// We may restrict derived tests to only be "general-tests" as it doesn't make sense to add a slice -// of a test to compatibility suite. +// Ensure at least one test_suite is listed. Ideally it should be general-tests +// or device-tests, whichever is listed in base and prefer general-tests if both are listed. +// However this is not enforced yet. // -// Returns ErrorMessage, false on problems -// Returns _, true if okay. +// Returns true if okay and reports errors via ModuleErrorf. func (m *testModuleConfigModule) validateTestSuites(ctx android.ModuleContext) bool { if len(m.tradefedProperties.Test_suites) == 0 { - ctx.ModuleErrorf("At least one test-suite must be set or this won't run. Use \"general-tests\"") + ctx.ModuleErrorf("At least one test-suite must be set or this won't run. Use \"general-tests\" or \"device-tests\"") return false } - derivedSuites := make(map[string]bool) - // See if any suites in base is also in derived (other than general-tests) - for _, s := range m.tradefedProperties.Test_suites { - if s != "general-tests" { - derivedSuites[s] = true - } - } - if len(derivedSuites) == 0 { - return true - } - for _, baseSuite := range m.provider.TestSuites { - if derivedSuites[baseSuite] { - ctx.ModuleErrorf("TestSuite %s exists in the base, do not add it here", baseSuite) - return false - } - } - return true } diff --git a/tradefed_modules/test_module_config_test.go b/tradefed_modules/test_module_config_test.go index 6997228ce..b2049b1af 100644 --- a/tradefed_modules/test_module_config_test.go +++ b/tradefed_modules/test_module_config_test.go @@ -325,30 +325,6 @@ func TestModuleConfigHostNeedsATestSuite(t *testing.T) { RunTestWithBp(t, badBp) } -func TestModuleConfigHostDuplicateTestSuitesGiveErrors(t *testing.T) { - badBp := ` - java_test_host { - name: "base", - srcs: ["a.java"], - test_suites: ["general-tests", "some-compat"], - } - - test_module_config_host { - name: "derived_test", - base: "base", - exclude_filters: ["android.test.example.devcodelab.DevCodelabTest#testHelloFail"], - include_annotations: ["android.platform.test.annotations.LargeTest"], - test_suites: ["general-tests", "some-compat"], - }` - - android.GroupFixturePreparers( - java.PrepareForTestWithJavaDefaultModules, - android.FixtureRegisterWithContext(RegisterTestModuleConfigBuildComponents), - ).ExtendWithErrorHandler( - android.FixtureExpectsAtLeastOneErrorMatchingPattern("TestSuite some-compat exists in the base")). - RunTestWithBp(t, badBp) -} - func TestTestOnlyProvider(t *testing.T) { t.Parallel() ctx := android.GroupFixturePreparers( |