Merge "Apply "excludes" for OutputFileProducer"
diff --git a/android/config.go b/android/config.go
index 6f73a12..7073a49 100644
--- a/android/config.go
+++ b/android/config.go
@@ -93,8 +93,9 @@
 
 	deviceConfig *deviceConfig
 
-	srcDir   string // the path of the root source directory
-	buildDir string // the path of the build output directory
+	srcDir         string // the path of the root source directory
+	buildDir       string // the path of the build output directory
+	moduleListFile string // the path to the file which lists blueprint files to parse.
 
 	env       map[string]string
 	envLock   sync.Mutex
@@ -316,7 +317,7 @@
 
 // New creates a new Config object.  The srcDir argument specifies the path to
 // the root source directory. It also loads the config file, if found.
-func NewConfig(srcDir, buildDir string) (Config, error) {
+func NewConfig(srcDir, buildDir string, moduleListFile string) (Config, error) {
 	// Make a config with default options
 	config := &config{
 		ConfigFileName:           filepath.Join(buildDir, configFileName),
@@ -328,7 +329,8 @@
 		buildDir:          buildDir,
 		multilibConflicts: make(map[ArchType]bool),
 
-		fs: pathtools.NewOsFs(absSrcDir),
+		moduleListFile: moduleListFile,
+		fs:             pathtools.NewOsFs(absSrcDir),
 	}
 
 	config.deviceConfig = &deviceConfig{
diff --git a/android/paths.go b/android/paths.go
index 887b3a3..d13b6d8 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -915,6 +915,22 @@
 var _ Path = OutputPath{}
 var _ WritablePath = OutputPath{}
 
+// toolDepPath is a Path representing a dependency of the build tool.
+type toolDepPath struct {
+	basePath
+}
+
+var _ Path = toolDepPath{}
+
+// pathForBuildToolDep returns a toolDepPath representing the given path string.
+// There is no validation for the path, as it is "trusted": It may fail
+// normal validation checks. For example, it may be an absolute path.
+// Only use this function to construct paths for dependencies of the build
+// tool invocation.
+func pathForBuildToolDep(ctx PathContext, path string) toolDepPath {
+	return toolDepPath{basePath{path, ctx.Config(), ""}}
+}
+
 // PathForOutput joins the provided paths and returns an OutputPath that is
 // validated to not escape the build dir.
 // On error, it will return a usable, but invalid OutputPath, and report a ModuleError.
diff --git a/android/writedocs.go b/android/writedocs.go
index 9e43e80..4eb15e6 100644
--- a/android/writedocs.go
+++ b/android/writedocs.go
@@ -44,6 +44,10 @@
 }
 
 func (c *docsSingleton) GenerateBuildActions(ctx SingletonContext) {
+	var deps Paths
+	deps = append(deps, pathForBuildToolDep(ctx, ctx.Config().moduleListFile))
+	deps = append(deps, pathForBuildToolDep(ctx, ctx.Config().ProductVariablesFileName))
+
 	// Generate build system docs for the primary builder.  Generating docs reads the source
 	// files used to build the primary builder, but that dependency will be picked up through
 	// the dependency on the primary builder itself.  There are no dependencies on the
@@ -63,6 +67,7 @@
 	ctx.Build(pctx, BuildParams{
 		Rule:   soongDocs,
 		Output: docsFile,
+		Inputs: deps,
 		Args: map[string]string{
 			"outDir": PathForOutput(ctx, "docs").String(),
 		},
diff --git a/cc/cc.go b/cc/cc.go
index 0a23967..0d5b6bd 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -96,6 +96,9 @@
 	HeaderLibs                                  []string
 	RuntimeLibs                                 []string
 
+	// Used for data dependencies adjacent to tests
+	DataLibs []string
+
 	StaticUnwinderIfLegacy bool
 
 	ReexportSharedLibHeaders, ReexportStaticLibHeaders, ReexportHeaderLibHeaders []string
@@ -136,7 +139,6 @@
 
 	// Paths to generated source files
 	GeneratedSources android.Paths
-	GeneratedHeaders android.Paths
 	GeneratedDeps    android.Paths
 
 	Flags                      []string
@@ -424,6 +426,7 @@
 }
 
 var (
+	dataLibDepTag         = DependencyTag{Name: "data_lib", Library: true, Shared: true}
 	sharedExportDepTag    = DependencyTag{Name: "shared", Library: true, Shared: true, ReexportFlags: true}
 	earlySharedDepTag     = DependencyTag{Name: "early_shared", Library: true, Shared: true}
 	lateSharedDepTag      = DependencyTag{Name: "late shared", Library: true, Shared: true}
@@ -1983,6 +1986,10 @@
 
 	actx.AddVariationDependencies([]blueprint.Variation{
 		{Mutator: "link", Variation: "shared"},
+	}, dataLibDepTag, deps.DataLibs...)
+
+	actx.AddVariationDependencies([]blueprint.Variation{
+		{Mutator: "link", Variation: "shared"},
 	}, runtimeDepTag, deps.RuntimeLibs...)
 
 	actx.AddDependency(c, genSourceDepTag, deps.GeneratedSources...)
@@ -2228,8 +2235,6 @@
 				fallthrough
 			case genHeaderDepTag, genHeaderExportDepTag:
 				if genRule, ok := dep.(genrule.SourceFileGenerator); ok {
-					depPaths.GeneratedHeaders = append(depPaths.GeneratedHeaders,
-						genRule.GeneratedSourceFiles()...)
 					depPaths.GeneratedDeps = append(depPaths.GeneratedDeps,
 						genRule.GeneratedDeps()...)
 					dirs := genRule.GeneratedHeaderDirs()
@@ -2417,7 +2422,6 @@
 			if _, ok := ccDep.(*Module); ok {
 				if i, ok := ccDep.(*Module).linker.(exportedFlagsProducer); ok {
 					depPaths.SystemIncludeDirs = append(depPaths.SystemIncludeDirs, i.exportedSystemDirs()...)
-					depPaths.GeneratedHeaders = append(depPaths.GeneratedHeaders, i.exportedGeneratedHeaders()...)
 					depPaths.GeneratedDeps = append(depPaths.GeneratedDeps, i.exportedDeps()...)
 					depPaths.Flags = append(depPaths.Flags, i.exportedFlags()...)
 
@@ -2647,7 +2651,6 @@
 	depPaths.Flags = android.FirstUniqueStrings(depPaths.Flags)
 	depPaths.IncludeDirs = android.FirstUniquePaths(depPaths.IncludeDirs)
 	depPaths.SystemIncludeDirs = android.FirstUniquePaths(depPaths.SystemIncludeDirs)
-	depPaths.GeneratedHeaders = android.FirstUniquePaths(depPaths.GeneratedHeaders)
 	depPaths.GeneratedDeps = android.FirstUniquePaths(depPaths.GeneratedDeps)
 	depPaths.ReexportedDirs = android.FirstUniquePaths(depPaths.ReexportedDirs)
 	depPaths.ReexportedSystemDirs = android.FirstUniquePaths(depPaths.ReexportedSystemDirs)
@@ -3009,6 +3012,9 @@
 
 		lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
 			lib.baseCompiler.Properties.Target.Vendor.Exclude_srcs...)
+
+		lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
+			lib.baseCompiler.Properties.Target.Vendor.Exclude_generated_sources...)
 	}
 }
 
@@ -3019,6 +3025,9 @@
 
 		lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
 			lib.baseCompiler.Properties.Target.Recovery.Exclude_srcs...)
+
+		lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
+			lib.baseCompiler.Properties.Target.Recovery.Exclude_generated_sources...)
 	}
 }
 
diff --git a/cc/cc_test.go b/cc/cc_test.go
index f73e021..8a1c8ed 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -526,6 +526,56 @@
 	checkVndkLibrariesOutput(t, ctx, "vndkcorevariant.libraries.txt", []string{"libc++.so", "libvndk2.so", "libvndk_sp.so"})
 }
 
+func TestDataLibs(t *testing.T) {
+	bp := `
+		cc_test_library {
+			name: "test_lib",
+			srcs: ["test_lib.cpp"],
+			gtest: false,
+		}
+
+		cc_test {
+			name: "main_test",
+			data_libs: ["test_lib"],
+			gtest: false,
+		}
+  `
+
+	config := TestConfig(buildDir, android.Android, nil, bp, nil)
+	config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+	config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+	config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true)
+
+	ctx := testCcWithConfig(t, config)
+	module := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon").Module()
+	testBinary := module.(*Module).linker.(*testBinary)
+	outputFiles, err := module.(android.OutputFileProducer).OutputFiles("")
+	if err != nil {
+		t.Errorf("Expected cc_test to produce output files, error: %s", err)
+		return
+	}
+	if len(outputFiles) != 1 {
+		t.Errorf("expected exactly one output file. output files: [%s]", outputFiles)
+		return
+	}
+	if len(testBinary.dataPaths()) != 1 {
+		t.Errorf("expected exactly one test data file. test data files: [%s]", testBinary.dataPaths())
+		return
+	}
+
+	outputPath := outputFiles[0].String()
+	testBinaryPath := testBinary.dataPaths()[0].String()
+
+	if !strings.HasSuffix(outputPath, "/main_test") {
+		t.Errorf("expected test output file to be 'main_test', but was '%s'", outputPath)
+		return
+	}
+	if !strings.HasSuffix(testBinaryPath, "/test_lib.so") {
+		t.Errorf("expected test data file to be 'test_lib.so', but was '%s'", testBinaryPath)
+		return
+	}
+}
+
 func TestVndkWhenVndkVersionIsNotSet(t *testing.T) {
 	ctx := testCcNoVndk(t, `
 		cc_library {
diff --git a/cc/ccdeps.go b/cc/ccdeps.go
index 225405c..b96d8b0 100644
--- a/cc/ccdeps.go
+++ b/cc/ccdeps.go
@@ -38,8 +38,11 @@
 }
 
 type ccdepsGeneratorSingleton struct {
+	outputPath android.Path
 }
 
+var _ android.SingletonMakeVarsProvider = (*ccdepsGeneratorSingleton)(nil)
+
 const (
 	// Environment variables used to control the behavior of this singleton.
 	envVariableCollectCCDeps = "SOONG_COLLECT_CC_DEPS"
@@ -110,6 +113,21 @@
 	if err != nil {
 		ctx.Errorf(err.Error())
 	}
+	c.outputPath = ccfpath
+
+	// This is necessary to satisfy the dangling rules check as this file is written by Soong rather than a rule.
+	ctx.Build(pctx, android.BuildParams{
+		Rule:   android.Touch,
+		Output: ccfpath,
+	})
+}
+
+func (c *ccdepsGeneratorSingleton) MakeVars(ctx android.MakeVarsContext) {
+	if c.outputPath == nil {
+		return
+	}
+
+	ctx.DistForGoal("general-tests", c.outputPath)
 }
 
 func parseCompilerCCParameters(ctx android.SingletonContext, params []string) ccParameters {
diff --git a/cc/compiler.go b/cc/compiler.go
index b5f297c..d5ea2c3 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -86,6 +86,10 @@
 	// genrule modules.
 	Generated_sources []string `android:"arch_variant"`
 
+	// list of generated sources that should not be used to build the C/C++ module.
+	// This is most useful in the arch/multilib variants to remove non-common files
+	Exclude_generated_sources []string `android:"arch_variant"`
+
 	// list of generated headers to add to the include path. These are the names
 	// of genrule modules.
 	Generated_headers []string `android:"arch_variant"`
@@ -150,6 +154,10 @@
 			// List of additional cflags that should be used to build the vendor
 			// variant of the C/C++ module.
 			Cflags []string
+
+			// list of generated sources that should not be used to
+			// build the vendor variant of the C/C++ module.
+			Exclude_generated_sources []string
 		}
 		Recovery struct {
 			// list of source files that should only be used in the
@@ -163,6 +171,10 @@
 			// List of additional cflags that should be used to build the recovery
 			// variant of the C/C++ module.
 			Cflags []string
+
+			// list of generated sources that should not be used to
+			// build the recovery variant of the C/C++ module.
+			Exclude_generated_sources []string
 		}
 	}
 
@@ -227,6 +239,7 @@
 
 func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps {
 	deps.GeneratedSources = append(deps.GeneratedSources, compiler.Properties.Generated_sources...)
+	deps.GeneratedSources = removeListFromList(deps.GeneratedSources, compiler.Properties.Exclude_generated_sources)
 	deps.GeneratedHeaders = append(deps.GeneratedHeaders, compiler.Properties.Generated_headers...)
 
 	android.ProtoDeps(ctx, &compiler.Proto)
diff --git a/cc/config/global.go b/cc/config/global.go
index 7b651bc..373fc77 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -32,6 +32,7 @@
 		"-Wno-unused",
 		"-Winit-self",
 		"-Wpointer-arith",
+		"-Wunreachable-code-loop-increment",
 
 		// Make paths in deps files relative
 		"-no-canonical-prefixes",
@@ -51,6 +52,7 @@
 		"-Werror=date-time",
 		"-Werror=pragma-pack",
 		"-Werror=pragma-pack-suspicious-include",
+		"-Werror=unreachable-code-loop-increment",
 	}
 
 	commonGlobalConlyflags = []string{}
diff --git a/cc/test.go b/cc/test.go
index 09da976..37afb0c 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -58,6 +58,9 @@
 	// the test
 	Data []string `android:"path,arch_variant"`
 
+	// list of shared library modules that should be installed alongside the test
+	Data_libs []string `android:"arch_variant"`
+
 	// list of compatibility suites (for example "cts", "vts") that the module should be
 	// installed into.
 	Test_suites []string `android:"arch_variant"`
@@ -325,6 +328,7 @@
 func (test *testBinary) linkerDeps(ctx DepsContext, deps Deps) Deps {
 	deps = test.testDecorator.linkerDeps(ctx, deps)
 	deps = test.binaryDecorator.linkerDeps(ctx, deps)
+	deps.DataLibs = append(deps.DataLibs, test.Properties.Data_libs...)
 	return deps
 }
 
@@ -336,6 +340,21 @@
 
 func (test *testBinary) install(ctx ModuleContext, file android.Path) {
 	test.data = android.PathsForModuleSrc(ctx, test.Properties.Data)
+
+	ctx.VisitDirectDepsWithTag(dataLibDepTag, func(dep android.Module) {
+		depName := ctx.OtherModuleName(dep)
+		ccDep, ok := dep.(LinkableInterface)
+
+		if !ok {
+			ctx.ModuleErrorf("data_lib %q is not a linkable cc module", depName)
+		}
+		if ccDep.OutputFile().Valid() {
+			test.data = append(test.data, ccDep.OutputFile().Path())
+		} else {
+			ctx.ModuleErrorf("data_lib %q has no output file", depName)
+		}
+	})
+
 	var api_level_prop string
 	var configs []tradefed.Config
 	var min_level string
@@ -507,6 +526,7 @@
 
 func (benchmark *benchmarkDecorator) install(ctx ModuleContext, file android.Path) {
 	benchmark.data = android.PathsForModuleSrc(ctx, benchmark.Properties.Data)
+
 	var configs []tradefed.Config
 	if Bool(benchmark.Properties.Require_root) {
 		configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil})
diff --git a/cc/testing.go b/cc/testing.go
index b0c3c162..a106d46 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -500,6 +500,7 @@
 	ctx := android.NewTestArchContext()
 	ctx.RegisterModuleType("cc_fuzz", FuzzFactory)
 	ctx.RegisterModuleType("cc_test", TestFactory)
+	ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
 	ctx.RegisterModuleType("llndk_headers", llndkHeadersFactory)
 	ctx.RegisterModuleType("vendor_public_library", vendorPublicLibraryFactory)
 	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 905f206..532d9e4 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -59,7 +59,7 @@
 	ctx := android.NewContext()
 	ctx.Register()
 
-	configuration, err := android.NewConfig(srcDir, bootstrap.BuildDir)
+	configuration, err := android.NewConfig(srcDir, bootstrap.BuildDir, bootstrap.ModuleListFile)
 	if err != nil {
 		fmt.Fprintf(os.Stderr, "%s", err)
 		os.Exit(1)
diff --git a/cmd/soong_build/writedocs.go b/cmd/soong_build/writedocs.go
index 9424b6c..c136846 100644
--- a/cmd/soong_build/writedocs.go
+++ b/cmd/soong_build/writedocs.go
@@ -44,7 +44,7 @@
 	"name":             0,
 	"src":              1,
 	"srcs":             2,
-	"defautls":         3,
+	"defaults":         3,
 	"host_supported":   4,
 	"device_supported": 5,
 }
diff --git a/finder/finder.go b/finder/finder.go
index f20bed2..6513fa3 100644
--- a/finder/finder.go
+++ b/finder/finder.go
@@ -325,7 +325,12 @@
 // Shutdown declares that the finder is no longer needed and waits for its cleanup to complete
 // Currently, that only entails waiting for the database dump to complete.
 func (f *Finder) Shutdown() {
-	f.waitForDbDump()
+	f.WaitForDbDump()
+}
+
+// WaitForDbDump returns once the database has been written to f.DbPath.
+func (f *Finder) WaitForDbDump() {
+	f.shutdownWaitgroup.Wait()
 }
 
 // End of public api
@@ -345,10 +350,6 @@
 	}
 }
 
-func (f *Finder) waitForDbDump() {
-	f.shutdownWaitgroup.Wait()
-}
-
 // joinCleanPaths is like filepath.Join but is faster because
 // joinCleanPaths doesn't have to support paths ending in "/" or containing ".."
 func joinCleanPaths(base string, leaf string) string {
diff --git a/java/java.go b/java/java.go
index 0d46672..46ef98b 100644
--- a/java/java.go
+++ b/java/java.go
@@ -140,10 +140,15 @@
 // Findbugs
 
 type CompilerProperties struct {
-	// list of source files used to compile the Java module.  May be .java, .logtags, .proto,
+	// list of source files used to compile the Java module.  May be .java, .kt, .logtags, .proto,
 	// or .aidl files.
 	Srcs []string `android:"path,arch_variant"`
 
+	// list Kotlin of source files containing Kotlin code that should be treated as common code in
+	// a codebase that supports Kotlin multiplatform.  See
+	// https://kotlinlang.org/docs/reference/multiplatform.html.  May be only be .kt files.
+	Common_srcs []string `android:"path,arch_variant"`
+
 	// list of source files that should not be used to build the Java module.
 	// This is most useful in the arch/multilib variants to remove non-common files
 	Exclude_srcs []string `android:"path,arch_variant"`
@@ -1300,6 +1305,11 @@
 		flags = protoFlags(ctx, &j.properties, &j.protoProperties, flags)
 	}
 
+	kotlinCommonSrcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Common_srcs, nil)
+	if len(kotlinCommonSrcFiles.FilterOutByExt(".kt")) > 0 {
+		ctx.PropertyErrorf("common_srcs", "common_srcs must be .kt files")
+	}
+
 	srcFiles = j.genSources(ctx, srcFiles, flags)
 
 	srcJars := srcFiles.FilterByExt(".srcjar")
@@ -1353,6 +1363,7 @@
 
 		// Collect .kt files for AIDEGen
 		j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, srcFiles.FilterByExt(".kt").Strings()...)
+		j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, kotlinCommonSrcFiles.Strings()...)
 
 		flags.classpath = append(flags.classpath, deps.kotlinStdlib...)
 		flags.classpath = append(flags.classpath, deps.kotlinAnnotations...)
@@ -1364,7 +1375,7 @@
 			// Use kapt for annotation processing
 			kaptSrcJar := android.PathForModuleOut(ctx, "kapt", "kapt-sources.jar")
 			kaptResJar := android.PathForModuleOut(ctx, "kapt", "kapt-res.jar")
-			kotlinKapt(ctx, kaptSrcJar, kaptResJar, kotlinSrcFiles, srcJars, flags)
+			kotlinKapt(ctx, kaptSrcJar, kaptResJar, kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
 			srcJars = append(srcJars, kaptSrcJar)
 			kotlinJars = append(kotlinJars, kaptResJar)
 			// Disable annotation processing in javac, it's already been handled by kapt
@@ -1373,7 +1384,7 @@
 		}
 
 		kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName)
-		kotlinCompile(ctx, kotlinJar, kotlinSrcFiles, srcJars, flags)
+		kotlinCompile(ctx, kotlinJar, kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
 		if ctx.Failed() {
 			return
 		}
diff --git a/java/jdeps.go b/java/jdeps.go
index 9f43887..2b5ee74 100644
--- a/java/jdeps.go
+++ b/java/jdeps.go
@@ -34,8 +34,11 @@
 }
 
 type jdepsGeneratorSingleton struct {
+	outputPath android.Path
 }
 
+var _ android.SingletonMakeVarsProvider = (*jdepsGeneratorSingleton)(nil)
+
 const (
 	// Environment variables used to modify behavior of this singleton.
 	envVariableCollectJavaDeps = "SOONG_COLLECT_JAVA_DEPS"
@@ -97,6 +100,21 @@
 	if err != nil {
 		ctx.Errorf(err.Error())
 	}
+	j.outputPath = jfpath
+
+	// This is necessary to satisfy the dangling rules check as this file is written by Soong rather than a rule.
+	ctx.Build(pctx, android.BuildParams{
+		Rule:   android.Touch,
+		Output: jfpath,
+	})
+}
+
+func (j *jdepsGeneratorSingleton) MakeVars(ctx android.MakeVarsContext) {
+	if j.outputPath == nil {
+		return
+	}
+
+	ctx.DistForGoal("general-tests", j.outputPath)
 }
 
 func createJsonFile(moduleInfos map[string]android.IdeInfo, jfpath android.WritablePath) error {
diff --git a/java/kotlin.go b/java/kotlin.go
index e3356be..e8c030a 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -33,7 +33,7 @@
 			`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
 			`${config.GenKotlinBuildFileCmd} --classpath "$classpath" --name "$name"` +
 			` --out_dir "$classesDir" --srcs "$out.rsp" --srcs "$srcJarDir/list"` +
-			` --out "$kotlinBuildFile" && ` +
+			` $commonSrcFilesArg --out "$kotlinBuildFile" && ` +
 			`${config.KotlincCmd} ${config.JavacHeapFlags} $kotlincFlags ` +
 			`-jvm-target $kotlinJvmTarget -Xbuild-file=$kotlinBuildFile -kotlin-home $emptyDir && ` +
 			`${config.SoongZipCmd} -jar -o $out -C $classesDir -D $classesDir && ` +
@@ -54,21 +54,43 @@
 		Rspfile:        "$out.rsp",
 		RspfileContent: `$in`,
 	},
-	"kotlincFlags", "classpath", "srcJars", "srcJarDir", "classesDir", "kotlinJvmTarget", "kotlinBuildFile",
-	"emptyDir", "name")
+	"kotlincFlags", "classpath", "srcJars", "commonSrcFilesArg", "srcJarDir", "classesDir",
+	"kotlinJvmTarget", "kotlinBuildFile", "emptyDir", "name")
+
+func kotlinCommonSrcsList(ctx android.ModuleContext, commonSrcFiles android.Paths) android.OptionalPath {
+	if len(commonSrcFiles) > 0 {
+		// The list of common_srcs may be too long to put on the command line, but
+		// we can't use the rsp file because it is already being used for srcs.
+		// Insert a second rule to write out the list of resources to a file.
+		commonSrcsList := android.PathForModuleOut(ctx, "kotlinc_common_srcs.list")
+		rule := android.NewRuleBuilder()
+		rule.Command().Text("cp").FlagWithRspFileInputList("", commonSrcFiles).Output(commonSrcsList)
+		rule.Build(pctx, ctx, "kotlin_common_srcs_list", "kotlin common_srcs list")
+		return android.OptionalPathForPath(commonSrcsList)
+	}
+	return android.OptionalPath{}
+}
 
 // kotlinCompile takes .java and .kt sources and srcJars, and compiles the .kt sources into a classes jar in outputFile.
 func kotlinCompile(ctx android.ModuleContext, outputFile android.WritablePath,
-	srcFiles, srcJars android.Paths,
+	srcFiles, commonSrcFiles, srcJars android.Paths,
 	flags javaBuilderFlags) {
 
 	var deps android.Paths
 	deps = append(deps, flags.kotlincClasspath...)
 	deps = append(deps, srcJars...)
+	deps = append(deps, commonSrcFiles...)
 
 	kotlinName := filepath.Join(ctx.ModuleDir(), ctx.ModuleSubDir(), ctx.ModuleName())
 	kotlinName = strings.ReplaceAll(kotlinName, "/", "__")
 
+	commonSrcsList := kotlinCommonSrcsList(ctx, commonSrcFiles)
+	commonSrcFilesArg := ""
+	if commonSrcsList.Valid() {
+		deps = append(deps, commonSrcsList.Path())
+		commonSrcFilesArg = "--common_srcs " + commonSrcsList.String()
+	}
+
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        kotlinc,
 		Description: "kotlinc",
@@ -76,13 +98,14 @@
 		Inputs:      srcFiles,
 		Implicits:   deps,
 		Args: map[string]string{
-			"classpath":       flags.kotlincClasspath.FormJavaClassPath(""),
-			"kotlincFlags":    flags.kotlincFlags,
-			"srcJars":         strings.Join(srcJars.Strings(), " "),
-			"classesDir":      android.PathForModuleOut(ctx, "kotlinc", "classes").String(),
-			"srcJarDir":       android.PathForModuleOut(ctx, "kotlinc", "srcJars").String(),
-			"kotlinBuildFile": android.PathForModuleOut(ctx, "kotlinc-build.xml").String(),
-			"emptyDir":        android.PathForModuleOut(ctx, "kotlinc", "empty").String(),
+			"classpath":         flags.kotlincClasspath.FormJavaClassPath(""),
+			"kotlincFlags":      flags.kotlincFlags,
+			"commonSrcFilesArg": commonSrcFilesArg,
+			"srcJars":           strings.Join(srcJars.Strings(), " "),
+			"classesDir":        android.PathForModuleOut(ctx, "kotlinc", "classes").String(),
+			"srcJarDir":         android.PathForModuleOut(ctx, "kotlinc", "srcJars").String(),
+			"kotlinBuildFile":   android.PathForModuleOut(ctx, "kotlinc-build.xml").String(),
+			"emptyDir":          android.PathForModuleOut(ctx, "kotlinc", "empty").String(),
 			// http://b/69160377 kotlinc only supports -jvm-target 1.6 and 1.8
 			"kotlinJvmTarget": "1.8",
 			"name":            kotlinName,
@@ -97,7 +120,7 @@
 			`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
 			`${config.GenKotlinBuildFileCmd} --classpath "$classpath" --name "$name"` +
 			` --srcs "$out.rsp" --srcs "$srcJarDir/list"` +
-			` --out "$kotlinBuildFile" && ` +
+			` $commonSrcFilesArg --out "$kotlinBuildFile" && ` +
 			`${config.KotlincCmd} ${config.KotlincSuppressJDK9Warnings} ${config.JavacHeapFlags} $kotlincFlags ` +
 			`-Xplugin=${config.KotlinKaptJar} ` +
 			`-P plugin:org.jetbrains.kotlin.kapt3:sources=$kaptDir/sources ` +
@@ -124,21 +147,31 @@
 		RspfileContent: `$in`,
 	},
 	"kotlincFlags", "encodedJavacFlags", "kaptProcessorPath", "kaptProcessor",
-	"classpath", "srcJars", "srcJarDir", "kaptDir", "kotlinJvmTarget", "kotlinBuildFile", "name",
-	"classesJarOut")
+	"classpath", "srcJars", "commonSrcFilesArg", "srcJarDir", "kaptDir", "kotlinJvmTarget",
+	"kotlinBuildFile", "name", "classesJarOut")
 
 // kotlinKapt performs Kotlin-compatible annotation processing.  It takes .kt and .java sources and srcjars, and runs
 // annotation processors over all of them, producing a srcjar of generated code in outputFile.  The srcjar should be
 // added as an additional input to kotlinc and javac rules, and the javac rule should have annotation processing
 // disabled.
 func kotlinKapt(ctx android.ModuleContext, srcJarOutputFile, resJarOutputFile android.WritablePath,
-	srcFiles, srcJars android.Paths,
+	srcFiles, commonSrcFiles, srcJars android.Paths,
 	flags javaBuilderFlags) {
 
+	srcFiles = append(android.Paths(nil), srcFiles...)
+
 	var deps android.Paths
 	deps = append(deps, flags.kotlincClasspath...)
 	deps = append(deps, srcJars...)
 	deps = append(deps, flags.processorPath...)
+	deps = append(deps, commonSrcFiles...)
+
+	commonSrcsList := kotlinCommonSrcsList(ctx, commonSrcFiles)
+	commonSrcFilesArg := ""
+	if commonSrcsList.Valid() {
+		deps = append(deps, commonSrcsList.Path())
+		commonSrcFilesArg = "--common_srcs " + commonSrcsList.String()
+	}
 
 	kaptProcessorPath := flags.processorPath.FormRepeatedClassPath("-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=")
 
@@ -168,6 +201,7 @@
 		Args: map[string]string{
 			"classpath":         flags.kotlincClasspath.FormJavaClassPath(""),
 			"kotlincFlags":      flags.kotlincFlags,
+			"commonSrcFilesArg": commonSrcFilesArg,
 			"srcJars":           strings.Join(srcJars.Strings(), " "),
 			"srcJarDir":         android.PathForModuleOut(ctx, "kapt", "srcJars").String(),
 			"kotlinBuildFile":   android.PathForModuleOut(ctx, "kapt", "build.xml").String(),
diff --git a/java/sdk.go b/java/sdk.go
index c4861e3..6564f6d 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -449,7 +449,12 @@
 	case sdkTest:
 		return toModule([]string{"android_test_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx))
 	case sdkCore:
-		return toModule([]string{"core.current.stubs"}, "", nil)
+		return sdkDep{
+			useModule:        true,
+			bootclasspath:    []string{"core.current.stubs", config.DefaultLambdaStubsLibrary},
+			systemModules:    "core-current-stubs-system-modules",
+			noFrameworksLibs: true,
+		}
 	case sdkModule:
 		// TODO(146757305): provide .apk and .aidl that have more APIs for modules
 		return toModule([]string{"android_module_lib_stubs_current"}, "framework-res", nonUpdatableFrameworkAidlPath(ctx))
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 773a70c..1f23b14 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -139,11 +139,10 @@
 		},
 		{
 
-			name:           "core_current",
-			properties:     `sdk_version: "core_current",`,
-			bootclasspath:  []string{"core.current.stubs", "core-lambda-stubs"},
-			system:         "core-current-stubs-system-modules",
-			java9classpath: []string{"core.current.stubs"},
+			name:          "core_current",
+			properties:    `sdk_version: "core_current",`,
+			bootclasspath: []string{"core.current.stubs", "core-lambda-stubs"},
+			system:        "core-current-stubs-system-modules",
 		},
 		{
 
diff --git a/ui/build/finder.go b/ui/build/finder.go
index 6786337..c019ea2 100644
--- a/ui/build/finder.go
+++ b/ui/build/finder.go
@@ -126,6 +126,11 @@
 	if err != nil {
 		ctx.Fatalf("Could not find modules: %v", err)
 	}
+
+	if config.Dist() {
+		f.WaitForDbDump()
+		distFile(ctx, config, f.DbPath, "module_paths")
+	}
 }
 
 func dumpListToFile(ctx Context, config Config, list []string, filePath string) (err error) {
diff --git a/ui/build/test_build.go b/ui/build/test_build.go
index 4ff9483..83b3807 100644
--- a/ui/build/test_build.go
+++ b/ui/build/test_build.go
@@ -66,6 +66,8 @@
 	outDir := config.OutDir()
 	bootstrapDir := filepath.Join(outDir, "soong", ".bootstrap")
 	miniBootstrapDir := filepath.Join(outDir, "soong", ".minibootstrap")
+	modulePathsDir := filepath.Join(outDir, ".module_paths")
+	variablesFilePath := filepath.Join(outDir, "soong", "soong.variables")
 
 	danglingRules := make(map[string]bool)
 
@@ -76,7 +78,10 @@
 			// Leaf node is not in the out directory.
 			continue
 		}
-		if strings.HasPrefix(line, bootstrapDir) || strings.HasPrefix(line, miniBootstrapDir) {
+		if strings.HasPrefix(line, bootstrapDir) ||
+			strings.HasPrefix(line, miniBootstrapDir) ||
+			strings.HasPrefix(line, modulePathsDir) ||
+			line == variablesFilePath {
 			// Leaf node is in one of Soong's bootstrap directories, which do not have
 			// full build rules in the primary build.ninja file.
 			continue