Merge "Fix ASAN mutator."
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/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/root.bp b/root.bp
index 7e22a55..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/*/*",
diff --git a/scripts/build-ndk-prebuilts.sh b/scripts/build-ndk-prebuilts.sh
index 2a1c7df..f8ce349 100755
--- a/scripts/build-ndk-prebuilts.sh
+++ b/scripts/build-ndk-prebuilts.sh
@@ -54,8 +54,7 @@
     "Safestack": false
 }
 EOF
-BUILDDIR=${SOONG_OUT} ./bootstrap.bash
-${SOONG_OUT}/soong ${SOONG_OUT}/ndk.timestamp
+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()