Merge "Make null builds always be null builds."
diff --git a/dexpreopt/testing.go b/dexpreopt/testing.go
index 8e90295..4801482 100644
--- a/dexpreopt/testing.go
+++ b/dexpreopt/testing.go
@@ -15,39 +15,78 @@
 package dexpreopt
 
 import (
+	"fmt"
+
 	"android/soong/android"
 )
 
-type dummyToolBinary struct {
+type fakeToolBinary struct {
 	android.ModuleBase
 }
 
-func (m *dummyToolBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {}
+func (m *fakeToolBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {}
 
-func (m *dummyToolBinary) HostToolPath() android.OptionalPath {
+func (m *fakeToolBinary) HostToolPath() android.OptionalPath {
 	return android.OptionalPathForPath(android.PathForTesting("dex2oat"))
 }
 
-func dummyToolBinaryFactory() android.Module {
-	module := &dummyToolBinary{}
+func fakeToolBinaryFactory() android.Module {
+	module := &fakeToolBinary{}
 	android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
 	return module
 }
 
 func RegisterToolModulesForTest(ctx android.RegistrationContext) {
-	ctx.RegisterModuleType("dummy_tool_binary", dummyToolBinaryFactory)
+	ctx.RegisterModuleType("fake_tool_binary", fakeToolBinaryFactory)
 }
 
 func BpToolModulesForTest() string {
 	return `
-		dummy_tool_binary {
+		fake_tool_binary {
 			name: "dex2oatd",
 		}
 	`
 }
 
-// Prepares a test fixture by enabling dexpreopt.
-var PrepareForTestWithDexpreopt = FixtureModifyGlobalConfig(func(*GlobalConfig) {})
+func CompatLibDefinitionsForTest() string {
+	bp := ""
+
+	// For class loader context and <uses-library> tests.
+	dexpreoptModules := []string{"android.test.runner"}
+	dexpreoptModules = append(dexpreoptModules, CompatUsesLibs...)
+	dexpreoptModules = append(dexpreoptModules, OptionalCompatUsesLibs...)
+
+	for _, extra := range dexpreoptModules {
+		bp += fmt.Sprintf(`
+			java_library {
+				name: "%s",
+				srcs: ["a.java"],
+				sdk_version: "none",
+				system_modules: "stable-core-platform-api-stubs-system-modules",
+				compile_dex: true,
+				installable: true,
+			}
+		`, extra)
+	}
+
+	return bp
+}
+
+var PrepareForTestWithDexpreoptCompatLibs = android.GroupFixturePreparers(
+	android.FixtureAddFile("defaults/dexpreopt/compat/a.java", nil),
+	android.FixtureAddTextFile("defaults/dexpreopt/compat/Android.bp", CompatLibDefinitionsForTest()),
+)
+
+var PrepareForTestWithFakeDex2oatd = android.GroupFixturePreparers(
+	android.FixtureRegisterWithContext(RegisterToolModulesForTest),
+	android.FixtureAddTextFile("defaults/dexpreopt/Android.bp", BpToolModulesForTest()),
+)
+
+// Prepares a test fixture by enabling dexpreopt, registering the fake_tool_binary module type and
+// using that to define the `dex2oatd` module.
+var PrepareForTestByEnablingDexpreopt = android.GroupFixturePreparers(
+	FixtureModifyGlobalConfig(func(*GlobalConfig) {}),
+)
 
 // FixtureModifyGlobalConfig enables dexpreopt (unless modified by the mutator) and modifies the
 // configuration.
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index e94b20c..17499ee 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -15,6 +15,7 @@
 package java
 
 import (
+	"fmt"
 	"path/filepath"
 	"sort"
 	"strings"
@@ -449,46 +450,61 @@
 // be needed there too.
 //
 // TODO(b/177892522): Avoid having to perform this type of check or if necessary dedup it.
-func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, module android.Module) (int, android.Path) {
+func getBootJar(ctx android.SingletonContext, bootjars android.ConfiguredJarList,
+	module android.Module, fromWhere string) (int, android.Path, *android.ApexInfo) {
+
 	name := ctx.ModuleName(module)
 
 	// Strip a prebuilt_ prefix so that this can access the dex jar from a prebuilt module.
 	name = android.RemoveOptionalPrebuiltPrefix(name)
 
 	// Ignore any module that is not listed in the boot image configuration.
-	index := image.modules.IndexOfJar(name)
+	index := bootjars.IndexOfJar(name)
 	if index == -1 {
-		return -1, nil
+		return -1, nil, nil
 	}
 
 	// It is an error if a module configured in the boot image does not support accessing the dex jar.
 	// This is safe because every module that has the same name has to have the same module type.
 	jar, hasJar := module.(interface{ DexJarBuildPath() android.Path })
 	if !hasJar {
-		ctx.Errorf("module %q configured in boot image %q does not support accessing dex jar", module, image.name)
-		return -1, nil
+		ctx.Errorf("module %q %sdoes not support accessing dex jar", module, fromWhere)
+		return -1, nil, nil
 	}
 
 	// It is also an error if the module is not an ApexModule.
 	if _, ok := module.(android.ApexModule); !ok {
-		ctx.Errorf("module %q configured in boot image %q does not support being added to an apex", module, image.name)
-		return -1, nil
+		ctx.Errorf("module %q %sdoes not support being added to an apex", module, fromWhere)
+		return -1, nil, nil
 	}
 
 	apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
 
 	// Now match the apex part of the boot image configuration.
-	requiredApex := image.modules.Apex(index)
+	requiredApex := bootjars.Apex(index)
 	if requiredApex == "platform" {
 		if len(apexInfo.InApexes) != 0 {
 			// A platform variant is required but this is for an apex so ignore it.
-			return -1, nil
+			return -1, nil, nil
 		}
 	} else if !apexInfo.InApexByBaseName(requiredApex) {
 		// An apex variant for a specific apex is required but this is the wrong apex.
+		return -1, nil, nil
+	}
+
+	return index, jar.DexJarBuildPath(), &apexInfo
+}
+
+// Inspect this module to see if it contains a bootclasspath dex jar from a given boot image.
+func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, module android.Module) (int, android.Path) {
+	fromImage := fmt.Sprintf("configured in boot image %q ", image.name)
+	index, jarPath, apexInfo := getBootJar(ctx, image.modules, module, fromImage)
+	if index == -1 {
 		return -1, nil
 	}
 
+	name := ctx.ModuleName(module)
+
 	// Check that this module satisfies any boot image specific constraints.
 	fromUpdatableApex := apexInfo.Updatable
 
@@ -525,39 +541,40 @@
 		panic("unknown boot image: " + image.name)
 	}
 
-	return index, jar.DexJarBuildPath()
+	return index, jarPath
 }
 
-// buildBootImage takes a bootImageConfig, creates rules to build it, and returns the image.
-func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootImageConfig {
-	// Collect dex jar paths for the boot image modules.
+// Generate commands that will copy boot jars to predefined paths in the global config.
+func findAndCopyBootJars(ctx android.SingletonContext, bootjars android.ConfiguredJarList,
+	jarPathsPredefined android.WritablePaths,
+	getBootJar func(module android.Module) (int, android.Path)) []string {
+
 	// This logic is tested in the apex package to avoid import cycle apex <-> java.
-	bootDexJars := make(android.Paths, image.modules.Len())
+	jarPaths := make(android.Paths, bootjars.Len())
 
 	ctx.VisitAllModules(func(module android.Module) {
 		if !isActiveModule(module) {
 			return
 		}
-
-		if i, j := getBootImageJar(ctx, image, module); i != -1 {
-			if existing := bootDexJars[i]; existing != nil {
-				ctx.Errorf("Multiple dex jars found for %s:%s - %s and %s",
-					image.modules.Apex(i), image.modules.Jar(i), existing, j)
+		if i, j := getBootJar(module); i != -1 {
+			if existing := jarPaths[i]; existing != nil {
+				ctx.Errorf("Multiple dex jars found for %s:%s - %q and %q",
+					bootjars.Apex(i), bootjars.Jar(i), existing, j)
 				return
 			}
-
-			bootDexJars[i] = j
+			jarPaths[i] = j
 		}
 	})
 
 	var missingDeps []string
 	// Ensure all modules were converted to paths
-	for i := range bootDexJars {
-		if bootDexJars[i] == nil {
-			m := image.modules.Jar(i)
+	for i := range jarPaths {
+		if jarPaths[i] == nil {
+			m := bootjars.Jar(i)
 			if ctx.Config().AllowMissingDependencies() {
 				missingDeps = append(missingDeps, m)
-				bootDexJars[i] = android.PathForOutput(ctx, "missing/module", m, "from/apex", image.modules.Apex(i))
+				jarPaths[i] = android.PathForOutput(ctx, "missing/module", m, "from/apex",
+					bootjars.Apex(i))
 			} else {
 				ctx.Errorf("failed to find a dex jar path for module '%s'"+
 					", note that some jars may be filtered out by module constraints", m)
@@ -569,14 +586,24 @@
 	// time, before the boot images are built (these paths are used in dexpreopt rule generation for
 	// Java libraries and apps). Generate rules that copy bootclasspath DEX jars to the predefined
 	// paths.
-	for i := range bootDexJars {
+	for i := range jarPaths {
 		ctx.Build(pctx, android.BuildParams{
 			Rule:   android.Cp,
-			Input:  bootDexJars[i],
-			Output: image.dexPaths[i],
+			Input:  jarPaths[i],
+			Output: jarPathsPredefined[i],
 		})
 	}
 
+	return missingDeps
+}
+
+// buildBootImage takes a bootImageConfig, creates rules to build it, and returns the image.
+func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootImageConfig {
+	getBootJarFunc := func(module android.Module) (int, android.Path) {
+		return getBootImageJar(ctx, image, module)
+	}
+	missingDeps := findAndCopyBootJars(ctx, image.modules, image.dexPaths, getBootJarFunc)
+
 	profile := bootImageProfileRule(ctx, image, missingDeps)
 	bootFrameworkProfileRule(ctx, image, missingDeps)
 	updatableBcpPackagesRule(ctx, image, missingDeps)
diff --git a/java/java_test.go b/java/java_test.go
index b6f639f..31eeb6b 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -53,7 +53,7 @@
 	android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
 		ctx.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory)
 	}),
-	dexpreopt.PrepareForTestWithDexpreopt,
+	PrepareForTestWithDexpreopt,
 )
 
 func TestMain(m *testing.M) {
@@ -68,7 +68,7 @@
 func testJavaError(t *testing.T, pattern string, bp string) (*android.TestContext, android.Config) {
 	t.Helper()
 	result := android.GroupFixturePreparers(
-		prepareForJavaTest, dexpreopt.PrepareForTestWithDexpreopt).
+		prepareForJavaTest, dexpreopt.PrepareForTestByEnablingDexpreopt).
 		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
 		RunTestWithBp(t, bp)
 	return result.TestContext, result.Config
diff --git a/java/testing.go b/java/testing.go
index 82a2103..295b8d0 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -43,7 +43,7 @@
 	// Make sure that mutators and module types, e.g. prebuilt mutators available.
 	android.PrepareForTestWithAndroidBuildComponents,
 	// Make java build components available to the test.
-	android.FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
+	android.FixtureRegisterWithContext(registerRequiredBuildComponentsForTest),
 	android.FixtureRegisterWithContext(registerJavaPluginBuildComponents),
 )
 
@@ -52,7 +52,16 @@
 	// Make sure that all the module types used in the defaults are registered.
 	PrepareForTestWithJavaBuildComponents,
 	// The java default module definitions.
-	android.FixtureAddTextFile(defaultJavaDir+"/Android.bp", GatherRequiredDepsForTest()),
+	android.FixtureAddTextFile(defaultJavaDir+"/Android.bp", gatherRequiredDepsForTest()),
+	// Add dexpreopt compat libs (android.test.base, etc.) and a fake dex2oatd module.
+	dexpreopt.PrepareForTestWithDexpreoptCompatLibs,
+	dexpreopt.PrepareForTestWithFakeDex2oatd,
+)
+
+// Provides everything needed by dexpreopt.
+var PrepareForTestWithDexpreopt = android.GroupFixturePreparers(
+	PrepareForTestWithJavaDefaultModules,
+	dexpreopt.PrepareForTestByEnablingDexpreopt,
 )
 
 var PrepareForTestWithOverlayBuildComponents = android.FixtureRegisterWithContext(registerOverlayBuildComponents)
@@ -178,7 +187,22 @@
 //
 // In particular this must register all the components that are used in the `Android.bp` snippet
 // returned by GatherRequiredDepsForTest()
+//
+// deprecated: Use test fixtures instead, e.g. PrepareForTestWithJavaBuildComponents
 func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
+	registerRequiredBuildComponentsForTest(ctx)
+
+	// Make sure that any tool related module types needed by dexpreopt have been registered.
+	dexpreopt.RegisterToolModulesForTest(ctx)
+}
+
+// registerRequiredBuildComponentsForTest registers the build components used by
+// PrepareForTestWithJavaDefaultModules.
+//
+// As functionality is moved out of here into separate FixturePreparer instances they should also
+// be moved into GatherRequiredDepsForTest for use by tests that have not yet switched to use test
+// fixtures.
+func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
 	RegisterAARBuildComponents(ctx)
 	RegisterAppBuildComponents(ctx)
 	RegisterAppImportBuildComponents(ctx)
@@ -193,15 +217,32 @@
 	RegisterSdkLibraryBuildComponents(ctx)
 	RegisterStubsBuildComponents(ctx)
 	RegisterSystemModulesBuildComponents(ctx)
-
-	// Make sure that any tool related module types needed by dexpreopt have been registered.
-	dexpreopt.RegisterToolModulesForTest(ctx)
 }
 
 // Gather the module definitions needed by tests that depend upon code from this package.
 //
 // Returns an `Android.bp` snippet that defines the modules that are needed by this package.
+//
+// deprecated: Use test fixtures instead, e.g. PrepareForTestWithJavaDefaultModules
 func GatherRequiredDepsForTest() string {
+	bp := gatherRequiredDepsForTest()
+
+	// For class loader context and <uses-library> tests.
+	bp += dexpreopt.CompatLibDefinitionsForTest()
+
+	// Make sure that any tools needed for dexpreopting are defined.
+	bp += dexpreopt.BpToolModulesForTest()
+
+	return bp
+}
+
+// gatherRequiredDepsForTest gathers the module definitions used by
+// PrepareForTestWithJavaDefaultModules.
+//
+// As functionality is moved out of here into separate FixturePreparer instances they should also
+// be moved into GatherRequiredDepsForTest for use by tests that have not yet switched to use test
+// fixtures.
+func gatherRequiredDepsForTest() string {
 	var bp string
 
 	extraModules := []string{
@@ -233,24 +274,6 @@
 		`, extra)
 	}
 
-	// For class loader context and <uses-library> tests.
-	dexpreoptModules := []string{"android.test.runner"}
-	dexpreoptModules = append(dexpreoptModules, dexpreopt.CompatUsesLibs...)
-	dexpreoptModules = append(dexpreoptModules, dexpreopt.OptionalCompatUsesLibs...)
-
-	for _, extra := range dexpreoptModules {
-		bp += fmt.Sprintf(`
-			java_library {
-				name: "%s",
-				srcs: ["a.java"],
-				sdk_version: "none",
-				system_modules: "stable-core-platform-api-stubs-system-modules",
-				compile_dex: true,
-				installable: true,
-			}
-		`, extra)
-	}
-
 	bp += `
 		java_library {
 			name: "framework",
@@ -287,9 +310,6 @@
 		`, extra)
 	}
 
-	// Make sure that any tools needed for dexpreopting are defined.
-	bp += dexpreopt.BpToolModulesForTest()
-
 	// Make sure that the dex_bootjars singleton module is instantiated for the tests.
 	bp += `
 		dex_bootjars {
diff --git a/rust/binary.go b/rust/binary.go
index df48916..dfe8744 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -87,7 +87,7 @@
 	deps = binary.baseCompiler.compilerDeps(ctx, deps)
 
 	if ctx.toolchain().Bionic() {
-		deps = bionicDeps(deps, Bool(binary.Properties.Static_executable))
+		deps = bionicDeps(ctx, deps, Bool(binary.Properties.Static_executable))
 		if Bool(binary.Properties.Static_executable) {
 			deps.CrtBegin = "crtbegin_static"
 		} else {
diff --git a/rust/bindgen.go b/rust/bindgen.go
index db69e23..bcc26b8 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -260,7 +260,7 @@
 func (b *bindgenDecorator) SourceProviderDeps(ctx DepsContext, deps Deps) Deps {
 	deps = b.BaseSourceProvider.SourceProviderDeps(ctx, deps)
 	if ctx.toolchain().Bionic() {
-		deps = bionicDeps(deps, false)
+		deps = bionicDeps(ctx, deps, false)
 	}
 
 	deps.SharedLibs = append(deps.SharedLibs, b.ClangProperties.Shared_libs...)
diff --git a/rust/compiler.go b/rust/compiler.go
index 98ad7ad..200af90 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -281,7 +281,7 @@
 	return deps
 }
 
-func bionicDeps(deps Deps, static bool) Deps {
+func bionicDeps(ctx DepsContext, deps Deps, static bool) Deps {
 	bionicLibs := []string{}
 	bionicLibs = append(bionicLibs, "liblog")
 	bionicLibs = append(bionicLibs, "libc")
@@ -294,9 +294,9 @@
 		deps.SharedLibs = append(deps.SharedLibs, bionicLibs...)
 	}
 
-	//TODO(b/141331117) libstd requires libgcc on Android
-	deps.StaticLibs = append(deps.StaticLibs, "libgcc")
-
+	if libRuntimeBuiltins := config.BuiltinsRuntimeLibrary(ctx.toolchain()); libRuntimeBuiltins != "" {
+		deps.StaticLibs = append(deps.StaticLibs, libRuntimeBuiltins)
+	}
 	return deps
 }
 
diff --git a/rust/config/global.go b/rust/config/global.go
index 12f4972..9208ddb 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -53,6 +53,7 @@
 
 	deviceGlobalRustFlags = []string{
 		"-C panic=abort",
+		"-Z link-native-libraries=no",
 	}
 
 	deviceGlobalLinkFlags = []string{
@@ -62,7 +63,7 @@
 		// Override cc's --no-undefined-version to allow rustc's generated alloc functions
 		"-Wl,--undefined-version",
 
-		"-Bdynamic",
+		"-Wl,-Bdynamic",
 		"-nostdlib",
 		"-Wl,--pack-dyn-relocs=android+relr",
 		"-Wl,--use-android-relr-tags",
diff --git a/rust/config/toolchain.go b/rust/config/toolchain.go
index 9525c38..a769f12 100644
--- a/rust/config/toolchain.go
+++ b/rust/config/toolchain.go
@@ -112,6 +112,10 @@
 	return ""
 }
 
+func BuiltinsRuntimeLibrary(t Toolchain) string {
+	return LibclangRuntimeLibrary(t, "builtins")
+}
+
 func LibFuzzerRuntimeLibrary(t Toolchain) string {
 	return LibclangRuntimeLibrary(t, "fuzzer")
 }
diff --git a/rust/library.go b/rust/library.go
index 7ff13ec..71fe1f5 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -404,7 +404,7 @@
 	deps = library.baseCompiler.compilerDeps(ctx, deps)
 
 	if ctx.toolchain().Bionic() && (library.dylib() || library.shared()) {
-		deps = bionicDeps(deps, false)
+		deps = bionicDeps(ctx, deps, false)
 		deps.CrtBegin = "crtbegin_so"
 		deps.CrtEnd = "crtend_so"
 	}