Update SOONG_PARTIAL_COMPILE logic

Separate PARTIAL_COMPILE changes that affect analysis from actually
using it.

- SOONG_PARTIAL_COMPILE affects how we generate the Ninja file.  Changes
  to this cause reanalysis.

- SOONG_USE_PARTIAL_COMPILE is used in the rules to determine if we use
  the PARTIAL_COMPILE implementation, or the legacy rules.  This means
  that the developer can switch between full compiles and partial
  compiles at will without waiting for analysis to happen each time they
  change it.

Bug: b/365536323
Test: manual
Change-Id: Icb06687d17f63edb22bf2457a659b452537dadba
diff --git a/ui/build/config.go b/ui/build/config.go
index 75edfcd..9ec04a0 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -98,7 +98,6 @@
 	buildFromSourceStub      bool
 	incrementalBuildActions  bool
 	ensureAllowlistIntegrity bool // For CI builds - make sure modules are mixed-built
-	partialCompileFlags      partialCompileFlags
 
 	// From the product config
 	katiArgs        []string
@@ -138,16 +137,6 @@
 	ninjaCommand ninjaCommandType
 }
 
-type partialCompileFlags struct {
-	// Is partial compilation enabled at all?
-	enabled bool
-
-	// Whether to use d8 instead of r8
-	use_d8 bool
-
-	// Add others as needed.
-}
-
 type NinjaWeightListSource uint
 
 const (
@@ -304,12 +293,24 @@
 		ret.sandboxConfig.SetSrcDirIsRO(srcDirIsWritable == "false")
 	}
 
-	ret.partialCompileFlags = parsePartialCompileFlags(ctx)
-
 	if os.Getenv("GENERATE_SOONG_DEBUG") == "true" {
 		ret.moduleDebugFile, _ = filepath.Abs(shared.JoinPath(ret.SoongOutDir(), "soong-debug-info.json"))
 	}
 
+	// If SOONG_USE_PARTIAL_COMPILE is set, make it one of "true" or the empty string.
+	// This simplifies the generated Ninja rules, so that they only need to check for the empty string.
+	if value, ok := os.LookupEnv("SOONG_USE_PARTIAL_COMPILE"); ok {
+		if value == "true" || value == "1" || value == "y" || value == "yes" {
+			value = "true"
+		} else {
+			value = ""
+		}
+		err = os.Setenv("SOONG_USE_PARTIAL_COMPILE", value)
+		if err != nil {
+			ctx.Fatalln("Failed to set SOONG_USE_PARTIAL_COMPILE: %v", err)
+		}
+	}
+
 	ret.ninjaCommand = NINJA_NINJA
 	switch os.Getenv("SOONG_NINJA") {
 	case "n2":
@@ -382,7 +383,6 @@
 		// Use config.ninjaCommand instead.
 		"SOONG_NINJA",
 		"SOONG_USE_N2",
-		"SOONG_PARTIAL_COMPILE",
 	)
 
 	if ret.UseGoma() || ret.ForceUseGoma() {
@@ -501,78 +501,6 @@
 	return c
 }
 
-// Parse SOONG_PARTIAL_COMPILE.
-//
-// The user-facing documentation shows:
-//
-// - empty or not set: "The current default state"
-// - "true" or "on": enable all stable partial compile features.
-// - "false" or "off": disable partial compile completely.
-//
-// What we actually allow is a comma separated list of tokens, whose first
-// character may be "+" (enable) or "-" (disable).  If neither is present, "+"
-// is assumed.  For example, "on,+use_d8" will enable partial compilation, and
-// additionally set the use_d8 flag (regardless of whether it is opt-in or
-// opt-out).
-//
-// To add a new feature to the list, add the field in the struct
-// `partialCompileFlags` above, and then add the name of the field in the
-// switch statement below.
-func parsePartialCompileFlags(ctx Context) partialCompileFlags {
-	defaultFlags := partialCompileFlags{
-		// Set any opt-out flags here.  Opt-in flags are off by default.
-		enabled: false,
-	}
-	value, ok := os.LookupEnv("SOONG_PARTIAL_COMPILE")
-
-	if !ok {
-		return defaultFlags
-	}
-
-	ret := defaultFlags
-	tokens := strings.Split(strings.ToLower(value), ",")
-	makeVal := func(state string, defaultValue bool) bool {
-		switch state {
-		case "":
-			return defaultValue
-		case "-":
-			return false
-		case "+":
-			return true
-		}
-		return false
-	}
-	for _, tok := range tokens {
-		var state string
-		switch tok[0:1] {
-		case "":
-			// Ignore empty tokens.
-			continue
-		case "-", "+":
-			state = tok[0:1]
-			tok = tok[1:]
-		default:
-			// Treat `feature` as `+feature`.
-			state = "+"
-		}
-		switch tok {
-		case "true", "on", "yes":
-			ret = defaultFlags
-			ret.enabled = true
-		case "false", "off", "no":
-			// Set everything to false.
-			ret = partialCompileFlags{}
-		case "enabled":
-			ret.enabled = makeVal(state, defaultFlags.enabled)
-		case "use_d8":
-			ret.use_d8 = makeVal(state, defaultFlags.use_d8)
-		default:
-			ctx.Fatalln("Unknown SOONG_PARTIAL_COMPILE value:", value)
-		}
-	}
-	return ret
-}
-
 // NewBuildActionConfig returns a build configuration based on the build action. The arguments are
 // processed based on the build action and extracts any arguments that belongs to the build action.
 func NewBuildActionConfig(action BuildAction, dir string, ctx Context, args ...string) Config {
@@ -1855,10 +1783,6 @@
 	return c.ensureAllowlistIntegrity
 }
 
-func (c *configImpl) PartialCompileFlags() partialCompileFlags {
-	return c.partialCompileFlags
-}
-
 // Returns a Time object if one was passed via a command-line flag.
 // Otherwise returns the passed default.
 func (c *configImpl) BuildStartedTimeOrDefault(defaultTime time.Time) time.Time {