diff options
45 files changed, 1041 insertions, 332 deletions
diff --git a/Android.bp b/Android.bp index 63de01589..b1db8e937 100644 --- a/Android.bp +++ b/Android.bp @@ -130,3 +130,8 @@ buildinfo_prop { // Currently, only microdroid can refer to buildinfo.prop visibility: ["//packages/modules/Virtualization/microdroid"], } + +// container for apex_contributions selected using build flags +all_apex_contributions { + name: "all_apex_contributions", +} @@ -1,3 +1,4 @@ +# Bug component: 99142 # This file is included by several other projects as the list of people # approving build related projects. diff --git a/aconfig/cc_aconfig_library.go b/aconfig/cc_aconfig_library.go index 5b0fb4a82..8aa696bf1 100644 --- a/aconfig/cc_aconfig_library.go +++ b/aconfig/cc_aconfig_library.go @@ -39,7 +39,14 @@ type CcAconfigLibraryProperties struct { Aconfig_declarations string // whether to generate test mode version of the library + // TODO: remove "Test" property when "Mode" can be used in all the branches Test *bool + + // default mode is "production", the other accepted modes are: + // "test": to generate test mode version of the library + // "exported": to generate exported mode version of the library + // an error will be thrown if the mode is not supported + Mode *string } type CcAconfigLibraryCallbacks struct { @@ -121,11 +128,16 @@ func (this *CcAconfigLibraryCallbacks) GeneratorBuildActions(ctx cc.ModuleContex } declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData) - var mode string + if this.properties.Mode != nil && this.properties.Test != nil { + ctx.PropertyErrorf("test", "test prop should not be specified when mode prop is set") + } + mode := proptools.StringDefault(this.properties.Mode, "production") + if !isModeSupported(mode) { + ctx.PropertyErrorf("mode", "%q is not a supported mode", mode) + } + // TODO: remove "Test" property if proptools.Bool(this.properties.Test) { mode = "test" - } else { - mode = "production" } ctx.Build(pctx, android.BuildParams{ Rule: cppRule, diff --git a/aconfig/cc_aconfig_library_test.go b/aconfig/cc_aconfig_library_test.go index 6f17c7594..9a819e59e 100644 --- a/aconfig/cc_aconfig_library_test.go +++ b/aconfig/cc_aconfig_library_test.go @@ -22,16 +22,17 @@ import ( "android/soong/cc" ) -var codegenModeTestData = []struct { +var ccCodegenModeTestData = []struct { setting, expected string }{ {"", "production"}, - {"test: false,", "production"}, - {"test: true,", "test"}, + {"mode: `production`,", "production"}, + {"mode: `test`,", "test"}, + {"mode: `exported`,", "exported"}, } func TestCCCodegenMode(t *testing.T) { - for _, testData := range codegenModeTestData { + for _, testData := range ccCodegenModeTestData { testCCCodegenModeHelper(t, testData.setting, testData.expected) } } @@ -65,3 +66,43 @@ func testCCCodegenModeHelper(t *testing.T, bpMode string, ruleMode string) { rule := module.Rule("cc_aconfig_library") android.AssertStringEquals(t, "rule must contain test mode", rule.Args["mode"], ruleMode) } + +var incorrectCCCodegenModeTestData = []struct { + setting, expectedErr string +}{ + {"mode: `unsupported`,", "mode: \"unsupported\" is not a supported mode"}, + // TODO: remove this test case when test prop is removed + {"mode: `test`, test: true", "test prop should not be specified when mode prop is set"}, +} + +func TestIncorrectCCCodegenMode(t *testing.T) { + for _, testData := range incorrectCCCodegenModeTestData { + testIncorrectCCCodegenModeHelper(t, testData.setting, testData.expectedErr) + } +} + +func testIncorrectCCCodegenModeHelper(t *testing.T, bpMode string, err string) { + t.Helper() + android.GroupFixturePreparers( + PrepareForTestWithAconfigBuildComponents, + cc.PrepareForTestWithCcDefaultModules). + ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(err)). + RunTestWithBp(t, fmt.Sprintf(` + aconfig_declarations { + name: "my_aconfig_declarations", + package: "com.example.package", + srcs: ["foo.aconfig"], + } + + cc_library { + name: "server_configurable_flags", + srcs: ["server_configurable_flags.cc"], + } + + cc_aconfig_library { + name: "my_cc_aconfig_library", + aconfig_declarations: "my_aconfig_declarations", + %s + } + `, bpMode)) +} diff --git a/aconfig/java_aconfig_library.go b/aconfig/java_aconfig_library.go index f7f8db85d..b6c90fc5f 100644 --- a/aconfig/java_aconfig_library.go +++ b/aconfig/java_aconfig_library.go @@ -30,12 +30,21 @@ type declarationsTagType struct { var declarationsTag = declarationsTagType{} +var aconfigSupportedModes = []string{"production", "test", "exported"} + type JavaAconfigDeclarationsLibraryProperties struct { // name of the aconfig_declarations module to generate a library for Aconfig_declarations string // whether to generate test mode version of the library + // TODO: remove "Test" property when "Mode" can be used in all the branches Test *bool + + // default mode is "production", the other accepted modes are: + // "test": to generate test mode version of the library + // "exported": to generate exported mode version of the library + // an error will be thrown if the mode is not supported + Mode *string } type JavaAconfigDeclarationsLibraryCallbacks struct { @@ -72,12 +81,19 @@ func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) GenerateSourceJarBuild // Generate the action to build the srcjar srcJarPath := android.PathForModuleGen(ctx, ctx.ModuleName()+".srcjar") - var mode string + + if callbacks.properties.Mode != nil && callbacks.properties.Test != nil { + ctx.PropertyErrorf("test", "test prop should not be specified when mode prop is set") + } + mode := proptools.StringDefault(callbacks.properties.Mode, "production") + if !isModeSupported(mode) { + ctx.PropertyErrorf("mode", "%q is not a supported mode", mode) + } + // TODO: remove "Test" property if proptools.Bool(callbacks.properties.Test) { mode = "test" - } else { - mode = "production" } + ctx.Build(pctx, android.BuildParams{ Rule: javaRule, Input: declarations.IntermediatePath, @@ -95,9 +111,12 @@ func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) GenerateSourceJarBuild return srcJarPath } +func isModeSupported(mode string) bool { + return android.InList(mode, aconfigSupportedModes) +} + type bazelJavaAconfigLibraryAttributes struct { Aconfig_declarations bazel.LabelAttribute - Test *bool Sdk_version *string Libs bazel.LabelListAttribute } @@ -138,7 +157,6 @@ func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) Bp2build(ctx android.B attrs := bazelJavaAconfigLibraryAttributes{ Aconfig_declarations: *bazel.MakeLabelAttribute(android.BazelLabelForModuleDepSingle(ctx, callbacks.properties.Aconfig_declarations).Label), - Test: callbacks.properties.Test, Sdk_version: &sdkVersion, Libs: libs, } diff --git a/aconfig/java_aconfig_library_test.go b/aconfig/java_aconfig_library_test.go index af50848f1..05532e701 100644 --- a/aconfig/java_aconfig_library_test.go +++ b/aconfig/java_aconfig_library_test.go @@ -178,14 +178,48 @@ func testCodegenMode(t *testing.T, bpMode string, ruleMode string) { android.AssertStringEquals(t, "rule must contain test mode", rule.Args["mode"], ruleMode) } +func testCodegenModeWithError(t *testing.T, bpMode string, err string) { + android.GroupFixturePreparers( + PrepareForTestWithAconfigBuildComponents, + java.PrepareForTestWithJavaDefaultModules). + ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(err)). + RunTestWithBp(t, fmt.Sprintf(` + aconfig_declarations { + name: "my_aconfig_declarations", + package: "com.example.package", + srcs: ["foo.aconfig"], + } + + java_aconfig_library { + name: "my_java_aconfig_library", + aconfig_declarations: "my_aconfig_declarations", + %s + } + `, bpMode)) +} + func TestDefaultProdMode(t *testing.T) { testCodegenMode(t, "", "production") } func TestProdMode(t *testing.T) { - testCodegenMode(t, "test: false,", "production") + testCodegenMode(t, "mode: `production`,", "production") } func TestTestMode(t *testing.T) { - testCodegenMode(t, "test: true,", "test") + testCodegenMode(t, "mode: `test`,", "test") +} + +func TestExportedMode(t *testing.T) { + testCodegenMode(t, "mode: `exported`,", "exported") +} + +func TestUnsupportedMode(t *testing.T) { + testCodegenModeWithError(t, "mode: `unsupported`,", "mode: \"unsupported\" is not a supported mode") +} + +// TODO: remove this test case when test prop is removed +func TestBothModeAndTestAreSet(t *testing.T) { + testCodegenModeWithError(t, "mode: `test`, test: true", + "test prop should not be specified when mode prop is set") } diff --git a/aconfig/rust_aconfig_library.go b/aconfig/rust_aconfig_library.go index de41776a3..43078b651 100644 --- a/aconfig/rust_aconfig_library.go +++ b/aconfig/rust_aconfig_library.go @@ -1,9 +1,10 @@ package aconfig import ( + "fmt" + "android/soong/android" "android/soong/rust" - "fmt" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -18,7 +19,16 @@ var rustDeclarationsTag = rustDeclarationsTagType{} type RustAconfigLibraryProperties struct { // name of the aconfig_declarations module to generate a library for Aconfig_declarations string - Test *bool + + // whether to generate test mode version of the library + // TODO: remove "Test" property when "Mode" can be used in all the branches + Test *bool + + // default mode is "production", the other accepted modes are: + // "test": to generate test mode version of the library + // "exported": to generate exported mode version of the library + // an error will be thrown if the mode is not supported + Mode *string } type aconfigDecorator struct { @@ -60,7 +70,15 @@ func (a *aconfigDecorator) GenerateSource(ctx rust.ModuleContext, deps rust.Path } declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData) - mode := "production" + if a.Properties.Mode != nil && a.Properties.Test != nil { + ctx.PropertyErrorf("test", "test prop should not be specified when mode prop is set") + } + mode := proptools.StringDefault(a.Properties.Mode, "production") + if !isModeSupported(mode) { + ctx.PropertyErrorf("mode", "%q is not a supported mode", mode) + } + + // TODO: remove "Test" property if proptools.Bool(a.Properties.Test) { mode = "test" } @@ -84,6 +102,7 @@ func (a *aconfigDecorator) GenerateSource(ctx rust.ModuleContext, deps rust.Path func (a *aconfigDecorator) SourceProviderDeps(ctx rust.DepsContext, deps rust.Deps) rust.Deps { deps = a.BaseSourceProvider.SourceProviderDeps(ctx, deps) deps.Rustlibs = append(deps.Rustlibs, "libflags_rust") + deps.Rustlibs = append(deps.Rustlibs, "liblazy_static") ctx.AddDependency(ctx.Module(), rustDeclarationsTag, a.Properties.Aconfig_declarations) return deps } diff --git a/aconfig/rust_aconfig_library_test.go b/aconfig/rust_aconfig_library_test.go index 17385c3d1..5e630b517 100644 --- a/aconfig/rust_aconfig_library_test.go +++ b/aconfig/rust_aconfig_library_test.go @@ -1,10 +1,11 @@ package aconfig import ( - "android/soong/android" - "android/soong/rust" "fmt" "testing" + + "android/soong/android" + "android/soong/rust" ) func TestRustAconfigLibrary(t *testing.T) { @@ -22,6 +23,11 @@ func TestRustAconfigLibrary(t *testing.T) { crate_name: "flags_rust", srcs: ["lib.rs"], } + rust_library { + name: "liblazy_static", // test mock + crate_name: "lazy_static", + srcs: ["src/lib.rs"], + } aconfig_declarations { name: "my_aconfig_declarations", package: "com.example.package", @@ -58,3 +64,98 @@ func TestRustAconfigLibrary(t *testing.T) { ) } } + +var rustCodegenModeTestData = []struct { + setting, expected string +}{ + {"", "production"}, + {"mode: `production`,", "production"}, + {"mode: `test`,", "test"}, + {"mode: `exported`,", "exported"}, +} + +func TestRustCodegenMode(t *testing.T) { + for _, testData := range rustCodegenModeTestData { + testRustCodegenModeHelper(t, testData.setting, testData.expected) + } +} + +func testRustCodegenModeHelper(t *testing.T, bpMode string, ruleMode string) { + t.Helper() + result := android.GroupFixturePreparers( + PrepareForTestWithAconfigBuildComponents, + rust.PrepareForTestWithRustIncludeVndk). + ExtendWithErrorHandler(android.FixtureExpectsNoErrors). + RunTestWithBp(t, fmt.Sprintf(` + rust_library { + name: "libflags_rust", // test mock + crate_name: "flags_rust", + srcs: ["lib.rs"], + } + rust_library { + name: "liblazy_static", // test mock + crate_name: "lazy_static", + srcs: ["src/lib.rs"], + } + aconfig_declarations { + name: "my_aconfig_declarations", + package: "com.example.package", + srcs: ["foo.aconfig"], + } + rust_aconfig_library { + name: "libmy_rust_aconfig_library", + crate_name: "my_rust_aconfig_library", + aconfig_declarations: "my_aconfig_declarations", + %s + } + `, bpMode)) + + module := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_source") + rule := module.Rule("rust_aconfig_library") + android.AssertStringEquals(t, "rule must contain test mode", rule.Args["mode"], ruleMode) +} + +var incorrectRustCodegenModeTestData = []struct { + setting, expectedErr string +}{ + {"mode: `unsupported`,", "mode: \"unsupported\" is not a supported mode"}, + // TODO: remove this test case when test prop is removed + {"mode: `test`, test: true", "test prop should not be specified when mode prop is set"}, +} + +func TestIncorrectRustCodegenMode(t *testing.T) { + for _, testData := range incorrectRustCodegenModeTestData { + testIncorrectRustCodegenModeHelper(t, testData.setting, testData.expectedErr) + } +} + +func testIncorrectRustCodegenModeHelper(t *testing.T, bpMode string, err string) { + t.Helper() + android.GroupFixturePreparers( + PrepareForTestWithAconfigBuildComponents, + rust.PrepareForTestWithRustIncludeVndk). + ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(err)). + RunTestWithBp(t, fmt.Sprintf(` + rust_library { + name: "libflags_rust", // test mock + crate_name: "flags_rust", + srcs: ["lib.rs"], + } + rust_library { + name: "liblazy_static", // test mock + crate_name: "lazy_static", + srcs: ["src/lib.rs"], + } + aconfig_declarations { + name: "my_aconfig_declarations", + package: "com.example.package", + srcs: ["foo.aconfig"], + } + rust_aconfig_library { + name: "libmy_rust_aconfig_library", + crate_name: "my_rust_aconfig_library", + aconfig_declarations: "my_aconfig_declarations", + %s + } + `, bpMode)) +} diff --git a/android/Android.bp b/android/Android.bp index f5bb785ff..7fbba4362 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -32,6 +32,7 @@ bootstrap_go_package { srcs: [ "androidmk.go", "apex.go", + "apex_contributions.go", "api_domain.go", "api_levels.go", "arch.go", diff --git a/android/apex_contributions.go b/android/apex_contributions.go new file mode 100644 index 000000000..6eaca8b23 --- /dev/null +++ b/android/apex_contributions.go @@ -0,0 +1,175 @@ +// Copyright 2023 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +import ( + "github.com/google/blueprint" + "github.com/google/blueprint/proptools" +) + +func init() { + RegisterApexContributionsBuildComponents(InitRegistrationContext) +} + +func RegisterApexContributionsBuildComponents(ctx RegistrationContext) { + ctx.RegisterModuleType("apex_contributions", apexContributionsFactory) + ctx.RegisterSingletonModuleType("all_apex_contributions", allApexContributionsFactory) +} + +type apexContributions struct { + ModuleBase + properties contributionProps +} + +type contributionProps struct { + // Name of the mainline module + Api_domain *string + // A list of module names that should be used when this contribution + // is selected via product_config + // The name should be explicit (foo or prebuilt_foo) + Contents []string +} + +func (m *apexContributions) ApiDomain() string { + return proptools.String(m.properties.Api_domain) +} + +func (m *apexContributions) Contents() []string { + return m.properties.Contents +} + +// apex_contributions contains a list of module names (source or +// prebuilt) belonging to the mainline module +// An apex can have multiple apex_contributions modules +// with different combinations of source or prebuilts, but only one can be +// selected via product_config. +func apexContributionsFactory() Module { + module := &apexContributions{} + module.AddProperties(&module.properties) + InitAndroidModule(module) + return module +} + +// This module type does not have any build actions. +// It provides metadata that is used in post-deps mutator phase for source vs +// prebuilts selection. +func (m *apexContributions) GenerateAndroidBuildActions(ctx ModuleContext) { +} + +// A container for apex_contributions. +// Based on product_config, it will create a dependency on the selected +// apex_contributions per mainline module +type allApexContributions struct { + SingletonModuleBase +} + +func allApexContributionsFactory() SingletonModule { + module := &allApexContributions{} + InitAndroidModule(module) + return module +} + +type apexContributionsDepTag struct { + blueprint.BaseDependencyTag +} + +var ( + acDepTag = apexContributionsDepTag{} +) + +// Creates a dep to each selected apex_contributions +func (a *allApexContributions) DepsMutator(ctx BottomUpMutatorContext) { + ctx.AddDependency(ctx.Module(), acDepTag, ctx.Config().AllApexContributions()...) +} + +// Set PrebuiltSelectionInfoProvider in post deps phase +func (a *allApexContributions) SetPrebuiltSelectionInfoProvider(ctx BaseModuleContext) { + addContentsToProvider := func(p *PrebuiltSelectionInfoMap, m *apexContributions) { + for _, content := range m.Contents() { + if !ctx.OtherModuleExists(content) { + ctx.ModuleErrorf("%s listed in apex_contributions %s does not exist\n", content, m.Name()) + } + pi := &PrebuiltSelectionInfo{ + baseModuleName: RemoveOptionalPrebuiltPrefix(content), + selectedModuleName: content, + metadataModuleName: m.Name(), + apiDomain: m.ApiDomain(), + } + p.Add(ctx, pi) + } + } + + if ctx.Config().Bp2buildMode() { // Skip bp2build + return + } + p := PrebuiltSelectionInfoMap{} + ctx.VisitDirectDepsWithTag(acDepTag, func(child Module) { + if m, ok := child.(*apexContributions); ok { + addContentsToProvider(&p, m) + } else { + ctx.ModuleErrorf("%s is not an apex_contributions module\n", child.Name()) + } + }) + ctx.SetProvider(PrebuiltSelectionInfoProvider, p) +} + +// A provider containing metadata about whether source or prebuilt should be used +// This provider will be used in prebuilt_select mutator to redirect deps +var PrebuiltSelectionInfoProvider = blueprint.NewMutatorProvider(PrebuiltSelectionInfoMap{}, "prebuilt_select") + +// Map of baseModuleName to the selected source or prebuilt +type PrebuiltSelectionInfoMap map[string]PrebuiltSelectionInfo + +// Add a new entry to the map with some validations +func (pm *PrebuiltSelectionInfoMap) Add(ctx BaseModuleContext, p *PrebuiltSelectionInfo) { + if p == nil { + return + } + // Do not allow dups. If the base module (without the prebuilt_) has been added before, raise an exception. + if old, exists := (*pm)[p.baseModuleName]; exists { + ctx.ModuleErrorf("Cannot use Soong module: %s from apex_contributions: %s because it has been added previously as: %s from apex_contributions: %s\n", + p.selectedModuleName, p.metadataModuleName, old.selectedModuleName, old.metadataModuleName, + ) + } + (*pm)[p.baseModuleName] = *p +} + +type PrebuiltSelectionInfo struct { + // e.g. libc + baseModuleName string + // e.g. (libc|prebuilt_libc) + selectedModuleName string + // Name of the apex_contributions module + metadataModuleName string + // e.g. com.android.runtime + apiDomain string +} + +// Returns true if `name` is explicitly requested using one of the selected +// apex_contributions metadata modules. +func (p *PrebuiltSelectionInfoMap) IsSelected(baseModuleName, name string) bool { + if i, exists := (*p)[baseModuleName]; exists { + return i.selectedModuleName == name + } else { + return false + } +} + +// This module type does not have any build actions. +func (a *allApexContributions) GenerateAndroidBuildActions(ctx ModuleContext) { +} + +func (a *allApexContributions) GenerateSingletonBuildActions(ctx SingletonContext) { +} diff --git a/android/config.go b/android/config.go index 213fa2f6b..bf0b9de06 100644 --- a/android/config.go +++ b/android/config.go @@ -99,7 +99,7 @@ type CmdArgs struct { UseBazelProxy bool - BuildFromTextStub bool + BuildFromSourceStub bool EnsureAllowlistIntegrity bool } @@ -344,9 +344,9 @@ type config struct { // unix sockets, instead of spawning Bazel as a subprocess. UseBazelProxy bool - // If buildFromTextStub is true then the Java API stubs are - // built from the signature text files, not the source Java files. - buildFromTextStub bool + // If buildFromSourceStub is true then the Java API stubs are + // built from the source Java files, not the signature text files. + buildFromSourceStub bool // If ensureAllowlistIntegrity is true, then the presence of any allowlisted // modules that aren't mixed-built for at least one variant will cause a build @@ -563,7 +563,7 @@ func NewConfig(cmdArgs CmdArgs, availableEnv map[string]string) (Config, error) MultitreeBuild: cmdArgs.MultitreeBuild, UseBazelProxy: cmdArgs.UseBazelProxy, - buildFromTextStub: cmdArgs.BuildFromTextStub, + buildFromSourceStub: cmdArgs.BuildFromSourceStub, } config.deviceConfig = &deviceConfig{ @@ -2079,11 +2079,11 @@ func (c *config) BuildFromTextStub() bool { // TODO: b/302320354 - Remove the coverage build specific logic once the // robust solution for handling native properties in from-text stub build // is implemented. - return c.buildFromTextStub && !c.JavaCoverageEnabled() + return !c.buildFromSourceStub && !c.JavaCoverageEnabled() } func (c *config) SetBuildFromTextStub(b bool) { - c.buildFromTextStub = b + c.buildFromSourceStub = !b c.productVariables.Build_from_text_stub = boolPtr(b) } @@ -2124,3 +2124,46 @@ func (c *deviceConfig) ReleaseExposeFlaggedApi() bool { func (c *deviceConfig) HideFlaggedApis() bool { return c.NextReleaseHideFlaggedApi() && !c.ReleaseExposeFlaggedApi() } + +func (c *config) GetBuildFlag(name string) (string, bool) { + val, ok := c.productVariables.BuildFlags[name] + return val, ok +} + +var ( + mainlineApexContributionBuildFlags = []string{ + "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", + "RELEASE_APEX_CONTRIBUTIONS_APPSEARCH", + "RELEASE_APEX_CONTRIBUTIONS_ART", + "RELEASE_APEX_CONTRIBUTIONS_BLUETOOTH", + "RELEASE_APEX_CONTRIBUTIONS_CONFIGINFRASTRUCTURE", + "RELEASE_APEX_CONTRIBUTIONS_CONNECTIVITY", + "RELEASE_APEX_CONTRIBUTIONS_CONSCRYPT", + "RELEASE_APEX_CONTRIBUTIONS_CRASHRECOVERY", + "RELEASE_APEX_CONTRIBUTIONS_DEVICELOCK", + "RELEASE_APEX_CONTRIBUTIONS_HEALTHFITNESS", + "RELEASE_APEX_CONTRIBUTIONS_IPSEC", + "RELEASE_APEX_CONTRIBUTIONS_MEDIA", + "RELEASE_APEX_CONTRIBUTIONS_MEDIAPROVIDER", + "RELEASE_APEX_CONTRIBUTIONS_ONDEVICEPERSONALIZATION", + "RELEASE_APEX_CONTRIBUTIONS_PERMISSION", + "RELEASE_APEX_CONTRIBUTIONS_REMOTEKEYPROVISIONING", + "RELEASE_APEX_CONTRIBUTIONS_SCHEDULING", + "RELEASE_APEX_CONTRIBUTIONS_SDKEXTENSIONS", + "RELEASE_APEX_CONTRIBUTIONS_STATSD", + "RELEASE_APEX_CONTRIBUTIONS_UWB", + "RELEASE_APEX_CONTRIBUTIONS_WIFI", + } +) + +// Returns the list of _selected_ apex_contributions +// Each mainline module will have one entry in the list +func (c *config) AllApexContributions() []string { + ret := []string{} + for _, f := range mainlineApexContributionBuildFlags { + if val, exists := c.GetBuildFlag(f); exists && val != "" { + ret = append(ret, val) + } + } + return ret +} diff --git a/android/module.go b/android/module.go index 250161f46..0d405ebd3 100644 --- a/android/module.go +++ b/android/module.go @@ -3231,6 +3231,8 @@ func IsMetaDependencyTag(tag blueprint.DependencyTag) bool { return true } else if tag == licensesTag { return true + } else if tag == acDepTag { + return true } return false } diff --git a/android/neverallow.go b/android/neverallow.go index 2be6a74f5..f721b945c 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -169,6 +169,8 @@ func createJavaDeviceForHostRules() []Rule { "external/kotlinx.coroutines", "external/robolectric-shadows", "external/robolectric", + "frameworks/base/ravenwood", + "frameworks/base/tools/hoststubgen", "frameworks/layoutlib", } diff --git a/android/prebuilt.go b/android/prebuilt.go index e7b79796e..91c0aa182 100644 --- a/android/prebuilt.go +++ b/android/prebuilt.go @@ -387,7 +387,7 @@ func RegisterPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) { func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) { ctx.BottomUp("prebuilt_source", PrebuiltSourceDepsMutator).Parallel() - ctx.TopDown("prebuilt_select", PrebuiltSelectModuleMutator).Parallel() + ctx.BottomUp("prebuilt_select", PrebuiltSelectModuleMutator).Parallel() ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).Parallel() } @@ -406,6 +406,8 @@ func PrebuiltRenameMutator(ctx BottomUpMutatorContext) { // PrebuiltSourceDepsMutator adds dependencies to the prebuilt module from the // corresponding source module, if one exists for the same variant. +// Add a dependency from the prebuilt to `all_apex_contributions` +// The metadata will be used for source vs prebuilts selection func PrebuiltSourceDepsMutator(ctx BottomUpMutatorContext) { m := ctx.Module() // If this module is a prebuilt, is enabled and has not been renamed to source then add a @@ -416,6 +418,14 @@ func PrebuiltSourceDepsMutator(ctx BottomUpMutatorContext) { ctx.AddReverseDependency(ctx.Module(), PrebuiltDepTag, name) p.properties.SourceExists = true } + // Add a dependency from the prebuilt to the `all_apex_contributions` + // metadata module + // TODO: When all branches contain this singleton module, make this strict + // TODO: Add this dependency only for mainline prebuilts and not every prebuilt module + if ctx.OtherModuleExists("all_apex_contributions") { + ctx.AddDependency(m, acDepTag, "all_apex_contributions") + } + } } @@ -435,7 +445,11 @@ func checkInvariantsForSourceAndPrebuilt(ctx BaseModuleContext, s, p Module) { // PrebuiltSelectModuleMutator marks prebuilts that are used, either overriding source modules or // because the source module doesn't exist. It also disables installing overridden source modules. -func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) { +// +// If the visited module is the metadata module `all_apex_contributions`, it sets a +// provider containing metadata about whether source or prebuilt of mainline modules should be used. +// This logic was added here to prevent the overhead of creating a new mutator. +func PrebuiltSelectModuleMutator(ctx BottomUpMutatorContext) { m := ctx.Module() if p := GetEmbeddedPrebuilt(m); p != nil { if p.srcsSupplier == nil && p.srcsPropertyName == "" { @@ -444,6 +458,17 @@ func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) { if !p.properties.SourceExists { p.properties.UsePrebuilt = p.usePrebuilt(ctx, nil, m) } + // Propagate the provider received from `all_apex_contributions` + // to the source module + ctx.VisitDirectDepsWithTag(acDepTag, func(am Module) { + if ctx.Config().Bp2buildMode() { + // This provider key is not applicable in bp2build + return + } + psi := ctx.OtherModuleProvider(am, PrebuiltSelectionInfoProvider).(PrebuiltSelectionInfoMap) + ctx.SetProvider(PrebuiltSelectionInfoProvider, psi) + }) + } else if s, ok := ctx.Module().(Module); ok { ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(prebuiltModule Module) { p := GetEmbeddedPrebuilt(prebuiltModule) @@ -455,6 +480,11 @@ func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) { } }) } + // If this is `all_apex_contributions`, set a provider containing + // metadata about source vs prebuilts selection + if am, ok := m.(*allApexContributions); ok { + am.SetPrebuiltSelectionInfoProvider(ctx) + } } // PrebuiltPostDepsMutator replaces dependencies on the source module with dependencies on the @@ -480,9 +510,66 @@ func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) { } } +// A wrapper around PrebuiltSelectionInfoMap.IsSelected with special handling for java_sdk_library +// java_sdk_library is a macro that creates +// 1. top-level impl library +// 2. stub libraries (suffixed with .stubs...) +// +// java_sdk_library_import is a macro that creates +// 1. top-level "impl" library +// 2. stub libraries (suffixed with .stubs...) +// +// the impl of java_sdk_library_import is a "hook" for hiddenapi and dexpreopt processing. It does not have an impl jar, but acts as a shim +// to provide the jar deapxed from the prebuilt apex +// +// isSelected uses `all_apex_contributions` to supersede source vs prebuilts selection of the stub libraries. It does not supersede the +// selection of the top-level "impl" library so that this hook can work +// +// TODO (b/308174306) - Fix this when we need to support multiple prebuilts in main +func isSelected(psi PrebuiltSelectionInfoMap, m Module) bool { + if sdkLibrary, ok := m.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil { + sln := proptools.String(sdkLibrary.SdkLibraryName()) + // This is the top-level library + // Do not supersede the existing prebuilts vs source selection mechanisms + if sln == m.base().BaseModuleName() { + return false + } + + // Stub library created by java_sdk_library_import + if p := GetEmbeddedPrebuilt(m); p != nil { + return psi.IsSelected(sln, PrebuiltNameFromSource(sln)) + } + + // Stub library created by java_sdk_library + return psi.IsSelected(sln, sln) + } + return psi.IsSelected(m.base().BaseModuleName(), m.Name()) +} + // usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt // will be used if it is marked "prefer" or if the source module is disabled. -func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module, prebuilt Module) bool { +func (p *Prebuilt) usePrebuilt(ctx BaseMutatorContext, source Module, prebuilt Module) bool { + // Use `all_apex_contributions` for source vs prebuilt selection. + psi := PrebuiltSelectionInfoMap{} + ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(am Module) { + if ctx.OtherModuleHasProvider(am, PrebuiltSelectionInfoProvider) { + psi = ctx.OtherModuleProvider(am, PrebuiltSelectionInfoProvider).(PrebuiltSelectionInfoMap) + } + }) + + // If the source module is explicitly listed in the metadata module, use that + if source != nil && isSelected(psi, source) { + return false + } + // If the prebuilt module is explicitly listed in the metadata module, use that + if isSelected(psi, prebuilt) { + return true + } + + // If the baseModuleName could not be found in the metadata module, + // fall back to the existing source vs prebuilt selection. + // TODO: Drop the fallback mechanisms + if !ctx.Config().Bp2buildMode() { if p.srcsSupplier != nil && len(p.srcsSupplier(ctx, prebuilt)) == 0 { return false diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go index fc47cfd97..953258edd 100644 --- a/android/prebuilt_test.go +++ b/android/prebuilt_test.go @@ -335,6 +335,78 @@ func TestPrebuilts(t *testing.T) { prebuilt: []OsType{Android, buildOS}, }, { + name: "apex_contributions supersedes any source preferred via use_source_config_var", + modules: ` + source { + name: "bar", + } + + prebuilt { + name: "bar", + use_source_config_var: {config_namespace: "acme", var_name: "use_source"}, + srcs: ["prebuilt_file"], + } + apex_contributions { + name: "my_mainline_module_contribution", + api_domain: "apexfoo", + // this metadata module contains prebuilt + contents: ["prebuilt_bar"], + } + all_apex_contributions { + name: "all_apex_contributions", + } + `, + preparer: FixtureModifyProductVariables(func(variables FixtureProductVariables) { + variables.VendorVars = map[string]map[string]string{ + "acme": { + "use_source": "true", + }, + } + variables.BuildFlags = map[string]string{ + "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_mainline_module_contribution", + } + }), + // use_source_config_var indicates that source should be used + // but this is superseded by `my_mainline_module_contribution` + prebuilt: []OsType{Android, buildOS}, + }, + { + name: "apex_contributions supersedes any prebuilt preferred via use_source_config_var", + modules: ` + source { + name: "bar", + } + + prebuilt { + name: "bar", + use_source_config_var: {config_namespace: "acme", var_name: "use_source"}, + srcs: ["prebuilt_file"], + } + apex_contributions { + name: "my_mainline_module_contribution", + api_domain: "apexfoo", + // this metadata module contains source + contents: ["bar"], + } + all_apex_contributions { + name: "all_apex_contributions", + } + `, + preparer: FixtureModifyProductVariables(func(variables FixtureProductVariables) { + variables.VendorVars = map[string]map[string]string{ + "acme": { + "use_source": "false", + }, + } + variables.BuildFlags = map[string]string{ + "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_mainline_module_contribution", + } + }), + // use_source_config_var indicates that prebuilt should be used + // but this is superseded by `my_mainline_module_contribution` + prebuilt: nil, + }, + { name: "prebuilt use_source_config_var={acme, use_source} - acme_use_source=true", modules: ` source { @@ -497,7 +569,7 @@ func TestPrebuilts(t *testing.T) { } } -func testPrebuiltError(t *testing.T, expectedError, bp string) { +func testPrebuiltErrorWithFixture(t *testing.T, expectedError, bp string, fixture FixturePreparer) { t.Helper() fs := MockFS{ "prebuilt_file": nil, @@ -508,9 +580,15 @@ func testPrebuiltError(t *testing.T, expectedError, bp string) { PrepareForTestWithOverrides, fs.AddToFixture(), FixtureRegisterWithContext(registerTestPrebuiltModules), + OptionalFixturePreparer(fixture), ). ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern(expectedError)). RunTestWithBp(t, bp) + +} + +func testPrebuiltError(t *testing.T, expectedError, bp string) { + testPrebuiltErrorWithFixture(t, expectedError, bp, nil) } func TestPrebuiltShouldNotChangePartition(t *testing.T) { @@ -559,6 +637,7 @@ func registerTestPrebuiltModules(ctx RegistrationContext) { ctx.RegisterModuleType("soong_config_module_type", SoongConfigModuleTypeFactory) ctx.RegisterModuleType("soong_config_string_variable", SoongConfigStringVariableDummyFactory) ctx.RegisterModuleType("soong_config_bool_variable", SoongConfigBoolVariableDummyFactory) + RegisterApexContributionsBuildComponents(ctx) } type prebuiltModule struct { @@ -653,3 +732,33 @@ func newOverrideSourceModule() Module { InitOverrideModule(m) return m } + +func TestPrebuiltErrorCannotListBothSourceAndPrebuiltInContributions(t *testing.T) { + selectMainlineModuleContritbutions := GroupFixturePreparers( + FixtureModifyProductVariables(func(variables FixtureProductVariables) { + variables.BuildFlags = map[string]string{ + "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_apex_contributions", + } + }), + ) + testPrebuiltErrorWithFixture(t, `Cannot use Soong module: prebuilt_foo from apex_contributions: my_apex_contributions because it has been added previously as: foo from apex_contributions: my_apex_contributions`, ` + source { + name: "foo", + } + prebuilt { + name: "foo", + srcs: ["prebuilt_file"], + } + apex_contributions { + name: "my_apex_contributions", + api_domain: "my_mainline_module", + contents: [ + "foo", + "prebuilt_foo", + ], + } + all_apex_contributions { + name: "all_apex_contributions", + } + `, selectMainlineModuleContritbutions) +} diff --git a/android/util.go b/android/util.go index 5375373a6..f687bca28 100644 --- a/android/util.go +++ b/android/util.go @@ -61,17 +61,39 @@ func JoinWithPrefix(strs []string, prefix string) string { // JoinWithPrefixAndSeparator prepends the prefix to each string in the list and // returns them joined together with the given separator. func JoinWithPrefixAndSeparator(strs []string, prefix string, sep string) string { + return JoinWithPrefixSuffixAndSeparator(strs, prefix, "", sep) +} + +// JoinWithSuffixAndSeparator appends the suffix to each string in the list and +// returns them joined together with the given separator. +func JoinWithSuffixAndSeparator(strs []string, suffix string, sep string) string { + return JoinWithPrefixSuffixAndSeparator(strs, "", suffix, sep) +} + +// JoinWithPrefixSuffixAndSeparator appends the prefix/suffix to each string in the list and +// returns them joined together with the given separator. +func JoinWithPrefixSuffixAndSeparator(strs []string, prefix, suffix, sep string) string { if len(strs) == 0 { return "" } + // Pre-calculate the length of the result + length := 0 + for _, s := range strs { + length += len(s) + } + length += (len(prefix)+len(suffix))*len(strs) + len(sep)*(len(strs)-1) + var buf strings.Builder + buf.Grow(length) buf.WriteString(prefix) buf.WriteString(strs[0]) + buf.WriteString(suffix) for i := 1; i < len(strs); i++ { buf.WriteString(sep) buf.WriteString(prefix) buf.WriteString(strs[i]) + buf.WriteString(suffix) } return buf.String() } diff --git a/android/util_test.go b/android/util_test.go index 20161e52d..699135bfc 100644 --- a/android/util_test.go +++ b/android/util_test.go @@ -811,7 +811,7 @@ func TestReverseSlice(t *testing.T) { if !reflect.DeepEqual(slice, testCase.expected) { t.Errorf("expected %#v, got %#v", testCase.expected, slice) } - if slice != nil && unsafe.SliceData(testCase.in) == unsafe.SliceData(slice) { + if cap(slice) > 0 && unsafe.SliceData(testCase.in) == unsafe.SliceData(slice) { t.Errorf("expected slices to have different backing arrays") } }) diff --git a/android/variable.go b/android/variable.go index 9896f2020..648e4cf18 100644 --- a/android/variable.go +++ b/android/variable.go @@ -492,6 +492,8 @@ type ProductVariables struct { NextReleaseHideFlaggedApi *bool `json:",omitempty"` Release_expose_flagged_api *bool `json:",omitempty"` + + BuildFlags map[string]string `json:",omitempty"` } type PartitionQualifiedVariablesType struct { diff --git a/apex/apex.go b/apex/apex.go index f2e8a0623..2f664e17a 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -3037,59 +3037,6 @@ func makeApexAvailableBaseline() map[string][]string { // // Module separator // - m["com.android.appsearch"] = []string{ - "icing-java-proto-lite", - } - // - // Module separator - // - m["com.android.btservices"] = []string{ - // empty - } - // - // Module separator - // - m["com.android.cellbroadcast"] = []string{} - // - // Module separator - // - m["com.android.extservices"] = []string{ - "ExtServices-core", - "libtextclassifier-java", - "textclassifier-statsd", - "TextClassifierNotificationLibNoManifest", - "TextClassifierServiceLibNoManifest", - } - // - // Module separator - // - m["com.android.neuralnetworks"] = []string{ - "android.hardware.neuralnetworks@1.0", - "android.hardware.neuralnetworks@1.1", - "android.hardware.neuralnetworks@1.2", - "android.hardware.neuralnetworks@1.3", - "android.hidl.allocator@1.0", - "android.hidl.memory.token@1.0", - "android.hidl.memory@1.0", - "android.hidl.safe_union@1.0", - "libarect", - "libprocpartition", - } - // - // Module separator - // - m["com.android.media"] = []string{ - // empty - } - // - // Module separator - // - m["com.android.media.swcodec"] = []string{ - // empty - } - // - // Module separator - // m["com.android.mediaprovider"] = []string{ "MediaProvider", "MediaProviderGoogle", diff --git a/apex/apex_test.go b/apex/apex_test.go index e6581cf31..ddb9a4051 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -5459,7 +5459,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { checkBootDexJarPath := func(t *testing.T, ctx *android.TestContext, stem string, bootDexJarPath string) { t.Helper() - s := ctx.ModuleForTests("platform-bootclasspath", "android_common") + s := ctx.ModuleForTests("dex_bootjars", "android_common") foundLibfooJar := false base := stem + ".jar" for _, output := range s.AllOutputs() { @@ -5909,8 +5909,8 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { ` ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment) - checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/libfoo/android_common_apex10000/hiddenapi/libfoo.jar") - checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/libbar/android_common_myapex/hiddenapi/libbar.jar") + checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/my-bootclasspath-fragment/android_common_myapex/hiddenapi-modular/encoded/libfoo.jar") + checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/my-bootclasspath-fragment/android_common_myapex/hiddenapi-modular/encoded/libbar.jar") // Verify the correct module jars contribute to the hiddenapi index file. checkHiddenAPIIndexFromClassesInputs(t, ctx, ``) diff --git a/apex/builder.go b/apex/builder.go index d75cc1df6..ba4df5f6b 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -75,9 +75,11 @@ func init() { pctx.HostBinToolVariable("apex_sepolicy_tests", "apex_sepolicy_tests") pctx.HostBinToolVariable("deapexer", "deapexer") pctx.HostBinToolVariable("debugfs_static", "debugfs_static") + pctx.HostBinToolVariable("fsck_erofs", "fsck.erofs") pctx.SourcePathVariable("genNdkUsedbyApexPath", "build/soong/scripts/gen_ndk_usedby_apex.sh") pctx.HostBinToolVariable("conv_linker_config", "conv_linker_config") pctx.HostBinToolVariable("assemble_vintf", "assemble_vintf") + pctx.HostBinToolVariable("apex_elf_checker", "apex_elf_checker") } var ( @@ -237,6 +239,12 @@ var ( CommandDeps: []string{"${assemble_vintf}"}, Description: "run assemble_vintf", }) + + apexElfCheckerUnwantedRule = pctx.StaticRule("apexElfCheckerUnwantedRule", blueprint.RuleParams{ + Command: `${apex_elf_checker} --tool_path ${tool_path} --unwanted ${unwanted} ${in} && touch ${out}`, + CommandDeps: []string{"${apex_elf_checker}", "${deapexer}", "${debugfs_static}", "${fsck_erofs}", "${config.ClangBin}/llvm-readelf"}, + Description: "run apex_elf_checker --unwanted", + }, "tool_path", "unwanted") ) // buildManifest creates buile rules to modify the input apex_manifest.json to add information @@ -364,12 +372,12 @@ func (a *apexBundle) buildFileContexts(ctx android.ModuleContext) android.Output output := android.PathForModuleOut(ctx, "file_contexts") rule := android.NewRuleBuilder(pctx, ctx) - forceLabel := "u:object_r:system_file:s0" + labelForRoot := "u:object_r:system_file:s0" + labelForManifest := "u:object_r:system_file:s0" if a.SocSpecific() && !a.vndkApex { - // APEX on /vendor should label ./ and ./apex_manifest.pb as vendor_apex_metadata_file. - // The reason why we skip VNDK APEX is that aosp_{pixel device} targets install VNDK APEX on /vendor - // even though VNDK APEX is supposed to be installed on /system. (See com.android.vndk.current.on_vendor) - forceLabel = "u:object_r:vendor_apex_metadata_file:s0" + // APEX on /vendor should label ./ and ./apex_manifest.pb as vendor file. + labelForRoot = "u:object_r:vendor_file:s0" + labelForManifest = "u:object_r:vendor_apex_metadata_file:s0" } // remove old file rule.Command().Text("rm").FlagWithOutput("-f ", output) @@ -379,8 +387,8 @@ func (a *apexBundle) buildFileContexts(ctx android.ModuleContext) android.Output rule.Command().Text("echo").Text(">>").Output(output) if !useFileContextsAsIs { // force-label /apex_manifest.pb and / - rule.Command().Text("echo").Text("/apex_manifest\\\\.pb").Text(forceLabel).Text(">>").Output(output) - rule.Command().Text("echo").Text("/").Text(forceLabel).Text(">>").Output(output) + rule.Command().Text("echo").Text("/apex_manifest\\\\.pb").Text(labelForManifest).Text(">>").Output(output) + rule.Command().Text("echo").Text("/").Text(labelForRoot).Text(">>").Output(output) } rule.Build("file_contexts."+a.Name(), "Generate file_contexts") @@ -886,6 +894,10 @@ func (a *apexBundle) buildApex(ctx android.ModuleContext) { if suffix == imageApexSuffix && ext4 == a.payloadFsType { validations = append(validations, runApexSepolicyTests(ctx, unsignedOutputFile.OutputPath)) } + if !a.testApex && len(a.properties.Unwanted_transitive_deps) > 0 { + validations = append(validations, + runApexElfCheckerUnwanted(ctx, unsignedOutputFile.OutputPath, a.properties.Unwanted_transitive_deps)) + } ctx.Build(pctx, android.BuildParams{ Rule: rule, Description: "signapk", @@ -1164,3 +1176,17 @@ func runApexSepolicyTests(ctx android.ModuleContext, apexFile android.OutputPath }) return timestamp } + +func runApexElfCheckerUnwanted(ctx android.ModuleContext, apexFile android.OutputPath, unwanted []string) android.Path { + timestamp := android.PathForModuleOut(ctx, "apex_elf_unwanted.timestamp") + ctx.Build(pctx, android.BuildParams{ + Rule: apexElfCheckerUnwantedRule, + Input: apexFile, + Output: timestamp, + Args: map[string]string{ + "unwanted": android.JoinWithSuffixAndSeparator(unwanted, ".so", ":"), + "tool_path": ctx.Config().HostToolPath(ctx, "").String() + ":${config.ClangBin}", + }, + }) + return timestamp +} diff --git a/cc/config/darwin_host.go b/cc/config/darwin_host.go index 2cabdc8ac..b7895900d 100644 --- a/cc/config/darwin_host.go +++ b/cc/config/darwin_host.go @@ -79,7 +79,7 @@ func init() { pctx.VariableFunc("macSdkRoot", func(ctx android.PackageVarContext) string { return getMacTools(ctx).sdkRoot }) - pctx.StaticVariable("macMinVersion", "10.13") + pctx.StaticVariable("macMinVersion", "10.14") pctx.VariableFunc("MacArPath", func(ctx android.PackageVarContext) string { return getMacTools(ctx).arPath }) diff --git a/cc/config/global.go b/cc/config/global.go index 892a86c7e..2ca9df9a1 100644 --- a/cc/config/global.go +++ b/cc/config/global.go @@ -174,9 +174,6 @@ var ( "-Werror=format-security", "-nostdlibinc", - // Enable MLGO for register allocation. - "-mllvm -regalloc-enable-advisor=release", - // Emit additional debug info for AutoFDO "-fdebug-info-for-profiling", } @@ -205,8 +202,6 @@ var ( "-Wl,--exclude-libs,libgcc_stripped.a", "-Wl,--exclude-libs,libunwind_llvm.a", "-Wl,--exclude-libs,libunwind.a", - // Enable MLGO for register allocation. - "-Wl,-mllvm,-regalloc-enable-advisor=release", } deviceGlobalLldflags = append(append(deviceGlobalLdflags, commonGlobalLldflags...), diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go index 9f093bb90..00a395f78 100644 --- a/cc/config/x86_64_device.go +++ b/cc/config/x86_64_device.go @@ -33,6 +33,8 @@ var ( "-Wl,--hash-style=gnu", } + X86_64Lldflags = x86_64Ldflags + x86_64ArchVariantCflags = map[string][]string{ "": []string{ "-march=x86-64", @@ -94,10 +96,23 @@ func init() { exportedVars.ExportStringListStaticVariable("X86_64ToolchainLdflags", []string{"-m64"}) exportedVars.ExportStringListStaticVariable("X86_64Ldflags", x86_64Ldflags) - exportedVars.ExportStringListStaticVariable("X86_64Lldflags", x86_64Ldflags) + exportedVars.ExportStringList("X86_64Lldflags", X86_64Lldflags) + pctx.VariableFunc("X86_64Lldflags", func(ctx android.PackageVarContext) string { + maxPageSizeFlag := "-Wl,-z,max-page-size=" + ctx.Config().MaxPageSizeSupported() + flags := append(X86_64Lldflags, maxPageSizeFlag) + return strings.Join(flags, " ") + }) // Clang cflags - exportedVars.ExportStringListStaticVariable("X86_64Cflags", x86_64Cflags) + exportedVars.ExportStringList("X86_64Cflags", x86_64Cflags) + pctx.VariableFunc("X86_64Cflags", func(ctx android.PackageVarContext) string { + flags := x86_64Cflags + if ctx.Config().PageSizeAgnostic() { + flags = append(flags, "-D__BIONIC_NO_PAGE_SIZE_MACRO") + } + return strings.Join(flags, " ") + }) + exportedVars.ExportStringListStaticVariable("X86_64Cppflags", x86_64Cppflags) // Yasm flags @@ -147,10 +147,15 @@ func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags { } } - // For ML training - if ctx.Config().IsEnvTrue("THINLTO_EMIT_INDEXES_AND_IMPORTS") { - ltoLdFlags = append(ltoLdFlags, "-Wl,--save-temps=import") - ltoLdFlags = append(ltoLdFlags, "-Wl,--thinlto-emit-index-files") + // Register allocation MLGO flags for ARM64. + if ctx.Arch().ArchType == android.Arm64 { + ltoCFlags = append(ltoCFlags, "-mllvm -regalloc-enable-advisor=release") + ltoLdFlags = append(ltoLdFlags, "-Wl,-mllvm,-regalloc-enable-advisor=release") + // Flags for training MLGO model. + if ctx.Config().IsEnvTrue("THINLTO_EMIT_INDEXES_AND_IMPORTS") { + ltoLdFlags = append(ltoLdFlags, "-Wl,--save-temps=import") + ltoLdFlags = append(ltoLdFlags, "-Wl,--thinlto-emit-index-files") + } } flags.Local.CFlags = append(flags.Local.CFlags, ltoCFlags...) diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go index 568a6f822..5abbdb7d5 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -84,7 +84,7 @@ func init() { flag.BoolVar(&cmdlineArgs.BazelMode, "bazel-mode", false, "use bazel for analysis of certain modules") flag.BoolVar(&cmdlineArgs.BazelModeStaging, "bazel-mode-staging", false, "use bazel for analysis of certain near-ready modules") flag.BoolVar(&cmdlineArgs.UseBazelProxy, "use-bazel-proxy", false, "communicate with bazel using unix socket proxy instead of spawning subprocesses") - flag.BoolVar(&cmdlineArgs.BuildFromTextStub, "build-from-text-stub", false, "build Java stubs from API text files instead of source files") + flag.BoolVar(&cmdlineArgs.BuildFromSourceStub, "build-from-source-stub", false, "build Java stubs from source files instead of API text files") flag.BoolVar(&cmdlineArgs.EnsureAllowlistIntegrity, "ensure-allowlist-integrity", false, "verify that allowlisted modules are mixed-built") // Flags that probably shouldn't be flags of soong_build, but we haven't found // the time to remove them yet diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go index 18cba776b..c94ff0721 100644 --- a/cmd/soong_ui/main.go +++ b/cmd/soong_ui/main.go @@ -182,8 +182,12 @@ func main() { CriticalPath: criticalPath, }} - config := c.config(buildCtx, args...) - config.SetLogsPrefix(c.logsPrefix) + freshConfig := func() build.Config { + config := c.config(buildCtx, args...) + config.SetLogsPrefix(c.logsPrefix) + return config + } + config := freshConfig() logsDir := config.LogsDir() buildStarted = config.BuildStartedTimeOrDefault(buildStarted) @@ -213,6 +217,15 @@ func main() { log.Verbosef(" [%d] %s", i, arg) } + // We need to call preProductConfigSetup before we can do product config, which is how we get + // PRODUCT_CONFIG_RELEASE_MAPS set for the final product config for the build. + // When product config uses a declarative language, we won't need to rerun product config. + preProductConfigSetup(buildCtx, config) + if build.SetProductReleaseConfigMaps(buildCtx, config) { + log.Verbose("Product release config maps found\n") + config = freshConfig() + } + defer func() { stat.Finish() criticalPath.WriteToMetrics(met) @@ -225,7 +238,9 @@ func main() { } -func logAndSymlinkSetup(buildCtx build.Context, config build.Config) { +// This function must not modify config, since product config may cause us to recreate the config, +// and we won't call this function a second time. +func preProductConfigSetup(buildCtx build.Context, config build.Config) { log := buildCtx.ContextImpl.Logger logsPrefix := config.GetLogsPrefix() build.SetupOutDir(buildCtx, config) @@ -311,7 +326,6 @@ func removeBadTargetRename(ctx build.Context, config build.Config) { } func dumpVar(ctx build.Context, config build.Config, args []string) { - logAndSymlinkSetup(ctx, config) flags := flag.NewFlagSet("dumpvar", flag.ExitOnError) flags.SetOutput(ctx.Writer) @@ -364,7 +378,6 @@ func dumpVar(ctx build.Context, config build.Config, args []string) { } func dumpVars(ctx build.Context, config build.Config, args []string) { - logAndSymlinkSetup(ctx, config) flags := flag.NewFlagSet("dumpvars", flag.ExitOnError) flags.SetOutput(ctx.Writer) @@ -544,7 +557,6 @@ func buildActionConfig(ctx build.Context, args ...string) build.Config { } func runMake(ctx build.Context, config build.Config, _ []string) { - logAndSymlinkSetup(ctx, config) logsDir := config.LogsDir() if config.IsVerbose() { writer := ctx.Writer @@ -680,9 +692,11 @@ func setMaxFiles(ctx build.Context) { } ctx.Verbosef("Current file limits: %d soft, %d hard", limits.Cur, limits.Max) - if limits.Cur == limits.Max { - return - } + + // Go 1.21 modifies the file limit but restores the original when + // execing subprocesses if it hasn't be overridden. Call Setrlimit + // here even if it doesn't appear to be necessary so that the + // syscall package considers it set. limits.Cur = limits.Max err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &limits) diff --git a/dexpreopt/config.go b/dexpreopt/config.go index ba41f4a66..c871e85bf 100644 --- a/dexpreopt/config.go +++ b/dexpreopt/config.go @@ -32,7 +32,7 @@ type GlobalConfig struct { DisablePreoptBootImages bool // disable prepot for boot images DisablePreoptModules []string // modules with preopt disabled by product-specific config - OnlyPreoptBootImageAndSystemServer bool // only preopt jars in the boot image or system server + OnlyPreoptArtBootImage bool // only preopt jars in the ART boot image PreoptWithUpdatableBcp bool // If updatable boot jars are included in dexpreopt or not. @@ -691,45 +691,45 @@ func (s *globalSoongConfigSingleton) MakeVars(ctx android.MakeVarsContext) { func GlobalConfigForTests(ctx android.PathContext) *GlobalConfig { return &GlobalConfig{ - DisablePreopt: false, - DisablePreoptModules: nil, - OnlyPreoptBootImageAndSystemServer: false, - HasSystemOther: false, - PatternsOnSystemOther: nil, - DisableGenerateProfile: false, - ProfileDir: "", - BootJars: android.EmptyConfiguredJarList(), - ApexBootJars: android.EmptyConfiguredJarList(), - ArtApexJars: android.EmptyConfiguredJarList(), - TestOnlyArtBootImageJars: android.EmptyConfiguredJarList(), - SystemServerJars: android.EmptyConfiguredJarList(), - SystemServerApps: nil, - ApexSystemServerJars: android.EmptyConfiguredJarList(), - StandaloneSystemServerJars: android.EmptyConfiguredJarList(), - ApexStandaloneSystemServerJars: android.EmptyConfiguredJarList(), - SpeedApps: nil, - PreoptFlags: nil, - DefaultCompilerFilter: "", - SystemServerCompilerFilter: "", - GenerateDMFiles: false, - NoDebugInfo: false, - DontResolveStartupStrings: false, - AlwaysSystemServerDebugInfo: false, - NeverSystemServerDebugInfo: false, - AlwaysOtherDebugInfo: false, - NeverOtherDebugInfo: false, - IsEng: false, - SanitizeLite: false, - DefaultAppImages: false, - Dex2oatXmx: "", - Dex2oatXms: "", - EmptyDirectory: "empty_dir", - CpuVariant: nil, - InstructionSetFeatures: nil, - BootImageProfiles: nil, - BootFlags: "", - Dex2oatImageXmx: "", - Dex2oatImageXms: "", + DisablePreopt: false, + DisablePreoptModules: nil, + OnlyPreoptArtBootImage: false, + HasSystemOther: false, + PatternsOnSystemOther: nil, + DisableGenerateProfile: false, + ProfileDir: "", + BootJars: android.EmptyConfiguredJarList(), + ApexBootJars: android.EmptyConfiguredJarList(), + ArtApexJars: android.EmptyConfiguredJarList(), + TestOnlyArtBootImageJars: android.EmptyConfiguredJarList(), + SystemServerJars: android.EmptyConfiguredJarList(), + SystemServerApps: nil, + ApexSystemServerJars: android.EmptyConfiguredJarList(), + StandaloneSystemServerJars: android.EmptyConfiguredJarList(), + ApexStandaloneSystemServerJars: android.EmptyConfiguredJarList(), + SpeedApps: nil, + PreoptFlags: nil, + DefaultCompilerFilter: "", + SystemServerCompilerFilter: "", + GenerateDMFiles: false, + NoDebugInfo: false, + DontResolveStartupStrings: false, + AlwaysSystemServerDebugInfo: false, + NeverSystemServerDebugInfo: false, + AlwaysOtherDebugInfo: false, + NeverOtherDebugInfo: false, + IsEng: false, + SanitizeLite: false, + DefaultAppImages: false, + Dex2oatXmx: "", + Dex2oatXms: "", + EmptyDirectory: "empty_dir", + CpuVariant: nil, + InstructionSetFeatures: nil, + BootImageProfiles: nil, + BootFlags: "", + Dex2oatImageXmx: "", + Dex2oatImageXms: "", } } diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go index 29ae188cd..c13e14ad2 100644 --- a/dexpreopt/dexpreopt.go +++ b/dexpreopt/dexpreopt.go @@ -124,12 +124,7 @@ func dexpreoptDisabled(ctx android.PathContext, global *GlobalConfig, module *Mo return true } - // If OnlyPreoptBootImageAndSystemServer=true and module is not in boot class path skip - // Also preopt system server jars since selinux prevents system server from loading anything from - // /data. If we don't do this they will need to be extracted which is not favorable for RAM usage - // or performance. If PreoptExtractedApk is true, we ignore the only preopt boot image options. - if global.OnlyPreoptBootImageAndSystemServer && !global.BootJars.ContainsJar(module.Name) && - !global.AllSystemServerJars(ctx).ContainsJar(module.Name) && !module.PreoptExtractedApk { + if global.OnlyPreoptArtBootImage && !module.PreoptExtractedApk { return true } diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go index 275d9c3ff..b7d29710d 100644 --- a/etc/prebuilt_etc.go +++ b/etc/prebuilt_etc.go @@ -150,8 +150,9 @@ type PrebuiltEtc struct { sourceFilePath android.Path outputFilePath android.OutputPath // The base install location, e.g. "etc" for prebuilt_etc, "usr/share" for prebuilt_usr_share. - installDirBase string - installDirBase64 string + installDirBase string + installDirBase64 string + installAvoidMultilibConflict bool // The base install location when soc_specific property is set to true, e.g. "firmware" for // prebuilt_firmware. socInstallDirBase string @@ -355,6 +356,10 @@ func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) { if p.SocSpecific() && p.socInstallDirBase != "" { installBaseDir = p.socInstallDirBase } + if p.installAvoidMultilibConflict && !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) { + installBaseDir = filepath.Join(installBaseDir, ctx.Arch().ArchType.String()) + } + p.installDirPath = android.PathForModuleInstall(ctx, installBaseDir, p.SubDir()) // Call InstallFile even when uninstallable to make the module included in the package @@ -590,6 +595,7 @@ func PrebuiltRenderScriptBitcodeFactory() android.Module { module := &PrebuiltEtc{} module.makeClass = "RENDERSCRIPT_BITCODE" module.installDirBase64 = "lib64" + module.installAvoidMultilibConflict = true InitPrebuiltEtcModule(module, "lib") // This module is device-only android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth) diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index f2efd463f..3d491145b 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -350,13 +350,16 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (propFile android. addStr("avb_algorithm", algorithm) key := android.PathForModuleSrc(ctx, proptools.String(f.properties.Avb_private_key)) addPath("avb_key_path", key) + partitionName := proptools.StringDefault(f.properties.Partition_name, f.Name()) + addStr("partition_name", partitionName) avb_add_hashtree_footer_args := "--do_not_generate_fec" if hashAlgorithm := proptools.String(f.properties.Avb_hash_algorithm); hashAlgorithm != "" { avb_add_hashtree_footer_args += " --hash_algorithm " + hashAlgorithm } + securityPatchKey := "com.android.build." + partitionName + ".security_patch" + securityPatchValue := ctx.Config().PlatformSecurityPatch() + avb_add_hashtree_footer_args += " --prop " + securityPatchKey + ":" + securityPatchValue addStr("avb_add_hashtree_footer_args", avb_add_hashtree_footer_args) - partitionName := proptools.StringDefault(f.properties.Partition_name, f.Name()) - addStr("partition_name", partitionName) addStr("avb_salt", f.salt()) } diff --git a/genrule/allowlists.go b/genrule/allowlists.go index 9cc98f57a..cae839ea3 100644 --- a/genrule/allowlists.go +++ b/genrule/allowlists.go @@ -18,31 +18,6 @@ var ( DepfileAllowList = []string{ // go/keep-sorted start "depfile_allowed_for_test", - "gen_uwb_core_proto", - "libtextclassifier_fbgen_actions_actions-entity-data", - "libtextclassifier_fbgen_actions_actions_model", - "libtextclassifier_fbgen_annotator_datetime_datetime", - "libtextclassifier_fbgen_annotator_entity-data", - "libtextclassifier_fbgen_annotator_experimental_experimental", - "libtextclassifier_fbgen_annotator_model", - "libtextclassifier_fbgen_annotator_person_name_person_name_model", - "libtextclassifier_fbgen_lang_id_common_flatbuffers_embedding-network", - "libtextclassifier_fbgen_lang_id_common_flatbuffers_model", - "libtextclassifier_fbgen_utils_codepoint-range", - "libtextclassifier_fbgen_utils_container_bit-vector", - "libtextclassifier_fbgen_utils_flatbuffers_flatbuffers", - "libtextclassifier_fbgen_utils_flatbuffers_flatbuffers_test", - "libtextclassifier_fbgen_utils_grammar_rules", - "libtextclassifier_fbgen_utils_grammar_semantics_expression", - "libtextclassifier_fbgen_utils_grammar_testing_value", - "libtextclassifier_fbgen_utils_i18n_language-tag", - "libtextclassifier_fbgen_utils_intents_intent-config", - "libtextclassifier_fbgen_utils_lua_utils_tests", - "libtextclassifier_fbgen_utils_normalization", - "libtextclassifier_fbgen_utils_resources", - "libtextclassifier_fbgen_utils_tflite_text_encoder_config", - "libtextclassifier_fbgen_utils_tokenizer", - "libtextclassifier_fbgen_utils_zlib_buffer", "tflite_support_metadata_schema", "tflite_support_spm_config", "tflite_support_spm_encoder_config", @@ -51,18 +26,15 @@ var ( SandboxingDenyModuleList = []string{ // go/keep-sorted start - "CompilationTestCases_package-dex-usage", "ControlEnvProxyServerProto_cc", "ControlEnvProxyServerProto_h", "CtsApkVerityTestDebugFiles", "FrontendStub_cc", "FrontendStub_h", - "HeadlessBuildTimestamp", "ImageProcessing-rscript", "ImageProcessing2-rscript", "ImageProcessingJB-rscript", "MultiDexLegacyTestApp_genrule", - "PackageManagerServiceServerTests_apks_as_resources", "PacketStreamerStub_cc", "PacketStreamerStub_h", "RSTest-rscript", @@ -86,18 +58,13 @@ var ( "android-support-multidex-instrumentation-version", "android-support-multidex-version", "angle_commit_id", - "apexer_test_host_tools", "atest_integration_fake_src", - "authfs_test_apk_assets", "awkgram.tab.h", - "bluetooth_core_rust_packets", "c2hal_test_genc++", "c2hal_test_genc++_headers", "camera-its", "checkIn-service-stub-lite", "chre_atoms_log.h", - "common-profile-text-protos", - "core-tests-smali-dex", "cronet_aml_base_android_runtime_jni_headers", "cronet_aml_base_android_runtime_jni_headers__testing", "cronet_aml_base_android_runtime_unchecked_jni_headers", @@ -110,97 +77,32 @@ var ( "fdt_test_tree_empty_memory_range_dtb", "fdt_test_tree_multiple_memory_ranges_dtb", "fdt_test_tree_one_memory_range_dtb", - "futility_cmds", - "gd_hci_packets_python3_gen", - "gd_smp_packets_python3_gen", "gen_corrupt_rebootless_apex", - "gen_corrupt_superblock_apex", "gen_key_mismatch_capex", - "gen_manifest_mismatch_apex_no_hashtree", - "generate_hash_v1", "gles1_core_functions_hdr", "gles1_extensions_functions_hdr", "gles2_core_functions_hdr", "gles2_extensions_functions_hdr", "gles31_only_functions_hdr", "gles3_only_functions_hdr", - "hci_packets_python3_gen", - "hidl2aidl_test_gen_aidl", - "hidl2aidl_translate_cpp_test_gen_headers", - "hidl2aidl_translate_cpp_test_gen_src", - "hidl2aidl_translate_java_test_gen_src", - "hidl2aidl_translate_ndk_test_gen_headers", - "hidl2aidl_translate_ndk_test_gen_src", - "hidl_cpp_impl_test_gen-headers", - "hidl_cpp_impl_test_gen-sources", - "hidl_error_test_gen", - "hidl_export_test_gen-headers", - "hidl_format_test_diff", - "hidl_hash_test_gen", - "hidl_hash_version_gen", - "hidl_java_impl_test_gen", - "lib-test-profile-text-protos", "libbssl_sys_src_nostd", "libc_musl_sysroot_bits", "libchrome-crypto-include", "libchrome-include", "libcore-non-cts-tests-txt", - "libmojo_jni_headers", "libxml2_schema_fuzz_corpus", "libxml2_xml_fuzz_corpus", - "link_layer_packets_python3_gen", - "llcp_packets_python3_gen", - "measure_io_as_jar", - "nos_app_avb_service_genc++", - "nos_app_avb_service_genc++_headers", - "nos_app_avb_service_genc++_mock", - "nos_app_identity_service_genc++", - "nos_app_identity_service_genc++_headers", - "nos_app_identity_service_genc++_mock", - "nos_app_keymaster_service_genc++", - "nos_app_keymaster_service_genc++_headers", - "nos_app_keymaster_service_genc++_mock", - "nos_app_weaver_service_genc++", - "nos_app_weaver_service_genc++_headers", - "nos_app_weaver_service_genc++_mock", - "nos_generator_test_service_genc++", - "nos_generator_test_service_genc++_headers", - "nos_generator_test_service_genc++_mock", - "openwrt_rootfs_combined_aarch64", - "openwrt_rootfs_combined_x86_64", - "openwrt_rootfs_customization_aarch64", - "openwrt_rootfs_customization_x86_64", - "pandora-python-gen-src", - "pdl_cxx_canonical_be_src_gen", - "pdl_cxx_canonical_be_test_gen", - "pdl_cxx_canonical_le_src_gen", - "pdl_cxx_canonical_le_test_gen", - "pdl_python_generator_be_test_gen", - "pdl_python_generator_le_test_gen", - "pdl_rust_noalloc_le_test_backend_srcs", - "pdl_rust_noalloc_le_test_gen_harness", "pixelatoms_defs.h", "pixelstatsatoms.cpp", "pixelstatsatoms.h", "pvmfw_fdt_template_rs", "r8retrace-dexdump-sample-app", "r8retrace-run-retrace", - "rootcanal_bredr_bb_packets_cxx_gen", - "rootcanal_hci_packets_cxx_gen", - "rootcanal_link_layer_packets_cxx_gen", - "sample-profile-text-protos", "seller-frontend-service-stub-lite", - "services.core.protologsrc", - "statsd-config-protos", "swiftshader_spvtools_update_build_version", - "temp_layoutlib", "ue_unittest_erofs_imgs", - "uwb_core_artifacts", "vm-tests-tf-lib", "vndk_abi_dump_zip", - "vts_vndk_abi_dump_zip", - "wm_shell_protolog_src", - "wmtests.protologsrc", // go/keep-sorted end } diff --git a/java/app.go b/java/app.go index 7c2cc3720..41848ce0b 100755 --- a/java/app.go +++ b/java/app.go @@ -1586,7 +1586,7 @@ func (u *usesLibrary) verifyUsesLibraries(ctx android.ModuleContext, inputFile a // non-linux build platforms where dexpreopt is generally disabled (the check may fail due to // various unrelated reasons, such as a failure to get manifest from an APK). global := dexpreopt.GetGlobalConfig(ctx) - if global.DisablePreopt || global.OnlyPreoptBootImageAndSystemServer { + if global.DisablePreopt || global.OnlyPreoptArtBootImage { return inputFile } diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index 2433530c9..ea3fc9dbb 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -584,7 +584,7 @@ func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext) // So ignore it even if it is not in PRODUCT_APEX_BOOT_JARS. // TODO(b/202896428): Add better way to handle this. _, unknown = android.RemoveFromList("android.car-module", unknown) - if len(unknown) > 0 { + if isActiveModule(ctx.Module()) && len(unknown) > 0 { ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown) } } diff --git a/java/config/droidstubs.go b/java/config/droidstubs.go index 59cee1d61..b7aab5a98 100644 --- a/java/config/droidstubs.go +++ b/java/config/droidstubs.go @@ -24,8 +24,6 @@ var ( "--repeat-errors-max 10", "--hide UnresolvedImport", "--hide InvalidNullabilityOverride", - // b/223382732 - "--hide ChangedDefault", // Force metalava to ignore classes on the classpath when an API file contains missing classes. // See b/285140653 for more information. @@ -54,8 +52,6 @@ var ( "--hide AnnotationExtraction", // b/222738070 "--hide BannedThrow", - // b/223382732 - "--hide ChangedDefault", } MetalavaAnnotationsWarningsFlags = strings.Join(metalavaAnnotationsWarningsFlags, " ") diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index c0f73afc5..5fb36df6d 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -610,7 +610,8 @@ func generateBootImage(ctx android.ModuleContext, imageConfig *bootImageConfig) profile := bootImageProfileRule(ctx, imageConfig) // If dexpreopt of boot image jars should be skipped, stop after generating a profile. - if SkipDexpreoptBootJars(ctx) { + global := dexpreopt.GetGlobalConfig(ctx) + if SkipDexpreoptBootJars(ctx) || (global.OnlyPreoptArtBootImage && imageConfig.name != "art") { return } diff --git a/java/dexpreopt_check.go b/java/dexpreopt_check.go index 7499481de..33be60352 100644 --- a/java/dexpreopt_check.go +++ b/java/dexpreopt_check.go @@ -68,7 +68,7 @@ func (m *dexpreoptSystemserverCheck) GenerateAndroidBuildActions(ctx android.Mod // The check should be skipped on unbundled builds because system server jars are not preopted on // unbundled builds since the artifacts are installed into the system image, not the APEXes. - if global.DisablePreopt || len(targets) == 0 || ctx.Config().UnbundledBuild() { + if global.DisablePreopt || global.OnlyPreoptArtBootImage || len(targets) == 0 || ctx.Config().UnbundledBuild() { return } diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go index 29551efcc..2bd696c3d 100644 --- a/java/dexpreopt_config.go +++ b/java/dexpreopt_config.go @@ -210,57 +210,18 @@ func isProfileProviderApex(ctx android.PathContext, apexName string) bool { return false } -// Apex boot config allows to access build/install paths of apex boot jars without going -// through the usual trouble of registering dependencies on those modules and extracting build paths -// from those dependencies. -type apexBootConfig struct { - // A list of apex boot jars. - modules android.ConfiguredJarList - - // A list of predefined build paths to apex boot jars. They are configured very early, - // before the modules for these jars are processed and the actual paths are generated, and - // later on a singleton adds commands to copy actual jars to the predefined paths. - dexPaths android.WritablePaths - - // Map from module name (without prebuilt_ prefix) to the predefined build path. - dexPathsByModule map[string]android.WritablePath - - // A list of dex locations (a.k.a. on-device paths) to the boot jars. - dexLocations []string -} - -var updatableBootConfigKey = android.NewOnceKey("apexBootConfig") - -// Returns apex boot config. -func GetApexBootConfig(ctx android.PathContext) apexBootConfig { - return ctx.Config().Once(updatableBootConfigKey, func() interface{} { - apexBootJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars - dir := android.PathForOutput(ctx, getDexpreoptDirName(ctx), "apex_bootjars") - dexPaths := apexBootJars.BuildPaths(ctx, dir) - dexPathsByModuleName := apexBootJars.BuildPathsByModule(ctx, dir) - - dexLocations := apexBootJars.DevicePaths(ctx.Config(), android.Android) - - return apexBootConfig{apexBootJars, dexPaths, dexPathsByModuleName, dexLocations} - }).(apexBootConfig) -} - // Returns a list of paths and a list of locations for the boot jars used in dexpreopt (to be // passed in -Xbootclasspath and -Xbootclasspath-locations arguments for dex2oat). func bcpForDexpreopt(ctx android.PathContext, withUpdatable bool) (android.WritablePaths, []string) { - // Non-updatable boot jars (they are used both in the boot image and in dexpreopt). bootImage := defaultBootImageConfig(ctx) + if withUpdatable { + bootImage = mainlineBootImageConfig(ctx) + } + dexPaths := bootImage.dexPathsDeps // The dex locations for all Android variants are identical. dexLocations := bootImage.getAnyAndroidVariant().dexLocationsDeps - if withUpdatable { - // Apex boot jars (they are used only in dexpreopt, but not in the boot image). - apexBootConfig := GetApexBootConfig(ctx) - dexPaths = append(dexPaths, apexBootConfig.dexPaths...) - dexLocations = append(dexLocations, apexBootConfig.dexLocations...) - } - return dexPaths, dexLocations } diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index 02a2298cd..0d52614ea 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -202,8 +202,6 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo bootDexJarByModule := b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments) buildRuleForBootJarsPackageCheck(ctx, bootDexJarByModule) - - b.copyApexBootJarsForAppsDexpreopt(ctx, apexModules) } // Generate classpaths.proto config @@ -415,10 +413,3 @@ func (b *platformBootclasspathModule) generateHiddenApiMakeVars(ctx android.Make // INTERNAL_PLATFORM_HIDDENAPI_FLAGS is used by Make rules in art/ and cts/. ctx.Strict("INTERNAL_PLATFORM_HIDDENAPI_FLAGS", b.hiddenAPIFlagsCSV.String()) } - -// Copy apex module dex jars to their predefined locations. They will be used for dexpreopt for apps. -func (b *platformBootclasspathModule) copyApexBootJarsForAppsDexpreopt(ctx android.ModuleContext, apexModules []android.Module) { - config := GetApexBootConfig(ctx) - apexBootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, apexModules) - copyBootJarsToPredefinedLocations(ctx, apexBootDexJarsByModule, config.dexPathsByModule) -} diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go index 21f0bab37..82f8a4d50 100644 --- a/java/sdk_library_test.go +++ b/java/sdk_library_test.go @@ -1068,6 +1068,137 @@ func TestJavaSdkLibraryImport_Preferred(t *testing.T) { }) } +// If a module is listed in `mainline_module_contributions, it should be used +// It will supersede any other source vs prebuilt selection mechanism like `prefer` attribute +func TestSdkLibraryImport_MetadataModuleSupersedesPreferred(t *testing.T) { + bp := ` + apex_contributions { + name: "my_mainline_module_contributions", + api_domain: "my_mainline_module", + contents: [ + // legacy mechanism prefers the prebuilt + // mainline_module_contributions supersedes this since source is listed explicitly + "sdklib.prebuilt_preferred_using_legacy_flags", + + // legacy mechanism prefers the source + // mainline_module_contributions supersedes this since prebuilt is listed explicitly + "prebuilt_sdklib.source_preferred_using_legacy_flags", + ], + } + all_apex_contributions { + name: "all_apex_contributions", + } + java_sdk_library { + name: "sdklib.prebuilt_preferred_using_legacy_flags", + srcs: ["a.java"], + sdk_version: "none", + system_modules: "none", + public: { + enabled: true, + }, + system: { + enabled: true, + } + } + java_sdk_library_import { + name: "sdklib.prebuilt_preferred_using_legacy_flags", + prefer: true, // prebuilt is preferred using legacy mechanism + public: { + jars: ["a.jar"], + stub_srcs: ["a.java"], + current_api: "current.txt", + removed_api: "removed.txt", + annotations: "annotations.zip", + }, + system: { + jars: ["a.jar"], + stub_srcs: ["a.java"], + current_api: "current.txt", + removed_api: "removed.txt", + annotations: "annotations.zip", + }, + } + java_sdk_library { + name: "sdklib.source_preferred_using_legacy_flags", + srcs: ["a.java"], + sdk_version: "none", + system_modules: "none", + public: { + enabled: true, + }, + system: { + enabled: true, + } + } + java_sdk_library_import { + name: "sdklib.source_preferred_using_legacy_flags", + prefer: false, // source is preferred using legacy mechanism + public: { + jars: ["a.jar"], + stub_srcs: ["a.java"], + current_api: "current.txt", + removed_api: "removed.txt", + annotations: "annotations.zip", + }, + system: { + jars: ["a.jar"], + stub_srcs: ["a.java"], + current_api: "current.txt", + removed_api: "removed.txt", + annotations: "annotations.zip", + }, + } + + // rdeps + java_library { + name: "public", + srcs: ["a.java"], + libs: [ + // this should get source since source is listed in my_mainline_module_contributions + "sdklib.prebuilt_preferred_using_legacy_flags.stubs", + "sdklib.prebuilt_preferred_using_legacy_flags.stubs.system", + + // this should get prebuilt since source is listed in my_mainline_module_contributions + "sdklib.source_preferred_using_legacy_flags.stubs", + "sdklib.source_preferred_using_legacy_flags.stubs.system", + + ], + } + ` + result := android.GroupFixturePreparers( + prepareForJavaTest, + PrepareForTestWithJavaSdkLibraryFiles, + FixtureWithLastReleaseApis("sdklib.source_preferred_using_legacy_flags", "sdklib.prebuilt_preferred_using_legacy_flags"), + android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) { + android.RegisterApexContributionsBuildComponents(ctx) + }), + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.BuildFlags = map[string]string{ + "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_mainline_module_contributions", + } + }), + ).RunTestWithBp(t, bp) + + // Make sure that rdeps get the correct source vs prebuilt based on mainline_module_contributions + public := result.ModuleForTests("public", "android_common") + rule := public.Output("javac/public.jar") + inputs := rule.Implicits.Strings() + expectedInputs := []string{ + // source + "out/soong/.intermediates/sdklib.prebuilt_preferred_using_legacy_flags.stubs/android_common/turbine-combined/sdklib.prebuilt_preferred_using_legacy_flags.stubs.jar", + "out/soong/.intermediates/sdklib.prebuilt_preferred_using_legacy_flags.stubs.system/android_common/turbine-combined/sdklib.prebuilt_preferred_using_legacy_flags.stubs.system.jar", + + // prebuilt + "out/soong/.intermediates/prebuilt_sdklib.source_preferred_using_legacy_flags.stubs/android_common/combined/sdklib.source_preferred_using_legacy_flags.stubs.jar", + "out/soong/.intermediates/prebuilt_sdklib.source_preferred_using_legacy_flags.stubs.system/android_common/combined/sdklib.source_preferred_using_legacy_flags.stubs.system.jar", + } + for _, expected := range expectedInputs { + if !android.InList(expected, inputs) { + t.Errorf("expected %q to contain %q", inputs, expected) + } + } +} + func TestJavaSdkLibraryEnforce(t *testing.T) { partitionToBpOption := func(partition string) string { switch partition { diff --git a/scripts/build-ndk-prebuilts.sh b/scripts/build-ndk-prebuilts.sh index 0d14019a5..ef0f44a7c 100755 --- a/scripts/build-ndk-prebuilts.sh +++ b/scripts/build-ndk-prebuilts.sh @@ -19,9 +19,11 @@ if [ -z "${OUT_DIR}" ]; then exit 1 fi +# Note: NDK doesn't support flagging APIs, so we hardcode it to trunk_staging. # TODO: remove ALLOW_MISSING_DEPENDENCIES=true when all the riscv64 # dependencies exist (currently blocked by http://b/273792258). # TODO: remove BUILD_BROKEN_DISABLE_BAZEL=1 when bazel supports riscv64 (http://b/262192655). +TARGET_RELEASE=trunk_staging \ ALLOW_MISSING_DEPENDENCIES=true \ BUILD_BROKEN_DISABLE_BAZEL=1 \ TARGET_PRODUCT=ndk build/soong/soong_ui.bash --make-mode --soong-only ${OUT_DIR}/soong/ndk.timestamp diff --git a/scripts/conv_linker_config.py b/scripts/conv_linker_config.py index c6e6e306f..ed3fbb79f 100644 --- a/scripts/conv_linker_config.py +++ b/scripts/conv_linker_config.py @@ -149,6 +149,11 @@ def Validate(args): else: sys.exit(f'Unknown type: {args.type}') + # Reject contributions field at build time while keeping the runtime behavior for GRF. + if getattr(pb, 'contributions'): + sys.exit(f"{args.input}: 'contributions' is set. " + "It's deprecated. Instead, make the APEX 'visible' and use android_dlopen_ext().") + def ValidateAndWriteAsPbFile(pb, output_path): ValidateConfiguration(pb) diff --git a/ui/build/config.go b/ui/build/config.go index c33312be0..d345415b5 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -31,6 +31,7 @@ import ( "time" "android/soong/shared" + "android/soong/ui/metrics" "google.golang.org/protobuf/proto" @@ -85,7 +86,7 @@ type configImpl struct { searchApiDir bool // Scan the Android.bp files generated in out/api_surfaces skipMetricsUpload bool buildStartedTime int64 // For metrics-upload-only - manually specify a build-started time - buildFromTextStub bool + buildFromSourceStub bool ensureAllowlistIntegrity bool // For CI builds - make sure modules are mixed-built bazelExitCode int32 // For b runs - necessary for updating NonZeroExit besId string // For b runs, to identify the BuildEventService logs @@ -461,6 +462,42 @@ func NewBuildActionConfig(action BuildAction, dir string, ctx Context, args ...s return NewConfig(ctx, getConfigArgs(action, dir, ctx, args)...) } +// Prepare for getting make variables. For them to be accurate, we need to have +// obtained PRODUCT_RELEASE_CONFIG_MAPS. +// +// Returns: +// +// Whether config should be called again. +// +// TODO: when converting product config to a declarative language, make sure +// that PRODUCT_RELEASE_CONFIG_MAPS is properly handled as a separate step in +// that process. +func SetProductReleaseConfigMaps(ctx Context, config Config) bool { + ctx.BeginTrace(metrics.RunKati, "SetProductReleaseConfigMaps") + defer ctx.EndTrace() + + if config.SkipConfig() { + // This duplicates the logic from Build to skip product config + // if the user has explicitly said to. + return false + } + + releaseConfigVars := []string{ + "PRODUCT_RELEASE_CONFIG_MAPS", + } + + origValue, _ := config.environ.Get("PRODUCT_RELEASE_CONFIG_MAPS") + // Get the PRODUCT_RELEASE_CONFIG_MAPS for this product, to avoid polluting the environment + // when we run product config to get the rest of the make vars. + releaseMapVars, err := dumpMakeVars(ctx, config, nil, releaseConfigVars, false, "") + if err != nil { + ctx.Fatalln("Error getting PRODUCT_RELEASE_CONFIG_MAPS:", err) + } + productReleaseConfigMaps := releaseMapVars["PRODUCT_RELEASE_CONFIG_MAPS"] + os.Setenv("PRODUCT_RELEASE_CONFIG_MAPS", productReleaseConfigMaps) + return origValue != productReleaseConfigMaps +} + // storeConfigMetrics selects a set of configuration information and store in // the metrics system for further analysis. func storeConfigMetrics(ctx Context, config Config) { @@ -783,8 +820,8 @@ func (c *configImpl) parseArgs(ctx Context, args []string) { } else { ctx.Fatalf("unknown option for ninja_weight_source: %s", source) } - } else if arg == "--build-from-text-stub" { - c.buildFromTextStub = true + } else if arg == "--build-from-source-stub" { + c.buildFromSourceStub = true } else if strings.HasPrefix(arg, "--build-command=") { buildCmd := strings.TrimPrefix(arg, "--build-command=") // remove quotations @@ -1119,7 +1156,7 @@ func (c *configImpl) SkipConfig() bool { } func (c *configImpl) BuildFromTextStub() bool { - return c.buildFromTextStub + return !c.buildFromSourceStub } func (c *configImpl) TargetProduct() string { diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go index efe747819..d364542c5 100644 --- a/ui/build/dumpvars.go +++ b/ui/build/dumpvars.go @@ -191,6 +191,9 @@ func runMakeProductConfig(ctx Context, config Config) { "TARGET_BUILD_APPS", "TARGET_BUILD_UNBUNDLED", + // Additional release config maps + "PRODUCT_RELEASE_CONFIG_MAPS", + // compiler wrappers set up by make "CC_WRAPPER", "CXX_WRAPPER", diff --git a/ui/build/soong.go b/ui/build/soong.go index 90f1798f3..667f0c90b 100644 --- a/ui/build/soong.go +++ b/ui/build/soong.go @@ -193,8 +193,8 @@ func (pb PrimaryBuilderFactory) primaryBuilderInvocation() bootstrap.PrimaryBuil if pb.config.multitreeBuild { commonArgs = append(commonArgs, "--multitree-build") } - if pb.config.buildFromTextStub { - commonArgs = append(commonArgs, "--build-from-text-stub") + if pb.config.buildFromSourceStub { + commonArgs = append(commonArgs, "--build-from-source-stub") } commonArgs = append(commonArgs, "-l", filepath.Join(pb.config.FileListDir(), "Android.bp.list")) @@ -310,8 +310,8 @@ func bootstrapBlueprint(ctx Context, config Config) { if config.MultitreeBuild() { mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--multitree-build") } - if config.buildFromTextStub { - mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--build-from-text-stub") + if config.buildFromSourceStub { + mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--build-from-source-stub") } if config.ensureAllowlistIntegrity { mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--ensure-allowlist-integrity") |