Refactor Kati logic

Make the cleanspec & Android.mk runs of kati use much of the same code
and arguments.

Also renames 'Kati' to 'KatiBuild' in many cases, in the the expectation
that we'll have a 'KatiPackage' step in the future.

Use --no_ninja_prelude and move local_pool & _kati_always_build_ into
the combined ninja file. This will reduce the need to re-read makefiles
when Goma is enabled, and it allows us to include more than one
Kati-generated ninja file in the build graph.

Bug: 116968624
Test: build_test on downstream branches
Change-Id: Ibdac689b81f62dc293647fad917d84946f2c3cfa
diff --git a/ui/build/build.go b/ui/build/build.go
index 52ef005..377481b 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -37,7 +37,10 @@
 
 var combinedBuildNinjaTemplate = template.Must(template.New("combined").Parse(`
 builddir = {{.OutDir}}
-{{if .HasKatiSuffix}}include {{.KatiNinjaFile}}
+pool local_pool
+ depth = {{.Parallel}}
+build _kati_always_build_: phony
+{{if .HasKatiSuffix}}include {{.KatiBuildNinjaFile}}
 {{end -}}
 include {{.SoongNinjaFile}}
 `))
@@ -174,7 +177,9 @@
 
 	if what&BuildKati != 0 {
 		// Run ckati
-		runKati(ctx, config)
+		genKatiSuffix(ctx, config)
+		runKatiCleanSpec(ctx, config)
+		runKatiBuild(ctx, config)
 
 		ioutil.WriteFile(config.LastKatiSuffixFile(), []byte(config.KatiSuffix()), 0777)
 	} else {
diff --git a/ui/build/config.go b/ui/build/config.go
index fdeb8f2..d470b96 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -501,8 +501,8 @@
 	return filepath.Join(c.OutDir(), "env"+c.KatiSuffix()+".sh")
 }
 
-func (c *configImpl) KatiNinjaFile() string {
-	return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+".ninja")
+func (c *configImpl) KatiBuildNinjaFile() string {
+	return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiBuildSuffix+".ninja")
 }
 
 func (c *configImpl) SoongNinjaFile() string {
diff --git a/ui/build/kati.go b/ui/build/kati.go
index b26d673..546fd1a 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -19,7 +19,6 @@
 	"fmt"
 	"io/ioutil"
 	"path/filepath"
-	"strconv"
 	"strings"
 
 	"android/soong/ui/status"
@@ -27,6 +26,9 @@
 
 var spaceSlashReplacer = strings.NewReplacer("/", "_", " ", "_")
 
+const katiBuildSuffix = ""
+const katiCleanspecSuffix = "-cleanspec"
+
 // genKatiSuffix creates a suffix for kati-generated files so that we can cache
 // them based on their inputs. So this should encode all common changes to Kati
 // inputs. Currently that includes the TARGET_PRODUCT, kati-processed command
@@ -49,7 +51,7 @@
 		ctx.Verbosef("Kati ninja suffix too long: %q", katiSuffix)
 		ctx.Verbosef("Replacing with: %q", shortSuffix)
 
-		if err := ioutil.WriteFile(strings.TrimSuffix(config.KatiNinjaFile(), "ninja")+"suf", []byte(katiSuffix), 0777); err != nil {
+		if err := ioutil.WriteFile(strings.TrimSuffix(config.KatiBuildNinjaFile(), "ninja")+"suf", []byte(katiSuffix), 0777); err != nil {
 			ctx.Println("Error writing suffix file:", err)
 		}
 	} else {
@@ -57,30 +59,49 @@
 	}
 }
 
-func runKati(ctx Context, config Config) {
-	genKatiSuffix(ctx, config)
-
-	runKatiCleanSpec(ctx, config)
-
-	ctx.BeginTrace("kati")
-	defer ctx.EndTrace()
-
+func runKati(ctx Context, config Config, extraSuffix string, args []string) {
 	executable := config.PrebuiltBuildTool("ckati")
-	args := []string{
+	args = append([]string{
 		"--ninja",
 		"--ninja_dir=" + config.OutDir(),
-		"--ninja_suffix=" + config.KatiSuffix(),
+		"--ninja_suffix=" + config.KatiSuffix() + extraSuffix,
+		"--no_ninja_prelude",
 		"--regen",
 		"--ignore_optional_include=" + filepath.Join(config.OutDir(), "%.P"),
 		"--detect_android_echo",
 		"--color_warnings",
 		"--gen_all_targets",
+		"--use_find_emulator",
 		"--werror_find_emulator",
 		"--no_builtin_rules",
 		"--werror_suffix_rules",
 		"--warn_real_to_phony",
 		"--warn_phony_looks_real",
 		"--kati_stats",
+	}, args...)
+
+	args = append(args,
+		"SOONG_MAKEVARS_MK="+config.SoongMakeVarsMk(),
+		"TARGET_DEVICE_DIR="+config.TargetDeviceDir())
+
+	cmd := Command(ctx, config, "ckati", executable, args...)
+	cmd.Sandbox = katiSandbox
+	pipe, err := cmd.StdoutPipe()
+	if err != nil {
+		ctx.Fatalln("Error getting output pipe for ckati:", err)
+	}
+	cmd.Stderr = cmd.Stdout
+
+	cmd.StartOrFatal()
+	status.KatiReader(ctx.Status.StartTool(), pipe)
+	cmd.WaitOrFatal()
+}
+
+func runKatiBuild(ctx Context, config Config) {
+	ctx.BeginTrace("kati build")
+	defer ctx.EndTrace()
+
+	args := []string{
 		"--writable", config.OutDir() + "/",
 		"--writable", config.DistDir() + "/",
 		"-f", "build/make/core/main.mk",
@@ -102,67 +123,20 @@
 			"--werror_writable")
 	}
 
-	if !config.Environment().IsFalse("KATI_EMULATE_FIND") {
-		args = append(args, "--use_find_emulator")
-	}
-
 	args = append(args, config.KatiArgs()...)
 
-	args = append(args,
-		"BUILDING_WITH_NINJA=true",
-		"SOONG_ANDROID_MK="+config.SoongAndroidMk(),
-		"SOONG_MAKEVARS_MK="+config.SoongMakeVarsMk(),
-		"TARGET_DEVICE_DIR="+config.TargetDeviceDir())
+	args = append(args, "SOONG_ANDROID_MK="+config.SoongAndroidMk())
 
-	if config.UseGoma() {
-		args = append(args, "-j"+strconv.Itoa(config.Parallel()))
-	}
-
-	cmd := Command(ctx, config, "ckati", executable, args...)
-	cmd.Sandbox = katiSandbox
-	pipe, err := cmd.StdoutPipe()
-	if err != nil {
-		ctx.Fatalln("Error getting output pipe for ckati:", err)
-	}
-	cmd.Stderr = cmd.Stdout
-
-	cmd.StartOrFatal()
-	status.KatiReader(ctx.Status.StartTool(), pipe)
-	cmd.WaitOrFatal()
+	runKati(ctx, config, katiBuildSuffix, args)
 }
 
 func runKatiCleanSpec(ctx Context, config Config) {
 	ctx.BeginTrace("kati cleanspec")
 	defer ctx.EndTrace()
 
-	executable := config.PrebuiltBuildTool("ckati")
-	args := []string{
-		"--ninja",
-		"--ninja_dir=" + config.OutDir(),
-		"--ninja_suffix=" + config.KatiSuffix() + "-cleanspec",
-		"--regen",
-		"--detect_android_echo",
-		"--color_warnings",
-		"--gen_all_targets",
-		"--werror_find_emulator",
+	runKati(ctx, config, katiCleanspecSuffix, []string{
+		"--werror_implicit_rules",
 		"--werror_overriding_commands",
-		"--use_find_emulator",
-		"--kati_stats",
 		"-f", "build/make/core/cleanbuild.mk",
-		"BUILDING_WITH_NINJA=true",
-		"SOONG_MAKEVARS_MK=" + config.SoongMakeVarsMk(),
-		"TARGET_DEVICE_DIR=" + config.TargetDeviceDir(),
-	}
-
-	cmd := Command(ctx, config, "ckati", executable, args...)
-	cmd.Sandbox = katiCleanSpecSandbox
-	pipe, err := cmd.StdoutPipe()
-	if err != nil {
-		ctx.Fatalln("Error getting output pipe for ckati:", err)
-	}
-	cmd.Stderr = cmd.Stdout
-
-	cmd.StartOrFatal()
-	status.KatiReader(ctx.Status.StartTool(), pipe)
-	cmd.WaitOrFatal()
+	})
 }