Add startup flag, --incompatible_enable_execution_transition, which will enable incremental migration of host attributes to exec attributes.

This has to be a startup flag because it will influence rule creation. Changing this flag will completely restart the Blaze server.

Part of work on execution transitions, #7935.

RELNOTES: Adds --incompatible_enable_execution_transition, which enables incremental migration of host attributes to exec attributes.
PiperOrigin-RevId: 256990772
diff --git a/src/main/cpp/bazel_startup_options.cc b/src/main/cpp/bazel_startup_options.cc
index 2ec8c8c..502bcf6 100644
--- a/src/main/cpp/bazel_startup_options.cc
+++ b/src/main/cpp/bazel_startup_options.cc
@@ -137,4 +137,9 @@
   }
 }
 
+void BazelStartupOptions::AddExtraOptions(
+    std::vector<std::string> *result) const {
+  StartupOptions::AddExtraOptions(result);
+}
+
 }  // namespace blaze
diff --git a/src/main/cpp/bazel_startup_options.h b/src/main/cpp/bazel_startup_options.h
index d84cfd2..db82530 100644
--- a/src/main/cpp/bazel_startup_options.h
+++ b/src/main/cpp/bazel_startup_options.h
@@ -26,6 +26,8 @@
  public:
   explicit BazelStartupOptions(const WorkspaceLayout *workspace_layout);
 
+  void AddExtraOptions(std::vector<std::string> *result) const override;
+
   blaze_exit_code::ExitCode ProcessArgExtra(
       const char *arg, const char *next_arg, const std::string &rcfile,
       const char **value, bool *is_processed, std::string *error) override;
diff --git a/src/main/cpp/startup_options.cc b/src/main/cpp/startup_options.cc
index 0528522..b0348db 100644
--- a/src/main/cpp/startup_options.cc
+++ b/src/main/cpp/startup_options.cc
@@ -100,7 +100,8 @@
 #if defined(__APPLE__)
       macos_qos_class(QOS_CLASS_DEFAULT),
 #endif
-      unlimit_coredumps(false) {
+      unlimit_coredumps(false),
+      incompatible_enable_execution_transition(false) {
   if (blaze::IsRunningWithinTest()) {
     output_root = blaze_util::MakeAbsolute(blaze::GetPathEnv("TEST_TMPDIR"));
     max_idle_secs = 15;
@@ -140,6 +141,7 @@
   RegisterNullaryStartupFlag("fatal_event_bus_exceptions");
   RegisterNullaryStartupFlag("host_jvm_debug");
   RegisterNullaryStartupFlag("idle_server_tasks");
+  RegisterNullaryStartupFlag("incompatible_enable_execution_transition");
   RegisterNullaryStartupFlag("shutdown_on_low_sys_mem");
   RegisterNullaryStartupFlag("ignore_all_rc_files");
   RegisterNullaryStartupFlag("unlimit_coredumps");
@@ -188,7 +190,13 @@
   return false;
 }
 
-void StartupOptions::AddExtraOptions(vector<string> *result) const {}
+void StartupOptions::AddExtraOptions(vector<string> *result) const {
+  if (incompatible_enable_execution_transition) {
+    result->push_back("--incompatible_enable_execution_transition");
+  } else {
+    result->push_back("--noincompatible_enable_execution_transition");
+  }
+}
 
 blaze_exit_code::ExitCode StartupOptions::ProcessArg(
       const string &argstr, const string &next_argstr, const string &rcfile,
@@ -423,6 +431,14 @@
   } else if (GetNullaryOption(arg, "--nounlimit_coredumps")) {
     unlimit_coredumps = false;
     option_sources["unlimit_coredumps"] = rcfile;
+  } else if (GetNullaryOption(arg,
+                              "--incompatible_enable_execution_transition")) {
+    incompatible_enable_execution_transition = true;
+    option_sources["incompatible_enable_execution_transition"] = rcfile;
+  } else if (GetNullaryOption(arg,
+                              "--noincompatible_enable_execution_transition")) {
+    incompatible_enable_execution_transition = false;
+    option_sources["incompatible_enable_execution_transition"] = rcfile;
   } else {
     bool extra_argument_processed;
     blaze_exit_code::ExitCode process_extra_arg_exit_code = ProcessArgExtra(
diff --git a/src/main/cpp/startup_options.h b/src/main/cpp/startup_options.h
index b776182..51c5466 100644
--- a/src/main/cpp/startup_options.h
+++ b/src/main/cpp/startup_options.h
@@ -267,6 +267,11 @@
   // Whether to raise the soft coredump limit to the hard one or not.
   bool unlimit_coredumps;
 
+  // Whether the execution transition is enabled, or behaves like a host
+  // transition. This must be set before rule classes are constructed.
+  // See https://github.com/bazelbuild/bazel/issues/7935
+  bool incompatible_enable_execution_transition;
+
  protected:
   // Constructor for subclasses only so that site-specific extensions of this
   // class can override the product name.  The product_name must be the
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java
index 31a2f8c..16ccd28 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java
@@ -478,4 +478,16 @@
               + "can be shared among them without changes. Possible values are: user-interactive, "
               + "user-initiated, default, utility, and background.")
   public String macosQosClass;
+
+  @Option(
+      name = "incompatible_enable_execution_transition",
+      defaultValue = "false", // Only for documentation; value is set by the client.
+      documentationCategory = OptionDocumentationCategory.TOOLCHAIN,
+      effectTags = {OptionEffectTag.BAZEL_INTERNAL_CONFIGURATION},
+      metadataTags = {
+        OptionMetadataTag.INCOMPATIBLE_CHANGE,
+        OptionMetadataTag.TRIGGERED_BY_ALL_INCOMPATIBLE_CHANGES
+      },
+      help = "If false, the execution transition behaves like the host transition.")
+  public boolean enableExecutionTransition;
 }
diff --git a/src/test/cpp/bazel_startup_options_test.cc b/src/test/cpp/bazel_startup_options_test.cc
index 0326441..09879e6 100644
--- a/src/test/cpp/bazel_startup_options_test.cc
+++ b/src/test/cpp/bazel_startup_options_test.cc
@@ -87,9 +87,10 @@
   ExpectIsNullaryOption(options, "fatal_event_bus_exceptions");
   ExpectIsNullaryOption(options, "home_rc");
   ExpectIsNullaryOption(options, "host_jvm_debug");
-  ExpectIsNullaryOption(options, "shutdown_on_low_sys_mem");
   ExpectIsNullaryOption(options, "ignore_all_rc_files");
+  ExpectIsNullaryOption(options, "incompatible_enable_execution_transition");
   ExpectIsNullaryOption(options, "master_bazelrc");
+  ExpectIsNullaryOption(options, "shutdown_on_low_sys_mem");
   ExpectIsNullaryOption(options, "system_rc");
   ExpectIsNullaryOption(options, "watchfs");
   ExpectIsNullaryOption(options, "workspace_rc");
@@ -99,16 +100,16 @@
   ExpectIsUnaryOption(options, "connect_timeout_secs");
   ExpectIsUnaryOption(options, "digest_function");
   ExpectIsUnaryOption(options, "experimental_oom_more_eagerly_threshold");
-  ExpectIsUnaryOption(options, "server_javabase");
   ExpectIsUnaryOption(options, "host_jvm_args");
   ExpectIsUnaryOption(options, "host_jvm_profile");
+  ExpectIsUnaryOption(options, "install_base");
   ExpectIsUnaryOption(options, "invocation_policy");
   ExpectIsUnaryOption(options, "io_nice_level");
-  ExpectIsUnaryOption(options, "install_base");
   ExpectIsUnaryOption(options, "macos_qos_class");
   ExpectIsUnaryOption(options, "max_idle_secs");
   ExpectIsUnaryOption(options, "output_base");
   ExpectIsUnaryOption(options, "output_user_root");
+  ExpectIsUnaryOption(options, "server_javabase");
 }
 
 TEST_F(BazelStartupOptionsTest, BlazercFlagsAreNotAccepted) {