Adds a special "_validation" output group to enable moving "validation actions" off the critical path of builds.

Validation actions are actions which validate something about the build based on execution-time information (e.g. the contents of files), but whose outputs are not needed by anything else in the build. Currently, to get such an action to run, its output (even a dummy empty file) must be "artificially" added to the inputs of some other action in the build. This reduces parallelism and potentially increases the critical path of the build.

The validation output group is provided here instead, so that the outputs of validation actions can be requested separately from all other targets, allowing the actions to be executed in parallel with the rest of the build.

The "_validation" output group is "special" in that it is automatically propagated through implicit outputs and through all rules. It also cannot be "deselected" with the --output_groups flag. Instead, the flag --run_validations is provided.

Note that with validation actions supported through output groups, such actions must still create some output file, even if it's empty.

RELNOTES[NEW]: Added a special "_validation" output group to enable moving "validation actions" off the critical path of builds.

PiperOrigin-RevId: 274652209
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupInfo.java b/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupInfo.java
index 8f0fe1a..1ddb105 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupInfo.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/OutputGroupInfo.java
@@ -99,6 +99,20 @@
       HIDDEN_OUTPUT_GROUP_PREFIX + "hidden_top_level" + INTERNAL_SUFFIX;
 
   /**
+   * This output group contains artifacts that are the outputs of validation actions. These actions
+   * should be run even if no other action depends on their outputs, therefore this output group is:
+   *
+   * <ul>
+   *   <li>built even if <code>--output_groups</code> overrides the default output groups
+   *   <li>not affected by the subtraction operation of <code>--output_groups</code> (i.e. <code>
+   *       "--output_groups=-_validation"</code>)
+   * </ul>
+   *
+   * The only way to disable this output group is with <code>--run_validations=false</code>.
+   */
+  public static final String VALIDATION = HIDDEN_OUTPUT_GROUP_PREFIX + "validation";
+
+  /**
    * Temporary files created during building a rule, for example, .i, .d and .s files for C++
    * compilation.
    *
@@ -179,19 +193,22 @@
     return new OutputGroupInfo(resultBuilder.build());
   }
 
-  public static ImmutableSortedSet<String> determineOutputGroups(List<String> outputGroups) {
-    return determineOutputGroups(DEFAULT_GROUPS, outputGroups);
+  public static ImmutableSortedSet<String> determineOutputGroups(
+      List<String> outputGroups, boolean includeValidationOutputGroup) {
+    return determineOutputGroups(DEFAULT_GROUPS, outputGroups, includeValidationOutputGroup);
   }
 
   public static ImmutableSortedSet<String> determineOutputGroups(
-      Set<String> defaultOutputGroups, List<String> outputGroups) {
+      Set<String> defaultOutputGroups,
+      List<String> outputGroups,
+      boolean includeValidationOutputGroup) {
 
     Set<String> current = Sets.newHashSet();
 
     // If all of the requested output groups start with "+" or "-", then these are added or
     // subtracted to the set of default output groups.
     // If any of them don't start with "+" or "-", then the list of requested output groups
-    // overrides the default set of output groups.
+    // overrides the default set of output groups, except for the validation output group.
     boolean addDefaultOutputGroups = true;
     for (String outputGroup : outputGroups) {
       if (!(outputGroup.startsWith("+") || outputGroup.startsWith("-"))) {
@@ -213,6 +230,11 @@
       }
     }
 
+    // Add the validation output group regardless of the additions and subtractions above.
+    if (includeValidationOutputGroup) {
+      current.add(VALIDATION);
+    }
+
     return ImmutableSortedSet.copyOf(current);
   }