RELNOTES: Save Blaze memory by not storing LinkerInput objects in LinkCommandLine

PiperOrigin-RevId: 195099909
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java
index 15ccb9e..249c53e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkAction.java
@@ -43,6 +43,7 @@
 import com.google.devtools.build.lib.analysis.RuleContext;
 import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
 import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.collect.CollectionUtils;
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
 import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
 import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
@@ -116,6 +117,8 @@
 
   /** True for cc_fake_binary targets. */
   private final boolean fake;
+
+  private final Iterable<Artifact> fakeLinkerInputArtifacts;
   private final boolean isLtoIndexing;
 
   private final PathFragment ldExecutable;
@@ -157,6 +160,7 @@
       Artifact linkOutput,
       LibraryToLink interfaceOutputLibrary,
       boolean fake,
+      Iterable<Artifact> fakeLinkerInputArtifacts,
       boolean isLtoIndexing,
       ImmutableList<Artifact> linkstampObjects,
       LinkCommandLine linkCommandLine,
@@ -178,6 +182,7 @@
     this.linkOutput = linkOutput;
     this.interfaceOutputLibrary = interfaceOutputLibrary;
     this.fake = fake;
+    this.fakeLinkerInputArtifacts = CollectionUtils.makeImmutable(fakeLinkerInputArtifacts);
     this.isLtoIndexing = isLtoIndexing;
     this.linkstampObjects = linkstampObjects;
     this.linkCommandLine = linkCommandLine;
@@ -351,11 +356,9 @@
 
     try {
       // Concatenate all the (fake) .o files into the result.
-      for (LinkerInput linkerInput : getLinkCommandLine().getLinkerInputs()) {
-        Artifact objectFile = linkerInput.getArtifact();
-        if ((CppFileTypes.OBJECT_FILE.matches(objectFile.getFilename())
-                || CppFileTypes.PIC_OBJECT_FILE.matches(objectFile.getFilename()))
-            && linkerInput.isFake()) {
+      for (Artifact objectFile : fakeLinkerInputArtifacts) {
+        if (CppFileTypes.OBJECT_FILE.matches(objectFile.getFilename())
+            || CppFileTypes.PIC_OBJECT_FILE.matches(objectFile.getFilename())) {
           s.append(
               FileSystemUtils.readContentAsLatin1(
                   actionExecutionContext.getInputPath(objectFile))); // (IOException)
@@ -414,8 +417,7 @@
     // The uses of getLinkConfiguration in this method may not be consistent with the computed key.
     // I.e., this may be incrementally incorrect.
     CppLinkInfo.Builder info = CppLinkInfo.newBuilder();
-    info.addAllInputFile(Artifact.toExecPaths(
-        LinkerInputs.toLibraryArtifacts(getLinkCommandLine().getLinkerInputs())));
+    info.addAllInputFile(Artifact.toExecPaths(getLinkCommandLine().getLinkerInputArtifacts()));
     info.setOutputFile(getPrimaryOutput().getExecPathString());
     if (interfaceOutputLibrary != null) {
       info.setInterfaceOutputFile(interfaceOutputLibrary.getArtifact().getExecPathString());
@@ -501,7 +503,7 @@
         ? MIN_DYNAMIC_LINK_RESOURCES
         : MIN_STATIC_LINK_RESOURCES;
 
-    final int inputSize = Iterables.size(getLinkCommandLine().getLinkerInputs());
+    final int inputSize = Iterables.size(getLinkCommandLine().getLinkerInputArtifacts());
 
     return ResourceSet.createWithRamCpuIo(
         Math.max(inputSize * LINK_RESOURCES_PER_INPUT.getMemoryMb(),
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
index 39222d0..2945ecc 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionBuilder.java
@@ -1038,9 +1038,15 @@
           !needWholeArchive, "the need whole archive flag must be false for static links");
     }
 
+    ImmutableSet<Artifact> linkerInputArtifacts =
+        ImmutableSet.<LinkerInput>copyOf(linkerInputs)
+            .stream()
+            .map(LinkerInput::getArtifact)
+            .collect(ImmutableSet.toImmutableSet());
+
     LinkCommandLine.Builder linkCommandLineBuilder =
         new LinkCommandLine.Builder(ruleContext)
-            .setLinkerInputs(linkerInputs)
+            .setLinkerInputArtifacts(linkerInputArtifacts)
             .setLinkTargetType(linkType)
             .setLinkStaticness(linkStaticness)
             .setToolchainLibrariesSolibDir(
@@ -1177,6 +1183,13 @@
 
     inputsBuilder.add(linkstampObjectArtifacts);
 
+    ImmutableSet<Artifact> fakeLinkerInputArtifacts =
+        ImmutableSet.<LinkerInput>copyOf(linkerInputs)
+            .stream()
+            .filter(linkerInput -> linkerInput.isFake())
+            .map(LinkerInput::getArtifact)
+            .collect(ImmutableSet.toImmutableSet());
+
     return new CppLinkAction(
         getOwner(),
         mnemonic,
@@ -1186,6 +1199,7 @@
         output,
         interfaceOutputLibrary,
         fake,
+        fakeLinkerInputArtifacts,
         isLtoIndexing,
         linkstampMap
             .keySet()
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java
index 81fa782..e39df63 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkCommandLine.java
@@ -49,7 +49,7 @@
   // The feature config can be null for tests.
   @Nullable private final FeatureConfiguration featureConfiguration;
   private final ImmutableList<Artifact> buildInfoHeaderArtifacts;
-  private final Iterable<LinkerInput> linkerInputs;
+  private final Iterable<Artifact> linkerInputArtifacts;
   private final LinkTargetType linkTargetType;
   private final LinkStaticness linkStaticness;
   private final ImmutableList<String> linkopts;
@@ -64,7 +64,7 @@
       String actionName,
       String forcedToolPath,
       ImmutableList<Artifact> buildInfoHeaderArtifacts,
-      Iterable<LinkerInput> linkerInputs,
+      Iterable<Artifact> linkerInputArtifacts,
       LinkTargetType linkTargetType,
       LinkStaticness linkStaticness,
       ImmutableList<String> linkopts,
@@ -80,7 +80,7 @@
     this.variables = variables;
     this.featureConfiguration = featureConfiguration;
     this.buildInfoHeaderArtifacts = Preconditions.checkNotNull(buildInfoHeaderArtifacts);
-    this.linkerInputs = Preconditions.checkNotNull(linkerInputs);
+    this.linkerInputArtifacts = Preconditions.checkNotNull(linkerInputArtifacts);
     this.linkTargetType = Preconditions.checkNotNull(linkTargetType);
     this.linkStaticness = Preconditions.checkNotNull(linkStaticness);
     this.linkopts = linkopts;
@@ -101,8 +101,8 @@
   }
 
   /** Returns the (ordered, immutable) list of paths to the linker's input files. */
-  public Iterable<LinkerInput> getLinkerInputs() {
-    return linkerInputs;
+  public Iterable<Artifact> getLinkerInputArtifacts() {
+    return linkerInputArtifacts;
   }
 
   /**
@@ -414,7 +414,7 @@
     private final RuleContext ruleContext;
     private String forcedToolPath;
     private ImmutableList<Artifact> buildInfoHeaderArtifacts = ImmutableList.of();
-    private Iterable<LinkerInput> linkerInputs = ImmutableList.of();
+    private Iterable<Artifact> linkerInputArtifacts = ImmutableList.of();
     @Nullable private LinkTargetType linkTargetType;
     private LinkStaticness linkStaticness = LinkStaticness.FULLY_STATIC;
     private ImmutableList<String> linkopts = ImmutableList.of();
@@ -452,7 +452,7 @@
           actionName,
           forcedToolPath,
           buildInfoHeaderArtifacts,
-          linkerInputs,
+          linkerInputArtifacts,
           linkTargetType,
           linkStaticness,
           linkopts,
@@ -489,12 +489,12 @@
     }
 
     /**
-     * Sets a list of linker inputs. These get turned into linker options depending on the
+     * Sets a list of linker input artifacts. These get turned into linker options depending on the
      * staticness and the target type. This call makes an immutable copy of the inputs, if the
      * provided Iterable isn't already immutable (see {@link CollectionUtils#makeImmutable}).
      */
-    public Builder setLinkerInputs(Iterable<LinkerInput> linkerInputs) {
-      this.linkerInputs = CollectionUtils.makeImmutable(linkerInputs);
+    public Builder setLinkerInputArtifacts(Iterable<Artifact> linkerInputArtifacts) {
+      this.linkerInputArtifacts = CollectionUtils.makeImmutable(linkerInputArtifacts);
       return this;
     }
 
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcCommonTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcCommonTest.java
index e0b0ead..656a64a 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcCommonTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcCommonTest.java
@@ -204,7 +204,7 @@
   private Iterable<Artifact> getLinkerInputs(ConfiguredTarget target) {
     Artifact executable = getExecutable(target);
     CppLinkAction linkAction = (CppLinkAction) getGeneratingAction(executable);
-    return LinkerInputs.toLibraryArtifacts(linkAction.getLinkCommandLine().getLinkerInputs());
+    return linkAction.getLinkCommandLine().getLinkerInputArtifacts();
   }
 
   @Test
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcLibraryConfiguredTargetTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcLibraryConfiguredTargetTest.java
index c509a36..0d50d72 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CcLibraryConfiguredTargetTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CcLibraryConfiguredTargetTest.java
@@ -289,8 +289,8 @@
     CppLinkInfo cppLinkInfo = info.getExtension(CppLinkInfo.cppLinkInfo);
     assertThat(cppLinkInfo).isNotNull();
 
-    Iterable<String> inputs = Artifact.asExecPaths(
-        LinkerInputs.toLibraryArtifacts(action.getLinkCommandLine().getLinkerInputs()));
+    Iterable<String> inputs =
+        Artifact.asExecPaths(action.getLinkCommandLine().getLinkerInputArtifacts());
     assertThat(cppLinkInfo.getInputFileList()).containsExactlyElementsIn(inputs);
     assertThat(cppLinkInfo.getOutputFile())
         .isEqualTo(action.getPrimaryOutput().getExecPathString());
@@ -323,8 +323,8 @@
     CppLinkInfo cppLinkInfo = info.getExtension(CppLinkInfo.cppLinkInfo);
     assertThat(cppLinkInfo).isNotNull();
 
-    Iterable<String> inputs = Artifact.asExecPaths(
-        LinkerInputs.toLibraryArtifacts(action.getLinkCommandLine().getLinkerInputs()));
+    Iterable<String> inputs =
+        Artifact.asExecPaths(action.getLinkCommandLine().getLinkerInputArtifacts());
     assertThat(cppLinkInfo.getInputFileList()).containsExactlyElementsIn(inputs);
     assertThat(cppLinkInfo.getOutputFile())
         .isEqualTo(action.getPrimaryOutput().getExecPathString());
diff --git a/src/test/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionTest.java b/src/test/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionTest.java
index 83ed1d7..8ec2267 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/cpp/CppLinkActionTest.java
@@ -467,7 +467,7 @@
     assertThat(resources.getIoUsage())
         .isAtLeast(CppLinkAction.MIN_STATIC_LINK_RESOURCES.getIoUsage());
 
-    final int linkSize = Iterables.size(linkAction.getLinkCommandLine().getLinkerInputs());
+    final int linkSize = Iterables.size(linkAction.getLinkCommandLine().getLinkerInputArtifacts());
     ResourceSet scaledSet = ResourceSet.createWithRamCpuIo(
         CppLinkAction.LINK_RESOURCES_PER_INPUT.getMemoryMb() * linkSize,
         CppLinkAction.LINK_RESOURCES_PER_INPUT.getCpuUsage() * linkSize,