Mixed bazel/soong build prototype for genrule

With this change, bazel_module is a specifiable property on
genrule module definitions. With bazel-enabled mode, soong_build will
defer to Bazel for information on these modules.

source build/soong/bazelenv.sh to enter bazel-enabled mode.

Test: Manually verified on bionic/libc genrules using aosp_cf_x86_phone-userdebug
Change-Id: I3619848186d50be7273a5eba31c79989b981d408
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 01a39a2..7ae1c37 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -51,30 +51,34 @@
 	return android.NewNameResolver(exportFilter)
 }
 
+func newContext(srcDir string, configuration android.Config) *android.Context {
+	ctx := android.NewContext()
+	ctx.Register()
+	if !shouldPrepareBuildActions() {
+		configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions)
+	}
+	ctx.SetNameInterface(newNameResolver(configuration))
+	ctx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
+	return ctx
+}
+
+func newConfig(srcDir string) android.Config {
+	configuration, err := android.NewConfig(srcDir, bootstrap.BuildDir, bootstrap.ModuleListFile)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "%s", err)
+		os.Exit(1)
+	}
+	return configuration
+}
+
 func main() {
 	android.ReexecWithDelveMaybe()
 	flag.Parse()
 
 	// The top-level Blueprints file is passed as the first argument.
 	srcDir := filepath.Dir(flag.Arg(0))
-
-	ctx := android.NewContext()
-	ctx.Register()
-
-	configuration, err := android.NewConfig(srcDir, bootstrap.BuildDir, bootstrap.ModuleListFile)
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "%s", err)
-		os.Exit(1)
-	}
-
-	if !shouldPrepareBuildActions() {
-		configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions)
-	}
-
-	ctx.SetNameInterface(newNameResolver(configuration))
-
-	ctx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
-
+	var ctx *android.Context
+	configuration := newConfig(srcDir)
 	extraNinjaDeps := []string{configuration.ConfigFileName, configuration.ProductVariablesFileName}
 
 	// Read the SOONG_DELVE again through configuration so that there is a dependency on the environment variable
@@ -84,9 +88,31 @@
 		// enabled even if it completed successfully.
 		extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.BuildDir(), "always_rerun_for_delve"))
 	}
-
-	bootstrap.Main(ctx.Context, configuration, extraNinjaDeps...)
-
+	if configuration.BazelContext.BazelEnabled() {
+		// Bazel-enabled mode. Soong runs in two passes.
+		// First pass: Analyze the build tree, but only store all bazel commands
+		// needed to correctly evaluate the tree in the second pass.
+		// TODO(cparsons): Don't output any ninja file, as the second pass will overwrite
+		// the incorrect results from the first pass, and file I/O is expensive.
+		firstCtx := newContext(srcDir, configuration)
+		bootstrap.Main(firstCtx.Context, configuration, extraNinjaDeps...)
+		// Invoke bazel commands and save results for second pass.
+		if err := configuration.BazelContext.InvokeBazel(); err != nil {
+			fmt.Fprintf(os.Stderr, "%s", err)
+			os.Exit(1)
+		}
+		// Second pass: Full analysis, using the bazel command results. Output ninja file.
+		secondPassConfig, err := android.ConfigForAdditionalRun(configuration)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "%s", err)
+			os.Exit(1)
+		}
+		ctx = newContext(srcDir, secondPassConfig)
+		bootstrap.Main(ctx.Context, secondPassConfig, extraNinjaDeps...)
+	} else {
+		ctx = newContext(srcDir, configuration)
+		bootstrap.Main(ctx.Context, configuration, extraNinjaDeps...)
+	}
 	if bazelOverlayDir != "" {
 		if err := createBazelOverlay(ctx, bazelOverlayDir); err != nil {
 			fmt.Fprintf(os.Stderr, "%s", err)
@@ -105,7 +131,7 @@
 	//  to affect the command line of the primary builder.
 	if shouldPrepareBuildActions() {
 		metricsFile := filepath.Join(bootstrap.BuildDir, "soong_build_metrics.pb")
-		err = android.WriteMetrics(configuration, metricsFile)
+		err := android.WriteMetrics(configuration, metricsFile)
 		if err != nil {
 			fmt.Fprintf(os.Stderr, "error writing soong_build metrics %s: %s", metricsFile, err)
 			os.Exit(1)