Merge "Cacheable, multithreaded finder."
diff --git a/android/mutator.go b/android/mutator.go
index c8f3e8f..e20bc2c 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -74,7 +74,7 @@
 	func(ctx RegisterMutatorsContext) {
 		ctx.TopDown("load_hooks", loadHookMutator).Parallel()
 	},
-	registerPrebuiltsPreArchMutators,
+	RegisterPrebuiltsPreArchMutators,
 	RegisterDefaultsPreArchMutators,
 }
 
@@ -86,7 +86,7 @@
 }
 
 var postDeps = []RegisterMutatorFunc{
-	registerPrebuiltsPostDepsMutators,
+	RegisterPrebuiltsPostDepsMutators,
 }
 
 func PreArchMutators(f RegisterMutatorFunc) {
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 080df91..507aa5f 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -61,11 +61,11 @@
 	Prebuilt() *Prebuilt
 }
 
-func registerPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) {
+func RegisterPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) {
 	ctx.BottomUp("prebuilts", prebuiltMutator).Parallel()
 }
 
-func registerPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
+func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
 	ctx.TopDown("prebuilt_select", PrebuiltSelectModuleMutator).Parallel()
 	ctx.BottomUp("prebuilt_replace", PrebuiltReplaceMutator).Parallel()
 }
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index fe763ed..774a15c 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -123,8 +123,8 @@
 	for _, test := range prebuiltsTests {
 		t.Run(test.name, func(t *testing.T) {
 			ctx := NewTestContext()
-			ctx.PreArchMutators(registerPrebuiltsPreArchMutators)
-			ctx.PostDepsMutators(registerPrebuiltsPostDepsMutators)
+			ctx.PreArchMutators(RegisterPrebuiltsPreArchMutators)
+			ctx.PostDepsMutators(RegisterPrebuiltsPostDepsMutators)
 			ctx.RegisterModuleType("prebuilt", ModuleFactoryAdaptor(newPrebuiltModule))
 			ctx.RegisterModuleType("source", ModuleFactoryAdaptor(newSourceModule))
 			ctx.Register()
diff --git a/bootstrap.bash b/bootstrap.bash
index dbc6eb2..ff1ac8a 100755
--- a/bootstrap.bash
+++ b/bootstrap.bash
@@ -2,6 +2,14 @@
 
 set -e
 
+if [ -z "$NO_DEPRECATION_WARNING" ]; then
+    echo '== WARNING: bootstrap.bash & ./soong are deprecated ==' >&2
+    echo 'Use `m --skip-make` with a standalone OUT_DIR instead.' >&2
+    echo 'Without envsetup.sh, use:' >&2
+    echo '  build/soong/soong_ui.bash --make-mode --skip-make' >&2
+    echo '======================================================' >&2
+fi
+
 ORIG_SRCDIR=$(dirname "${BASH_SOURCE[0]}")
 if [[ "$ORIG_SRCDIR" != "." ]]; then
   if [[ ! -z "$BUILDDIR" ]]; then
diff --git a/cc/library.go b/cc/library.go
index 3d463bd..4e3e2b3 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -351,7 +351,7 @@
 		}
 		return Objects{}
 	}
-	if ctx.createVndkSourceAbiDump() {
+	if ctx.createVndkSourceAbiDump() || library.sabi.Properties.CreateSAbiDumps {
 		exportIncludeDirs := android.PathsForModuleSrc(ctx, library.flagExporter.Properties.Export_include_dirs)
 		var SourceAbiFlags []string
 		for _, dir := range exportIncludeDirs.Strings() {
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index ac05df0..976c711 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -116,7 +116,19 @@
 	// TODO(ccross): verify shared library dependencies
 	if len(p.Prebuilt.Properties.Srcs) > 0 {
 		// TODO(ccross): .toc optimization, stripping, packing
-		return p.Prebuilt.Path(ctx)
+
+		// Copy binaries to a name matching the final installed name
+		fileName := p.getStem(ctx) + flags.Toolchain.ExecutableSuffix()
+		outputFile := android.PathForModuleOut(ctx, fileName)
+
+		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+			Rule:        android.Cp,
+			Description: "prebuilt",
+			Output:      outputFile,
+			Input:       p.Prebuilt.Path(ctx),
+		})
+
+		return outputFile
 	}
 
 	return nil
diff --git a/java/androidmk.go b/java/androidmk.go
index 086ba7a..9ccf856 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -15,21 +15,17 @@
 package java
 
 import (
-	"fmt"
-
 	"android/soong/android"
 )
 
-func (*Library) AndroidMk() (ret android.AndroidMkData, err error) {
+func (library *Library) AndroidMk() (ret android.AndroidMkData, err error) {
 	ret.Class = "JAVA_LIBRARIES"
-	// TODO
-	err = fmt.Errorf("Not yet implemented")
+	ret.OutputFile = android.OptionalPathForPath(library.outputFile)
 	return
 }
 
-func (*Prebuilt) AndroidMk() (ret android.AndroidMkData, err error) {
+func (prebuilt *Prebuilt) AndroidMk() (ret android.AndroidMkData, err error) {
 	ret.Class = "JAVA_LIBRARIES"
-	// TODO
-	err = fmt.Errorf("Not yet implemented")
+	ret.OutputFile = android.OptionalPathForPath(prebuilt.classpathFile)
 	return
 }
diff --git a/java/java.go b/java/java.go
index 1ef1c26..f7191bf 100644
--- a/java/java.go
+++ b/java/java.go
@@ -531,6 +531,10 @@
 	return &j.prebuilt
 }
 
+func (j *Prebuilt) Name() string {
+	return j.prebuilt.Name(j.ModuleBase.Name())
+}
+
 func (j *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {
 }
 
diff --git a/java/java_test.go b/java/java_test.go
index 3443610..de3be49 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -57,6 +57,8 @@
 	ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(LibraryFactory))
 	ctx.RegisterModuleType("java_prebuilt_library", android.ModuleFactoryAdaptor(PrebuiltFactory))
 	ctx.RegisterModuleType("java_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
+	ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
+	ctx.PreArchMutators(android.RegisterPrebuiltsPostDepsMutators)
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
 	ctx.Register()
 
diff --git a/root.bp b/root.bp
index 08f2ff8..582552e 100644
--- a/root.bp
+++ b/root.bp
@@ -13,7 +13,7 @@
     "bionic",
     "bootable/recovery",
     "build/kati",
-    "build/tools/*",
+    "build/make/tools/*",
     "dalvik",
     "development/*",
     "device/*/*",
@@ -29,6 +29,7 @@
     "prebuilts/clang/host/linux-x86",
     "prebuilts/ndk",
     "prebuilts/sdk",
+    "prebuilts/misc",
     "system/*",
     "system/hardware/interfaces",
     "system/tools/*",
diff --git a/scripts/build-ndk-prebuilts.sh b/scripts/build-ndk-prebuilts.sh
index 65a2329..f8ce349 100755
--- a/scripts/build-ndk-prebuilts.sh
+++ b/scripts/build-ndk-prebuilts.sh
@@ -9,6 +9,12 @@
 
 source build/envsetup.sh
 PLATFORM_SDK_VERSION=$(get_build_var PLATFORM_SDK_VERSION)
+PLATFORM_VERSION_ALL_CODENAMES=$(get_build_var PLATFORM_VERSION_ALL_CODENAMES)
+
+# PLATFORM_VERSION_ALL_CODESNAMES is a comma separated list like O,P. We need to
+# turn this into ["O","P"].
+PLATFORM_VERSION_ALL_CODENAMES=${PLATFORM_VERSION_ALL_CODENAMES/,/","}
+PLATFORM_VERSION_ALL_CODENAMES="[\"${PLATFORM_VERSION_ALL_CODENAMES}\"]"
 
 SOONG_OUT=${OUT_DIR}/soong
 SOONG_NDK_OUT=${OUT_DIR}/soong/ndk
@@ -16,12 +22,39 @@
 mkdir -p ${SOONG_OUT}
 cat > ${SOONG_OUT}/soong.config << EOF
 {
-    "Ndk_abis": true,
-    "Platform_sdk_version": ${PLATFORM_SDK_VERSION}
+    "Ndk_abis": true
 }
 EOF
-BUILDDIR=${SOONG_OUT} ./bootstrap.bash
-${SOONG_OUT}/soong ${SOONG_OUT}/ndk.timestamp
+
+# We only really need to set some of these variables, but soong won't merge this
+# with the defaults, so we need to write out all the defaults with our values
+# added.
+cat > ${SOONG_OUT}/soong.variables << EOF
+{
+    "Platform_sdk_version": ${PLATFORM_SDK_VERSION},
+    "Platform_version_active_codenames": ${PLATFORM_VERSION_ALL_CODENAMES},
+
+    "DeviceName": "flounder",
+    "DeviceArch": "arm64",
+    "DeviceArchVariant": "armv8-a",
+    "DeviceCpuVariant": "denver64",
+    "DeviceAbi": [
+        "arm64-v8a"
+    ],
+    "DeviceUsesClang": true,
+    "DeviceSecondaryArch": "arm",
+    "DeviceSecondaryArchVariant": "armv7-a-neon",
+    "DeviceSecondaryCpuVariant": "denver",
+    "DeviceSecondaryAbi": [
+        "armeabi-v7a"
+    ],
+    "HostArch": "x86_64",
+    "HostSecondaryArch": "x86",
+    "Malloc_not_svelte": false,
+    "Safestack": false
+}
+EOF
+m --skip-make ${SOONG_OUT}/ndk.timestamp
 
 if [ -n "${DIST_DIR}" ]; then
     mkdir -p ${DIST_DIR} || true
diff --git a/soong.bash b/soong.bash
index 1dbf4e4..d832eb2 100755
--- a/soong.bash
+++ b/soong.bash
@@ -5,6 +5,14 @@
 # Switch to the build directory
 cd $(dirname "${BASH_SOURCE[0]}")
 
+if [ -z "$NO_DEPRECATION_WARNING" ]; then
+    echo '== WARNING: bootstrap.bash & ./soong are deprecated ==' >&2
+    echo 'Use `m --skip-make` with a standalone OUT_DIR instead.' >&2
+    echo 'Without envsetup.sh, use:' >&2
+    echo '  build/soong/soong_ui.bash --make-mode --skip-make' >&2
+    echo '======================================================' >&2
+fi
+
 # The source directory path and operating system will get written to
 # .soong.bootstrap by the bootstrap script.
 
diff --git a/ui/build/build.go b/ui/build/build.go
index 32f4ba5..9650eaa 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -26,7 +26,9 @@
 func SetupOutDir(ctx Context, config Config) {
 	ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "Android.mk"))
 	ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "CleanSpec.mk"))
-	ensureEmptyFileExists(ctx, filepath.Join(config.SoongOutDir(), ".soong.in_make"))
+	if !config.SkipMake() {
+		ensureEmptyFileExists(ctx, filepath.Join(config.SoongOutDir(), ".soong.in_make"))
+	}
 	// The ninja_build file is used by our buildbots to understand that the output
 	// can be parsed as ninja output.
 	ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "ninja_build"))
@@ -34,12 +36,20 @@
 
 var combinedBuildNinjaTemplate = template.Must(template.New("combined").Parse(`
 builddir = {{.OutDir}}
-include {{.KatiNinjaFile}}
+{{if .HasKatiSuffix}}include {{.KatiNinjaFile}}
+{{end -}}
 include {{.SoongNinjaFile}}
 build {{.CombinedNinjaFile}}: phony {{.SoongNinjaFile}}
 `))
 
 func createCombinedBuildNinjaFile(ctx Context, config Config) {
+	// If we're in SkipMake mode, skip creating this file if it already exists
+	if config.SkipMake() {
+		if _, err := os.Stat(config.CombinedNinjaFile()); err == nil || !os.IsNotExist(err) {
+			return
+		}
+	}
+
 	file, err := os.Create(config.CombinedNinjaFile())
 	if err != nil {
 		ctx.Fatalln("Failed to create combined ninja file:", err)
@@ -92,8 +102,7 @@
 }
 
 func help(ctx Context, config Config, what int) {
-	cmd := Command(ctx, config, "make",
-		"make", "-f", "build/core/help.mk")
+	cmd := Command(ctx, config, "help.sh", "build/make/help.sh")
 	cmd.Sandbox = makeSandbox
 	cmd.Stdout = ctx.Stdout()
 	cmd.Stderr = ctx.Stderr()
@@ -106,6 +115,11 @@
 	ctx.Verboseln("Starting build with args:", config.Arguments())
 	ctx.Verboseln("Environment:", config.Environment().Environ())
 
+	if config.SkipMake() {
+		ctx.Verboseln("Skipping Make/Kati as requested")
+		what = what & (BuildSoong | BuildNinja)
+	}
+
 	if inList("help", config.Arguments()) {
 		help(ctx, config, what)
 		return
@@ -148,10 +162,20 @@
 	if what&BuildKati != 0 {
 		// Run ckati
 		runKati(ctx, config)
+
+		ioutil.WriteFile(config.LastKatiSuffixFile(), []byte(config.KatiSuffix()), 0777)
+	} else {
+		// Load last Kati Suffix if it exists
+		if katiSuffix, err := ioutil.ReadFile(config.LastKatiSuffixFile()); err == nil {
+			ctx.Verboseln("Loaded previous kati config:", string(katiSuffix))
+			config.SetKatiSuffix(string(katiSuffix))
+		}
 	}
 
 	if what&BuildNinja != 0 {
-		installCleanIfNecessary(ctx, config)
+		if !config.SkipMake() {
+			installCleanIfNecessary(ctx, config)
+		}
 
 		// Write combined ninja file
 		createCombinedBuildNinjaFile(ctx, config)
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index 2967c3a..f2de2cd 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -129,6 +129,8 @@
 	suffix := "\n"
 	currentProduct := prefix + config.TargetProduct() + "-" + config.TargetBuildVariant() + suffix
 
+	ensureDirectoriesExist(ctx, filepath.Dir(configFile))
+
 	writeConfig := func() {
 		err := ioutil.WriteFile(configFile, []byte(currentProduct), 0666)
 		if err != nil {
diff --git a/ui/build/config.go b/ui/build/config.go
index ef06157..045f674 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -38,6 +38,7 @@
 	keepGoing int
 	verbose   bool
 	dist      bool
+	skipMake  bool
 
 	// From the product config
 	katiArgs     []string
@@ -149,14 +150,11 @@
 	for i := 0; i < len(args); i++ {
 		arg := strings.TrimSpace(args[i])
 		if arg == "--make-mode" {
-			continue
 		} else if arg == "showcommands" {
 			c.verbose = true
-			continue
-		} else if arg == "dist" {
-			c.dist = true
-		}
-		if arg[0] == '-' {
+		} else if arg == "--skip-make" {
+			c.skipMake = true
+		} else if arg[0] == '-' {
 			parseArgNum := func(def int) int {
 				if len(arg) > 2 {
 					p, err := strconv.ParseUint(arg[2:], 10, 31)
@@ -184,6 +182,9 @@
 		} else if k, v, ok := decodeKeyValue(arg); ok && len(k) > 0 {
 			c.environ.Set(k, v)
 		} else {
+			if arg == "dist" {
+				c.dist = true
+			}
 			c.arguments = append(c.arguments, arg)
 		}
 	}
@@ -265,6 +266,9 @@
 }
 
 func (c *configImpl) NinjaArgs() []string {
+	if c.skipMake {
+		return c.arguments
+	}
 	return c.ninjaArgs
 }
 
@@ -291,6 +295,10 @@
 	return c.verbose
 }
 
+func (c *configImpl) SkipMake() bool {
+	return c.skipMake
+}
+
 func (c *configImpl) TargetProduct() string {
 	if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
 		return v
@@ -355,6 +363,14 @@
 	c.katiSuffix = suffix
 }
 
+func (c *configImpl) LastKatiSuffixFile() string {
+	return filepath.Join(c.OutDir(), "last_kati_suffix")
+}
+
+func (c *configImpl) HasKatiSuffix() bool {
+	return c.katiSuffix != ""
+}
+
 func (c *configImpl) KatiEnvFile() string {
 	return filepath.Join(c.OutDir(), "env"+c.KatiSuffix()+".sh")
 }
@@ -368,6 +384,9 @@
 }
 
 func (c *configImpl) CombinedNinjaFile() string {
+	if c.katiSuffix == "" {
+		return filepath.Join(c.OutDir(), "combined.ninja")
+	}
 	return filepath.Join(c.OutDir(), "combined"+c.KatiSuffix()+".ninja")
 }
 
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index 78d1170..96b5e9d 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -53,7 +53,9 @@
 	args = append(args, "-w", "dupbuild=err")
 
 	cmd := Command(ctx, config, "ninja", executable, args...)
-	cmd.Environment.AppendFromKati(config.KatiEnvFile())
+	if config.HasKatiSuffix() {
+		cmd.Environment.AppendFromKati(config.KatiEnvFile())
+	}
 
 	// Allow both NINJA_ARGS and NINJA_EXTRA_ARGS, since both have been
 	// used in the past to specify extra ninja arguments.
diff --git a/ui/build/soong.go b/ui/build/soong.go
index d242805..2af3616 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -25,6 +25,7 @@
 	cmd := Command(ctx, config, "soong bootstrap", "./bootstrap.bash")
 	cmd.Environment.Set("BUILDDIR", config.SoongOutDir())
 	cmd.Environment.Set("NINJA_BUILDDIR", config.OutDir())
+	cmd.Environment.Set("NO_DEPRECATION_WARNING", "true")
 	cmd.Sandbox = soongSandbox
 	cmd.Stdout = ctx.Stdout()
 	cmd.Stderr = ctx.Stderr()
@@ -41,6 +42,7 @@
 		cmd.Args = append(cmd.Args, "-v")
 	}
 	cmd.Environment.Set("SKIP_NINJA", "true")
+	cmd.Environment.Set("NO_DEPRECATION_WARNING", "true")
 	cmd.Sandbox = soongSandbox
 	cmd.Stdin = ctx.Stdin()
 	cmd.Stdout = ctx.Stdout()