Obsolete bootstrap.bash and ./soong wrappers

We can call directly into the blueprint bootstrap.bash using values that
soong_ui has already calculated.

Instead of calling into blueprint.bash, build minibp with microfactory,
and directly run ninja. This allows us to get individual tracing data
from each component.

Test: m -j blueprint_tools
Test: m clean; m -j blueprint_tools
Change-Id: I2239943c9a8a3ad6e1a40fa0dc914421f4b5202c
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 2af3616..8220597 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -15,37 +15,101 @@
 package build
 
 import (
+	"os"
 	"path/filepath"
+	"strconv"
+	"time"
+
+	"github.com/google/blueprint/microfactory"
 )
 
-func runSoongBootstrap(ctx Context, config Config) {
-	ctx.BeginTrace("bootstrap soong")
-	defer ctx.EndTrace()
-
-	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()
-	cmd.RunOrFatal()
-}
-
 func runSoong(ctx Context, config Config) {
 	ctx.BeginTrace("soong")
 	defer ctx.EndTrace()
 
-	cmd := Command(ctx, config, "soong",
-		filepath.Join(config.SoongOutDir(), "soong"), "-w", "dupbuild=err")
-	if config.IsVerbose() {
-		cmd.Args = append(cmd.Args, "-v")
+	func() {
+		ctx.BeginTrace("blueprint bootstrap")
+		defer ctx.EndTrace()
+
+		cmd := Command(ctx, config, "blueprint bootstrap", "build/blueprint/bootstrap.bash", "-t")
+		cmd.Environment.Set("BLUEPRINTDIR", "./build/blueprint")
+		cmd.Environment.Set("BOOTSTRAP", "./build/blueprint/bootstrap.bash")
+		cmd.Environment.Set("BUILDDIR", config.SoongOutDir())
+		cmd.Environment.Set("GOROOT", filepath.Join("./prebuilts/go", config.HostPrebuiltTag()))
+		cmd.Environment.Set("NINJA_BUILDDIR", config.OutDir())
+		cmd.Environment.Set("SRCDIR", ".")
+		cmd.Environment.Set("TOPNAME", "Android.bp")
+		cmd.Sandbox = soongSandbox
+		cmd.Stdout = ctx.Stdout()
+		cmd.Stderr = ctx.Stderr()
+		cmd.RunOrFatal()
+	}()
+
+	func() {
+		ctx.BeginTrace("environment check")
+		defer ctx.EndTrace()
+
+		envFile := filepath.Join(config.SoongOutDir(), ".soong.environment")
+		envTool := filepath.Join(config.SoongOutDir(), ".bootstrap/bin/soong_env")
+		if _, err := os.Stat(envFile); err == nil {
+			if _, err := os.Stat(envTool); err == nil {
+				cmd := Command(ctx, config, "soong_env", envTool, envFile)
+				cmd.Sandbox = soongSandbox
+				cmd.Stdout = ctx.Stdout()
+				cmd.Stderr = ctx.Stderr()
+				if err := cmd.Run(); err != nil {
+					ctx.Verboseln("soong_env failed, forcing manifest regeneration")
+					os.Remove(envFile)
+				}
+			} else {
+				ctx.Verboseln("Missing soong_env tool, forcing manifest regeneration")
+				os.Remove(envFile)
+			}
+		} else if !os.IsNotExist(err) {
+			ctx.Fatalf("Failed to stat %f: %v", envFile, err)
+		}
+	}()
+
+	func() {
+		ctx.BeginTrace("minibp")
+		defer ctx.EndTrace()
+
+		var cfg microfactory.Config
+		cfg.Map("github.com/google/blueprint", "build/blueprint")
+
+		if absPath, err := filepath.Abs("."); err == nil {
+			cfg.TrimPath = absPath
+		}
+
+		minibp := filepath.Join(config.SoongOutDir(), ".minibootstrap/minibp")
+		if _, err := microfactory.Build(&cfg, minibp, "github.com/google/blueprint/bootstrap/minibp"); err != nil {
+			ctx.Fatalln("Failed to build minibp:", err)
+		}
+	}()
+
+	ninja := func(name, file string) {
+		ctx.BeginTrace(name)
+		defer ctx.EndTrace()
+
+		cmd := Command(ctx, config, "soong "+name,
+			config.PrebuiltBuildTool("ninja"),
+			"-d", "keepdepfile",
+			"-w", "dupbuild=err",
+			"-j", strconv.Itoa(config.Parallel()),
+			"-f", filepath.Join(config.SoongOutDir(), file))
+		if config.IsVerbose() {
+			cmd.Args = append(cmd.Args, "-v")
+		}
+		cmd.Environment.Set("GOROOT", filepath.Join("./prebuilts/go", config.HostPrebuiltTag()))
+		cmd.Sandbox = soongSandbox
+		cmd.Stdin = ctx.Stdin()
+		cmd.Stdout = ctx.Stdout()
+		cmd.Stderr = ctx.Stderr()
+
+		defer ctx.ImportNinjaLog(filepath.Join(config.OutDir(), ".ninja_log"), time.Now())
+		cmd.RunOrFatal()
 	}
-	cmd.Environment.Set("SKIP_NINJA", "true")
-	cmd.Environment.Set("NO_DEPRECATION_WARNING", "true")
-	cmd.Sandbox = soongSandbox
-	cmd.Stdin = ctx.Stdin()
-	cmd.Stdout = ctx.Stdout()
-	cmd.Stderr = ctx.Stderr()
-	cmd.RunOrFatal()
+
+	ninja("minibootstrap", ".minibootstrap/build.ninja")
+	ninja("bootstrap", ".bootstrap/build.ninja")
 }