Allow multiple ninja implementations

This permits easier testing and comparison between different ninja
implementations.

Bug: 362926979
Bug: 318434287
Test: manual
Change-Id: Ic058338d0a2fd8c988794a0781dcc93c0f4c03e3
diff --git a/ui/build/config.go b/ui/build/config.go
index f02222e..79f57ac 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -54,6 +54,16 @@
 	rbeRandPrefix = rand.Intn(1000)
 }
 
+// Which builder are we using?
+type ninjaCommandType = int
+
+const (
+	_ = iota
+	NINJA_NINJA
+	NINJA_N2
+	NINJA_SISO
+)
+
 type Config struct{ *configImpl }
 
 type configImpl struct {
@@ -123,9 +133,8 @@
 	// could consider merging them.
 	moduleDebugFile string
 
-	// Whether to use n2 instead of ninja.  This is controlled with the
-	// environment variable SOONG_USE_N2
-	useN2 bool
+	// Which builder are we using
+	ninjaCommand ninjaCommandType
 }
 
 type NinjaWeightListSource uint
@@ -288,8 +297,16 @@
 		ret.moduleDebugFile, _ = filepath.Abs(shared.JoinPath(ret.SoongOutDir(), "soong-debug-info.json"))
 	}
 
-	if os.Getenv("SOONG_USE_N2") == "true" {
-		ret.useN2 = true
+	ret.ninjaCommand = NINJA_NINJA
+	switch os.Getenv("SOONG_NINJA") {
+	case "n2":
+		ret.ninjaCommand = NINJA_N2
+	case "siso":
+		ret.ninjaCommand = NINJA_SISO
+	default:
+		if os.Getenv("SOONG_USE_N2") == "true" {
+			ret.ninjaCommand = NINJA_N2
+		}
 	}
 
 	ret.environ.Unset(
@@ -349,7 +366,8 @@
 		// We read it here already, don't let others share in the fun
 		"GENERATE_SOONG_DEBUG",
 
-		// Use config.useN2 instead.
+		// Use config.ninjaCommand instead.
+		"SOONG_NINJA",
 		"SOONG_USE_N2",
 	)
 
@@ -1641,6 +1659,12 @@
 	return strings.ReplaceAll(path, "/linux-x86/", "/linux_musl-x86/")
 }
 
+func (c *configImpl) SisoBin() string {
+	path := c.PrebuiltBuildTool("siso")
+	// Use musl instead of glibc because glibc on the build server is old and has bugs
+	return strings.ReplaceAll(path, "/linux-x86/", "/linux_musl-x86/")
+}
+
 func (c *configImpl) PrebuiltBuildTool(name string) string {
 	if v, ok := c.environ.Get("SANITIZE_HOST"); ok {
 		if sanitize := strings.Fields(v); inList("address", sanitize) {