Add a --build_runfile_manifests flag which controls production of
foo_test.runfiles_manifest files.  These are the largest local outputs
in many builds, and unnecessary for remote test execution.

RELNOTES: New --build_runfile_manifests flag controls production of runfiles manifests.
PiperOrigin-RevId: 166001477
diff --git a/site/docs/bazel-user-manual.html b/site/docs/bazel-user-manual.html
index 798e592..2c797d8 100644
--- a/site/docs/bazel-user-manual.html
+++ b/site/docs/bazel-user-manual.html
@@ -1918,6 +1918,15 @@
   each individual test (or application) requires its own runfiles tree.
 </p>
 
+<h4 id='flag--build_runfile_manifests'><code class='flag'>--[no]build_runfile_manifests</code></h4>
+<p>
+  This option, which is enabled by default, specifies whether runfiles manifests
+  should be written to the output tree.
+  Disabling it implies <code class='flag'>--nobuild_runfile_links</code>.
+
+  It can be disabled when executing tests on Forge, as runfiles trees will
+  be created remotely from in-memory manifests.
+
 <h4 id='flag--discard_analysis_cache'>
   <code class='flag'>--[no]discard_analysis_cache</code></h4>
 <p>
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
index 9c13d4b..3f28614 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
@@ -1517,14 +1517,6 @@
   }
 
   /**
-   * Returns true if runfiles support should create the runfiles tree, or
-   * false if it should just create the manifest.
-   */
-  public boolean shouldCreateRunfilesSymlinks() {
-    return getConfiguration().buildRunfiles();
-  }
-
-  /**
    * @return true if {@code rule} is visible from {@code prerequisite}.
    *
    * <p>This only computes the logic as implemented by the visibility system. The final decision
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java b/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java
index e9d711d..2f99405 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java
@@ -93,7 +93,8 @@
       Runfiles runfiles,
       CommandLine args) {
     owningExecutable = Preconditions.checkNotNull(executable);
-    createSymlinks = ruleContext.shouldCreateRunfilesSymlinks();
+    boolean createManifest = ruleContext.getConfiguration().buildRunfilesManifests();
+    createSymlinks = createManifest && ruleContext.getConfiguration().buildRunfiles();
 
     // Adding run_under target to the runfiles manifest so it would become part
     // of runfiles tree and would be executable everywhere.
@@ -118,10 +119,14 @@
     }
 
     Artifact artifactsMiddleman = createArtifactsMiddleman(ruleContext, runfiles.getAllArtifacts());
-    runfilesInputManifest = createRunfilesInputManifestArtifact(ruleContext);
-    this.runfilesManifest = createRunfilesAction(ruleContext, runfiles, artifactsMiddleman);
-    this.runfilesMiddleman = createRunfilesMiddleman(
-        ruleContext, artifactsMiddleman, runfilesManifest);
+    if (createManifest) {
+      runfilesInputManifest = createRunfilesInputManifestArtifact(ruleContext);
+      runfilesManifest = createRunfilesAction(ruleContext, runfiles, artifactsMiddleman);
+    } else {
+      runfilesInputManifest = artifactsMiddleman;
+      runfilesManifest = artifactsMiddleman;
+    }
+    runfilesMiddleman = createRunfilesMiddleman(ruleContext, artifactsMiddleman, runfilesManifest);
     sourcesManifest = createSourceManifest(ruleContext, runfiles);
 
     this.args = args;
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
index ccb3ea6..7f9133f 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
@@ -747,6 +747,18 @@
     public boolean useLLVMCoverageMapFormat;
 
     @Option(
+      name = "build_runfile_manifests",
+      defaultValue = "true",
+      category = "strategy",
+      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+      effectTags = {OptionEffectTag.UNKNOWN},
+      help =
+          "If true, write runfiles manifests for all targets.  "
+              + "If false, omit them."
+    )
+    public boolean buildRunfilesManifests;
+
+    @Option(
       name = "build_runfile_links",
       defaultValue = "true",
       category = "strategy",
@@ -1044,6 +1056,7 @@
       }
 
       // === Runfiles ===
+      host.buildRunfilesManifests = buildRunfilesManifests;
       host.buildRunfiles = buildRunfiles;
 
       // === Linkstamping ===
@@ -1874,6 +1887,13 @@
   }
 
   /**
+   * Returns true if we are building runfiles manifests for this configuration.
+   */
+  public boolean buildRunfilesManifests() {
+    return options.buildRunfilesManifests;
+  }
+
+  /**
    * Returns true if we are building runfiles symlinks for this configuration.
    */
   public boolean buildRunfiles() {
diff --git a/src/test/shell/integration/run_test.sh b/src/test/shell/integration/run_test.sh
index 664198c..405272c 100755
--- a/src/test/shell/integration/run_test.sh
+++ b/src/test/shell/integration/run_test.sh
@@ -85,9 +85,6 @@
 }
 
 function test_runfiles_present_cc_binary() {
-  # cc_binary is needed because runfiles are always created for Python
-  # and shell binaries, so --nobuild_runfile_links does not apply to them.
-  # (see RuleConfiguredTarget.shouldCreateRunfilesSymlinks())
   write_cc_source_files
 
   cat > cc/hello_kitty.txt <<EOF