Add an explicit bit to actions that tells whether they are shareable or not.

This bit is set to "true" by default everywhere except on CppCompileActions that are not used for linkstamp data compilation.

RELNOTES: None.
PiperOrigin-RevId: 211476344
diff --git a/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java b/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java
index 4156175..fc80892 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/AbstractAction.java
@@ -322,6 +322,11 @@
   }
 
   @Override
+  public boolean isShareable() {
+    return true;
+  }
+
+  @Override
   public boolean showsOutputUnconditionally() {
     return false;
   }
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ActionAnalysisMetadata.java b/src/main/java/com/google/devtools/build/lib/actions/ActionAnalysisMetadata.java
index d86224b..d39d7a5 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ActionAnalysisMetadata.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ActionAnalysisMetadata.java
@@ -31,6 +31,14 @@
   ActionOwner getOwner();
 
   /**
+   * Returns true if the action can be shared, i.e. multiple configured targets can create the same
+   * action.
+   *
+   * <p>In theory, these should not exist, but in practice, they do.
+   */
+  boolean isShareable();
+
+  /**
    * Returns a mnemonic (string constant) for this kind of action; written into
    * the master log so that the appropriate parser can be invoked for the output
    * of the action. Effectively a public method as the value is used by the
diff --git a/src/main/java/com/google/devtools/build/lib/actions/Actions.java b/src/main/java/com/google/devtools/build/lib/actions/Actions.java
index a3a6ba6..4e9fb5e 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/Actions.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/Actions.java
@@ -58,6 +58,10 @@
    */
   public static boolean canBeShared(
       ActionKeyContext actionKeyContext, ActionAnalysisMetadata a, ActionAnalysisMetadata b) {
+    if (!a.isShareable() || !b.isShareable()) {
+      return false;
+    }
+
     if (!a.getMnemonic().equals(b.getMnemonic())) {
       return false;
     }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnActionTemplate.java b/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnActionTemplate.java
index fcb1766..ab54b4f 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnActionTemplate.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/actions/SpawnActionTemplate.java
@@ -156,6 +156,11 @@
   }
 
   @Override
+  public boolean isShareable() {
+    return true;
+  }
+
+  @Override
   public final String getMnemonic() {
     return mnemonic;
   }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java
index a028a5d..b74cdbd 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java
@@ -104,6 +104,7 @@
   private final NestedSet<Artifact> additionalPrunableHeaders;
 
   @Nullable private final Artifact grepIncludes;
+  private final boolean shareable;
   private final boolean shouldScanIncludes;
   private final boolean shouldPruneModules;
   private final boolean usePic;
@@ -200,6 +201,7 @@
       CcToolchainVariables variables,
       Artifact sourceFile,
       CppConfiguration cppConfiguration,
+      boolean shareable,
       boolean shouldScanIncludes,
       boolean shouldPruneModules,
       boolean usePic,
@@ -236,6 +238,7 @@
     Preconditions.checkArgument(!shouldPruneModules || shouldScanIncludes);
     this.outputFile = Preconditions.checkNotNull(outputFile);
     this.sourceFile = sourceFile;
+    this.shareable = shareable;
     this.cppConfiguration = cppConfiguration;
     // We do not need to include the middleman artifact since it is a generated artifact and will
     // definitely exist prior to this action execution.
@@ -984,6 +987,11 @@
   }
 
   @Override
+  public boolean isShareable() {
+    return shareable;
+  }
+
+  @Override
   public void computeKey(ActionKeyContext actionKeyContext, Fingerprint fp) {
     fp.addUUID(actionClassId);
     fp.addStringMap(env.getFixedEnv());
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java
index 000eca8..4ac5cc9 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionBuilder.java
@@ -50,6 +50,7 @@
   public static final UUID GUID = UUID.fromString("97493805-894f-493a-be66-9a698f45c31d");
 
   private final ActionOwner owner;
+  private boolean shareable;
   private final BuildConfiguration configuration;
   private CcToolchainFeatures.FeatureConfiguration featureConfiguration;
   private CcToolchainVariables variables = CcToolchainVariables.EMPTY;
@@ -112,6 +113,7 @@
       CcToolchainProvider ccToolchain,
       @Nullable Artifact grepIncludes) {
     this.owner = actionOwner;
+    this.shareable = false;
     this.configuration = configuration;
     this.cppConfiguration = configuration.getFragment(CppConfiguration.class);
     this.mandatoryInputsBuilder = NestedSetBuilder.stableOrder();
@@ -128,6 +130,7 @@
    */
   public CppCompileActionBuilder(CppCompileActionBuilder other) {
     this.owner = other.owner;
+    this.shareable = other.shareable;
     this.featureConfiguration = other.featureConfiguration;
     this.sourceFile = other.sourceFile;
     this.mandatoryInputsBuilder = NestedSetBuilder.<Artifact>stableOrder()
@@ -304,6 +307,7 @@
               variables,
               sourceFile,
               cppConfiguration,
+              shareable,
               shouldScanIncludes,
               shouldPruneModules(),
               usePic,
@@ -331,6 +335,7 @@
               variables,
               sourceFile,
               cppConfiguration,
+              shareable,
               shouldScanIncludes,
               shouldPruneModules(),
               usePic,
@@ -597,6 +602,11 @@
     return this;
   }
 
+  public CppCompileActionBuilder setShareable(boolean shareable) {
+    this.shareable = shareable;
+    return this;
+  }
+
   public CppCompileActionBuilder setShouldScanIncludes(boolean shouldScanIncludes) {
     this.shouldScanIncludes = shouldScanIncludes;
     return this;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionTemplate.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionTemplate.java
index c183877..7b2a752 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionTemplate.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileActionTemplate.java
@@ -189,6 +189,11 @@
   }
 
   @Override
+  public boolean isShareable() {
+    return false;
+  }
+
+  @Override
   public final String getMnemonic() {
     return "CppCompileActionTemplate";
   }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkstampCompileHelper.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkstampCompileHelper.java
index 2fef020..1e52447 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkstampCompileHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkstampCompileHelper.java
@@ -75,6 +75,7 @@
             .setBuiltinIncludeFiles(buildInfoHeaderArtifacts)
             .addMandatoryInputs(nonCodeInputs)
             .setCppConfiguration(cppConfiguration)
+            .setShareable(true)
             .setShouldScanIncludes(false)
             .setActionName(CppActionNames.LINKSTAMP_COMPILE);
     semantics.finalizeCompileActionBuilder(ruleContext, builder);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/FakeCppCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/FakeCppCompileAction.java
index 362ada1..f848d65 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/FakeCppCompileAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/FakeCppCompileAction.java
@@ -63,6 +63,7 @@
       CcToolchainVariables variables,
       Artifact sourceFile,
       CppConfiguration cppConfiguration,
+      boolean shareable,
       boolean shouldScanIncludes,
       boolean shouldPruneModules,
       boolean usePic,
@@ -88,6 +89,7 @@
         variables,
         sourceFile,
         cppConfiguration,
+        shareable,
         shouldScanIncludes,
         shouldPruneModules,
         usePic,
diff --git a/src/test/java/com/google/devtools/build/lib/actions/ResourceManagerTest.java b/src/test/java/com/google/devtools/build/lib/actions/ResourceManagerTest.java
index 4d25bde..233efc0 100644
--- a/src/test/java/com/google/devtools/build/lib/actions/ResourceManagerTest.java
+++ b/src/test/java/com/google/devtools/build/lib/actions/ResourceManagerTest.java
@@ -484,6 +484,11 @@
     }
 
     @Override
+    public boolean isShareable() {
+      throw new IllegalStateException();
+    }
+
+    @Override
     public String prettyPrint() {
       throw new IllegalStateException();
     }
diff --git a/src/test/java/com/google/devtools/build/lib/exec/util/FakeOwner.java b/src/test/java/com/google/devtools/build/lib/exec/util/FakeOwner.java
index aaf7197..49bb3f8 100644
--- a/src/test/java/com/google/devtools/build/lib/exec/util/FakeOwner.java
+++ b/src/test/java/com/google/devtools/build/lib/exec/util/FakeOwner.java
@@ -60,6 +60,11 @@
   }
 
   @Override
+  public boolean isShareable() {
+    return false;
+  }
+
+  @Override
   public String getMnemonic() {
     return mnemonic;
   }