make execGroups available to the RuleClass (like requiredToolchains)

PiperOrigin-RevId: 304174397
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
index 666451c..ab180ad 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
@@ -710,6 +710,7 @@
     private boolean useToolchainResolution = true;
     private Set<Label> executionPlatformConstraints = new HashSet<>();
     private OutputFile.Kind outputFileKind = OutputFile.Kind.FILE;
+    private final Map<String, ExecGroup> execGroups = new HashMap<>();
 
     /**
      * Constructs a new {@code RuleClassBuilder} using all attributes from all
@@ -743,6 +744,14 @@
         addRequiredToolchains(parent.getRequiredToolchains());
         useToolchainResolution = parent.useToolchainResolution;
         addExecutionPlatformConstraints(parent.getExecutionPlatformConstraints());
+        try {
+          addExecGroups(parent.getExecGroups());
+        } catch (DuplicateExecGroupError e) {
+          throw new IllegalArgumentException(
+              String.format(
+                  "An execution group named '%s' is inherited multiple times in %s ruleclass",
+                  e.getDuplicateGroup(), name));
+        }
 
         for (Attribute attribute : parent.getAttributes()) {
           String attrName = attribute.getName();
@@ -862,6 +871,7 @@
           requiredToolchains,
           useToolchainResolution,
           executionPlatformConstraints,
+          execGroups,
           outputFileKind,
           attributes.values(),
           buildSetting);
@@ -1365,6 +1375,36 @@
     }
 
     /**
+     * Adds execution groups to this rule class. Errors out if multiple groups with the same name
+     * are added.
+     */
+    public Builder addExecGroups(Map<String, ExecGroup> execGroups) throws DuplicateExecGroupError {
+      for (Map.Entry<String, ExecGroup> group : execGroups.entrySet()) {
+        String name = group.getKey();
+        if (this.execGroups.put(name, group.getValue()) != null) {
+          throw new DuplicateExecGroupError(name);
+        }
+      }
+      return this;
+    }
+
+    /** An error to help report {@link ExecGroup}s with the same name */
+    static class DuplicateExecGroupError extends EvalException {
+      private final String duplicateGroup;
+
+      DuplicateExecGroupError(String duplicateGroup) {
+        super(
+            null,
+            String.format("Multiple execution groups with the same name: '%s'.", duplicateGroup));
+        this.duplicateGroup = duplicateGroup;
+      }
+
+      String getDuplicateGroup() {
+        return duplicateGroup;
+      }
+    }
+
+    /**
      * Causes rules to use toolchain resolution to determine the execution platform and toolchains.
      * Rules that are part of configuring toolchains and platforms should set this to {@code false}.
      */
@@ -1524,6 +1564,7 @@
   private final ImmutableSet<Label> requiredToolchains;
   private final boolean useToolchainResolution;
   private final ImmutableSet<Label> executionPlatformConstraints;
+  private final ImmutableMap<String, ExecGroup> execGroups;
 
   /**
    * Constructs an instance of RuleClass whose name is 'name', attributes are 'attributes'. The
@@ -1579,6 +1620,7 @@
       Set<Label> requiredToolchains,
       boolean useToolchainResolution,
       Set<Label> executionPlatformConstraints,
+      Map<String, ExecGroup> execGroups,
       OutputFile.Kind outputFileKind,
       Collection<Attribute> attributes,
       @Nullable BuildSetting buildSetting) {
@@ -1618,6 +1660,7 @@
     this.requiredToolchains = ImmutableSet.copyOf(requiredToolchains);
     this.useToolchainResolution = useToolchainResolution;
     this.executionPlatformConstraints = ImmutableSet.copyOf(executionPlatformConstraints);
+    this.execGroups = ImmutableMap.copyOf(execGroups);
     this.buildSetting = buildSetting;
 
     // Create the index and collect non-configurable attributes.
@@ -2536,6 +2579,10 @@
     return executionPlatformConstraints;
   }
 
+  public ImmutableMap<String, ExecGroup> getExecGroups() {
+    return execGroups;
+  }
+
   public OutputFile.Kind  getOutputFileKind() {
     return outputFileKind;
   }