Cleanup LibraryToLinkCollector to properly distinguish C++ runtimes from dynamic libraries

Term runtime input had 2 meanings in CppLinkAction:
1) input needed at runtime - dynamic library
2) input corresponding to the C++ runtime (libstdc++ or libc++)

This confused me and therefore the code :) This cl cleans this up to some extent by:
* renaming runtimeInput to runtimesInput, to at least give the reader a chance to catch the difference :)
* treating runtimesInputs as normal linker inputs, also downstream in CppLinkAction and LinkCommandLine
* Simplifying LibrariesToLinkCollector by removing explicit runtimesHandling.

RELNOTES: None
PiperOrigin-RevId: 194046439
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 afff9ae..15ccb9e 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
@@ -416,8 +416,6 @@
     CppLinkInfo.Builder info = CppLinkInfo.newBuilder();
     info.addAllInputFile(Artifact.toExecPaths(
         LinkerInputs.toLibraryArtifacts(getLinkCommandLine().getLinkerInputs())));
-    info.addAllInputFile(Artifact.toExecPaths(
-        LinkerInputs.toLibraryArtifacts(getLinkCommandLine().getRuntimeInputs())));
     info.setOutputFile(getPrimaryOutput().getExecPathString());
     if (interfaceOutputLibrary != null) {
       info.setInterfaceOutputFile(interfaceOutputLibrary.getArtifact().getExecPathString());
@@ -457,8 +455,8 @@
     // the argv.
     fp.addBoolean(linkCommandLine.isNativeDeps());
     fp.addBoolean(linkCommandLine.useTestOnlyFlags());
-    if (linkCommandLine.getRuntimeSolibDir() != null) {
-      fp.addPath(linkCommandLine.getRuntimeSolibDir());
+    if (linkCommandLine.getToolchainLibrariesSolibDir() != null) {
+      fp.addPath(linkCommandLine.getToolchainLibrariesSolibDir());
     }
     fp.addBoolean(isLtoIndexing);
   }
@@ -503,8 +501,7 @@
         ? MIN_DYNAMIC_LINK_RESOURCES
         : MIN_STATIC_LINK_RESOURCES;
 
-    final int inputSize = Iterables.size(getLinkCommandLine().getLinkerInputs())
-        + Iterables.size(getLinkCommandLine().getRuntimeInputs());
+    final int inputSize = Iterables.size(getLinkCommandLine().getLinkerInputs());
 
     return ResourceSet.createWithRamCpuIo(
         Math.max(inputSize * LINK_RESOURCES_PER_INPUT.getMemoryMb(),
@@ -579,9 +576,9 @@
           ImmutableMap.copyOf(builder.getLtoBitcodeFiles()),
           builder.getRuntimeMiddleman(),
           NestedSetBuilder.<Artifact>stableOrder()
-              .addTransitive(builder.getRuntimeInputs())
+              .addTransitive(builder.getToolchainLibrariesInputs())
               .build(),
-          builder.getRuntimeType(),
+          builder.getToolchainLibrariesType(),
           builder.getLinkstamps(),
           ImmutableList.copyOf(builder.getLinkopts()),
           builder.getLinkType(),
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 70c29d2..19bd3a7 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
@@ -103,7 +103,9 @@
   private final FdoSupportProvider fdoSupport;
   private Artifact interfaceOutput;
   private Artifact symbolCounts;
-  private PathFragment runtimeSolibDir;
+  /** Directory where toolchain stores language-runtime libraries (libstdc++, libc++ ...) */
+  private PathFragment toolchainLibrariesSolibDir;
+
   protected final BuildConfiguration configuration;
   private final CppConfiguration cppConfiguration;
   private FeatureConfiguration featureConfiguration;
@@ -115,8 +117,9 @@
   private final NestedSetBuilder<LibraryToLink> libraries = NestedSetBuilder.linkOrder();
   private NestedSet<Artifact> crosstoolInputs = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
   private Artifact runtimeMiddleman;
-  private ArtifactCategory runtimeType = null;
-  private NestedSet<Artifact> runtimeInputs = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
+  private ArtifactCategory toolchainLibrariesType = null;
+  private NestedSet<Artifact> toolchainLibrariesInputs =
+      NestedSetBuilder.emptySet(Order.STABLE_ORDER);
   private final ImmutableSet.Builder<Linkstamp> linkstampsBuilder = ImmutableSet.builder();
   private ImmutableList<String> additionalLinkstampDefines = ImmutableList.of();
   private final List<String> linkopts = new ArrayList<>();
@@ -225,7 +228,7 @@
     this.toolchain = toolchain;
     this.fdoSupport = fdoSupport;
     if (featureConfiguration.isEnabled(CppRuleClasses.STATIC_LINK_CPP_RUNTIMES)) {
-      runtimeSolibDir = toolchain.getDynamicRuntimeSolibDir();
+      toolchainLibrariesSolibDir = toolchain.getDynamicRuntimeSolibDir();
     }
     this.featureConfiguration = featureConfiguration;
     this.cppSemantics = Preconditions.checkNotNull(cppSemantics);
@@ -253,7 +256,7 @@
       FeatureConfiguration featureConfiguration,
       CppSemantics cppSemantics) {
     // These Builder-only fields get set in the constructor:
-    //   ruleContext, analysisEnvironment, outputPath, configuration, runtimeSolibDir
+    //   ruleContext, analysisEnvironment, outputPath, configuration, toolchainLibrariesSolibDir
     this(
         ruleContext,
         output,
@@ -272,8 +275,8 @@
     this.crosstoolInputs = linkContext.crosstoolInputs;
     this.ltoBitcodeFiles = linkContext.ltoBitcodeFiles;
     this.runtimeMiddleman = linkContext.runtimeMiddleman;
-    this.runtimeInputs = linkContext.runtimeInputs;
-    this.runtimeType = linkContext.runtimeType;
+    this.toolchainLibrariesInputs = linkContext.runtimeInputs;
+    this.toolchainLibrariesType = linkContext.runtimeType;
     this.linkstampsBuilder.addAll(linkContext.linkstamps);
     this.linkopts.addAll(linkContext.linkopts);
     this.linkType = linkContext.linkType;
@@ -317,16 +320,14 @@
   public Artifact getRuntimeMiddleman() {
     return this.runtimeMiddleman;
   }
-  
-  /**
-   * Returns runtime inputs for this link action.
-   */
-  public NestedSet<Artifact> getRuntimeInputs() {
-    return this.runtimeInputs;
+
+  /** Returns runtime inputs for this link action. */
+  public NestedSet<Artifact> getToolchainLibrariesInputs() {
+    return this.toolchainLibrariesInputs;
   }
 
-  public ArtifactCategory getRuntimeType() {
-    return runtimeType;
+  public ArtifactCategory getToolchainLibrariesType() {
+    return toolchainLibrariesType;
   }
 
   /** Returns linkstamps for this link action. */
@@ -398,7 +399,8 @@
       objectFileInputsBuilder.add(
           LinkerInputs.simpleLinkerInput(
               this.ltoBitcodeFiles.getOrDefault(objectFile, objectFile),
-              ArtifactCategory.OBJECT_FILE));
+              ArtifactCategory.OBJECT_FILE,
+              /* disableWholeArchive= */ false));
     }
     return objectFileInputsBuilder.build();
   }
@@ -828,7 +830,10 @@
       objectFileInputs = ImmutableSet.copyOf(objectFiles);
       linkstampObjectFileInputs =
           ImmutableSet.copyOf(
-              LinkerInputs.simpleLinkerInputs(linkstampMap.values(), ArtifactCategory.OBJECT_FILE));
+              LinkerInputs.simpleLinkerInputs(
+                  linkstampMap.values(),
+                  ArtifactCategory.OBJECT_FILE,
+                  /* disableWholeArchive= */ false));
       uniqueLibraries = originalUniqueLibraries;
     }
 
@@ -933,11 +938,16 @@
                         uniqueLibraries,
                         needWholeArchive,
                         CppHelper.getArchiveType(cppConfiguration, toolchain))))
+            .add(
+                // Adding toolchain libraries without whole archive no-matter-what. People don't
+                // want to include whole libstdc++ in their binary ever.
+                ImmutableSet.copyOf(
+                    LinkerInputs.simpleLinkerInputs(
+                        toolchainLibrariesInputs,
+                        toolchainLibrariesType,
+                        /* disableWholeArchive= */ true)))
             .build();
 
-    ImmutableList<LinkerInput> runtimeLinkerInputs =
-        ImmutableList.copyOf(LinkerInputs.simpleLinkerInputs(runtimeInputs, runtimeType));
-
     PathFragment paramRootPath =
         ParameterFile.derivePath(outputRootPath, (isLtoIndexing) ? "lto-index" : "2");
 
@@ -962,14 +972,13 @@
             isNativeDeps,
             cppConfiguration,
             toolchain,
-            runtimeSolibDir,
+            toolchainLibrariesSolibDir,
             linkType,
             linkStaticness,
             output,
             solibDir,
             isLtoIndexing,
             allLtoArtifacts,
-            runtimeLinkerInputs,
             featureConfiguration,
             thinltoParamFile,
             allowLtoIndexing,
@@ -1018,7 +1027,7 @@
     }
     if (linkType.staticness() == Staticness.STATIC) {
       // solib dir must be null for static links
-      runtimeSolibDir = null;
+      toolchainLibrariesSolibDir = null;
 
       Preconditions.checkArgument(
           linkStaticness == LinkStaticness.FULLY_STATIC, "static library link must be static");
@@ -1033,10 +1042,10 @@
     LinkCommandLine.Builder linkCommandLineBuilder =
         new LinkCommandLine.Builder(ruleContext)
             .setLinkerInputs(linkerInputs)
-            .setRuntimeInputs(runtimeLinkerInputs)
             .setLinkTargetType(linkType)
             .setLinkStaticness(linkStaticness)
-            .setRuntimeSolibDir(linkType.staticness() == Staticness.STATIC ? null : runtimeSolibDir)
+            .setToolchainLibrariesSolibDir(
+                linkType.staticness() == Staticness.STATIC ? null : toolchainLibrariesSolibDir)
             .setNativeDeps(isNativeDeps)
             .setUseTestOnlyFlags(useTestOnlyFlags)
             .setParamFile(paramFile)
@@ -1323,9 +1332,9 @@
   public CppLinkActionBuilder setRuntimeInputs(
       ArtifactCategory runtimeType, Artifact middleman, NestedSet<Artifact> inputs) {
     Preconditions.checkArgument((middleman == null) == inputs.isEmpty());
-    this.runtimeType = runtimeType;
+    this.toolchainLibrariesType = runtimeType;
     this.runtimeMiddleman = middleman;
-    this.runtimeInputs = inputs;
+    this.toolchainLibrariesInputs = inputs;
     return this;
   }
 
@@ -1384,7 +1393,9 @@
    * Adds a single object file to the set of inputs.
    */
   public CppLinkActionBuilder addObjectFile(Artifact input) {
-    addObjectFile(LinkerInputs.simpleLinkerInput(input, ArtifactCategory.OBJECT_FILE));
+    addObjectFile(
+        LinkerInputs.simpleLinkerInput(
+            input, ArtifactCategory.OBJECT_FILE, /* disableWholeArchive= */ false));
     return this;
   }
 
@@ -1393,7 +1404,9 @@
    */
   public CppLinkActionBuilder addObjectFiles(Iterable<Artifact> inputs) {
     for (Artifact input : inputs) {
-      addObjectFile(LinkerInputs.simpleLinkerInput(input, ArtifactCategory.OBJECT_FILE));
+      addObjectFile(
+          LinkerInputs.simpleLinkerInput(
+              input, ArtifactCategory.OBJECT_FILE, /* disableWholeArchive= */ false));
     }
     return this;
   }
@@ -1592,8 +1605,9 @@
    * Sets the name of the directory where the solib symlinks for the dynamic runtime libraries live.
    * This is usually automatically set from the cc_toolchain.
    */
-  public CppLinkActionBuilder setRuntimeSolibDir(PathFragment runtimeSolibDir) {
-    this.runtimeSolibDir = runtimeSolibDir;
+  public CppLinkActionBuilder setToolchainLibrariesSolibDir(
+      PathFragment toolchainLibrariesSolibDir) {
+    this.toolchainLibrariesSolibDir = toolchainLibrariesSolibDir;
     return this;
   }
   
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/LibrariesToLinkCollector.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/LibrariesToLinkCollector.java
index 4994bee..dc7fb3b 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/LibrariesToLinkCollector.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/LibrariesToLinkCollector.java
@@ -17,6 +17,7 @@
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
 import com.google.common.collect.Iterables;
 import com.google.devtools.build.lib.actions.Artifact;
 import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
@@ -24,6 +25,7 @@
 import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.SequenceBuilder;
 import com.google.devtools.build.lib.rules.cpp.Link.LinkStaticness;
 import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType;
+import com.google.devtools.build.lib.util.Pair;
 import com.google.devtools.build.lib.vfs.PathFragment;
 import java.util.HashMap;
 import java.util.Map;
@@ -32,7 +34,7 @@
 public class LibrariesToLinkCollector {
 
   private final boolean isNativeDeps;
-  private final PathFragment runtimeSolibDir;
+  private final PathFragment toolchainLibrariesSolibDir;
   private final CppConfiguration cppConfiguration;
   private final CcToolchainProvider ccToolchainProvider;
   private final Artifact outputArtifact;
@@ -42,25 +44,23 @@
   private final Iterable<LtoBackendArtifacts> allLtoArtifacts;
   private final boolean allowLtoIndexing;
   private final Artifact thinltoParamFile;
-  private final Iterable<? extends LinkerInput> runtimeLinkerInputs;
   private final FeatureConfiguration featureConfiguration;
   private final boolean needWholeArchive;
   private final String rpathRoot;
-  private final boolean runtimeRpath;
+  private final boolean needToolchainLibrariesRpath;
   private final Map<Artifact, Artifact> ltoMap;
 
   public LibrariesToLinkCollector(
       boolean isNativeDeps,
       CppConfiguration cppConfiguration,
       CcToolchainProvider toolchain,
-      PathFragment runtimeSolibDir,
+      PathFragment toolchainLibrariesSolibDir,
       LinkTargetType linkType,
       LinkStaticness linkStaticness,
       Artifact output,
       PathFragment solibDir,
       boolean isLtoIndexing,
       Iterable<LtoBackendArtifacts> allLtoArtifacts,
-      ImmutableList<LinkerInput> runtimeLinkerInputs,
       FeatureConfiguration featureConfiguration,
       Artifact thinltoParamFile,
       boolean allowLtoIndexing,
@@ -69,29 +69,28 @@
     this.isNativeDeps = isNativeDeps;
     this.cppConfiguration = cppConfiguration;
     this.ccToolchainProvider = toolchain;
-    this.runtimeSolibDir = runtimeSolibDir;
+    this.toolchainLibrariesSolibDir = toolchainLibrariesSolibDir;
     this.outputArtifact = output;
     this.solibDir = solibDir;
     this.isLtoIndexing = isLtoIndexing;
     this.allLtoArtifacts = allLtoArtifacts;
-    this.runtimeLinkerInputs = runtimeLinkerInputs;
     this.featureConfiguration = featureConfiguration;
     this.thinltoParamFile = thinltoParamFile;
     this.allowLtoIndexing = allowLtoIndexing;
     this.linkerInputs = linkerInputs;
     this.needWholeArchive = needWholeArchive;
 
-    runtimeRpath =
-        runtimeSolibDir != null
+    needToolchainLibrariesRpath =
+        toolchainLibrariesSolibDir != null
             && (linkType.isDynamicLibrary()
-            || (linkType == LinkTargetType.EXECUTABLE
-            && linkStaticness == LinkStaticness.DYNAMIC));
+                || (linkType == LinkTargetType.EXECUTABLE
+                    && linkStaticness == LinkStaticness.DYNAMIC));
 
     // Calculate the correct relative value for the "-rpath" link option (which sets
     // the search path for finding shared libraries).
     if (isNativeDeps && cppConfiguration.shareNativeDeps()) {
       // For shared native libraries, special symlinking is applied to ensure C++
-      // runtimes are available under $ORIGIN/_solib_[arch]. So we set the RPATH to find
+      // toolchain libraries are available under $ORIGIN/_solib_[arch]. So we set the RPATH to find
       // them.
       //
       // Note that we have to do this because $ORIGIN points to different paths for
@@ -160,43 +159,43 @@
     // --whole-archive ... --no-whole-archive.
     SequenceBuilder librariesToLink = new SequenceBuilder();
 
-    String runtimeSolibName = runtimeSolibDir != null ? runtimeSolibDir.getBaseName() : null;
+    String toolchainLibrariesSolibName =
+        toolchainLibrariesSolibDir != null ? toolchainLibrariesSolibDir.getBaseName() : null;
     if (isNativeDeps && cppConfiguration.shareNativeDeps()) {
-      if (runtimeRpath) {
-        runtimeLibrarySearchDirectories.add("../" + runtimeSolibName + "/");
+      if (needToolchainLibrariesRpath) {
+        runtimeLibrarySearchDirectories.add("../" + toolchainLibrariesSolibName + "/");
       }
     } else {
       // For all other links, calculate the relative path from the output file to _solib_[arch]
       // (the directory where all shared libraries are stored, which resides under the blaze-bin
       // directory. In other words, given blaze-bin/my/package/binary, rpathRoot would be
       // "../../_solib_[arch]".
-      if (runtimeRpath) {
+      if (needToolchainLibrariesRpath) {
         runtimeLibrarySearchDirectories.add(
             Strings.repeat("../", outputArtifact.getRootRelativePath().segmentCount() - 1)
-                + runtimeSolibName
+                + toolchainLibrariesSolibName
                 + "/");
       }
       if (isNativeDeps) {
         // We also retain the $ORIGIN/ path to solibs that are in _solib_<arch>, as opposed to
         // the package directory)
-        if (runtimeRpath) {
-          runtimeLibrarySearchDirectories.add("../" + runtimeSolibName + "/");
+        if (needToolchainLibrariesRpath) {
+          runtimeLibrarySearchDirectories.add("../" + toolchainLibrariesSolibName + "/");
         }
       }
     }
 
-    if (runtimeRpath) {
+    if (needToolchainLibrariesRpath) {
       if (isNativeDeps) {
         runtimeLibrarySearchDirectories.add(".");
       }
-      runtimeLibrarySearchDirectories.add(runtimeSolibName + "/");
+      runtimeLibrarySearchDirectories.add(toolchainLibrariesSolibName + "/");
     }
 
-    boolean includeSolibDir =
+    Pair<Boolean, Boolean> includeSolibsPair =
         addLinkerInputs(librarySearchDirectories, rpathRootsForExplicitSoDeps, librariesToLink);
-    boolean includeRuntimeSolibDir =
-        addRuntimeLinkerInputs(
-            librarySearchDirectories, rpathRootsForExplicitSoDeps, librariesToLink);
+    boolean includeSolibDir = includeSolibsPair.first;
+    boolean includeToolchainLibrariesSolibDir = includeSolibsPair.second;
     Preconditions.checkState(
         ltoMap == null || ltoMap.isEmpty(), "Still have LTO objects left: %s", ltoMap);
 
@@ -206,7 +205,7 @@
       allRuntimeLibrarySearchDirectories.add(rpathRoot);
     }
     allRuntimeLibrarySearchDirectories.addAll(rpathRootsForExplicitSoDeps.build());
-    if (includeRuntimeSolibDir) {
+    if (includeToolchainLibrariesSolibDir) {
       allRuntimeLibrarySearchDirectories.addAll(runtimeLibrarySearchDirectories.build());
     }
 
@@ -216,11 +215,12 @@
         allRuntimeLibrarySearchDirectories.build());
   }
 
-  private boolean addLinkerInputs(
-      ImmutableSet.Builder<String> librarySearchDirectories,
-      ImmutableSet.Builder<String> rpathEntries,
+  private Pair<Boolean, Boolean> addLinkerInputs(
+      Builder<String> librarySearchDirectories,
+      Builder<String> rpathEntries,
       SequenceBuilder librariesToLink) {
     boolean includeSolibDir = false;
+    boolean includeToolchainLibrariesSolibDir = false;
     for (LinkerInput input : linkerInputs) {
       if (input.getArtifactCategory() == ArtifactCategory.DYNAMIC_LIBRARY
           || input.getArtifactCategory() == ArtifactCategory.INTERFACE_LIBRARY) {
@@ -229,20 +229,25 @@
         // under solibDir, so don't check it and don't include solibDir.
         if (!featureConfiguration.isEnabled(CppRuleClasses.COPY_DYNAMIC_LIBRARIES_TO_BINARY)) {
           Preconditions.checkState(
-              libDir.startsWith(solibDir),
-              "Artifact '%s' is not under directory '%s'.",
+              libDir.startsWith(solibDir) || libDir.startsWith(toolchainLibrariesSolibDir),
+              "Artifact '%s' is not under directory expected '%s',"
+                  + " neither it is in directory for toolchain libraries '%'.",
               input.getArtifact(),
-              solibDir);
+              solibDir,
+              toolchainLibrariesSolibDir);
           if (libDir.equals(solibDir)) {
             includeSolibDir = true;
           }
+          if (libDir.equals(toolchainLibrariesSolibDir)) {
+            includeToolchainLibrariesSolibDir = true;
+          }
         }
         addDynamicInputLinkOptions(input, librariesToLink, librarySearchDirectories, rpathEntries);
       } else {
-        addStaticInputLinkOptions(input, librariesToLink, false);
+        addStaticInputLinkOptions(input, librariesToLink);
       }
     }
-    return includeSolibDir;
+    return Pair.of(includeSolibDir, includeToolchainLibrariesSolibDir);
   }
 
   /**
@@ -264,7 +269,8 @@
 
     Artifact inputArtifact = input.getArtifact();
     PathFragment libDir = inputArtifact.getExecPath().getParentDirectory();
-    if (!libDir.equals(solibDir) && (runtimeSolibDir == null || !runtimeSolibDir.equals(libDir))) {
+    if (!libDir.equals(solibDir)
+        && (toolchainLibrariesSolibDir == null || !toolchainLibrariesSolibDir.equals(libDir))) {
       String dotdots = "";
       PathFragment commonParent = solibDir;
       while (!libDir.startsWith(commonParent)) {
@@ -303,8 +309,7 @@
    *
    * @param librariesToLink - a collection that will be exposed as a build variable.
    */
-  private void addStaticInputLinkOptions(
-      LinkerInput input, SequenceBuilder librariesToLink, boolean isRuntimeLinkerInput) {
+  private void addStaticInputLinkOptions(LinkerInput input, SequenceBuilder librariesToLink) {
     ArtifactCategory artifactCategory = input.getArtifactCategory();
     Preconditions.checkState(artifactCategory != ArtifactCategory.DYNAMIC_LIBRARY);
     // If we had any LTO artifacts, ltoMap whould be non-null. In that case,
@@ -340,9 +345,8 @@
         }
         ImmutableList<Artifact> nonLtoArchiveMembers = nonLtoArchiveMembersBuilder.build();
         if (!nonLtoArchiveMembers.isEmpty()) {
-          boolean inputIsWholeArchive = !isRuntimeLinkerInput && needWholeArchive;
           librariesToLink.addValue(
-              LibraryToLinkValue.forObjectFileGroup(nonLtoArchiveMembers, inputIsWholeArchive));
+              LibraryToLinkValue.forObjectFileGroup(nonLtoArchiveMembers, needWholeArchive));
         }
       }
     } else {
@@ -353,8 +357,7 @@
       boolean isAlwaysLinkStaticLibrary =
           artifactCategory == ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY;
       boolean inputIsWholeArchive =
-          (!isRuntimeLinkerInput && (isAlwaysLinkStaticLibrary || needWholeArchive))
-              || (isRuntimeLinkerInput && isAlwaysLinkStaticLibrary && !needWholeArchive);
+          !input.disableWholeArchive() && (isAlwaysLinkStaticLibrary || needWholeArchive);
 
       Artifact inputArtifact = input.getArtifact();
       Artifact a;
@@ -408,32 +411,6 @@
             PathFragment.create(CppLinkActionBuilder.SHARED_NONLTO_BACKEND_ROOT_PREFIX));
   }
 
-  private boolean addRuntimeLinkerInputs(
-      ImmutableSet.Builder<String> librarySearchDirectories,
-      ImmutableSet.Builder<String> rpathRootsForExplicitSoDeps,
-      SequenceBuilder librariesToLink) {
-    boolean includeRuntimeSolibDir = false;
-    for (LinkerInput input : runtimeLinkerInputs) {
-      if (input.getArtifactCategory() == ArtifactCategory.DYNAMIC_LIBRARY
-          || input.getArtifactCategory() == ArtifactCategory.INTERFACE_LIBRARY) {
-        PathFragment libDir = input.getArtifact().getExecPath().getParentDirectory();
-        if (!featureConfiguration.isEnabled(CppRuleClasses.COPY_DYNAMIC_LIBRARIES_TO_BINARY)) {
-          Preconditions.checkState(
-              runtimeSolibDir != null && libDir.equals(runtimeSolibDir),
-              "Artifact '%s' is not under directory '%s'.",
-              input.getArtifact(),
-              solibDir);
-          includeRuntimeSolibDir = true;
-        }
-        addDynamicInputLinkOptions(
-            input, librariesToLink, librarySearchDirectories, rpathRootsForExplicitSoDeps);
-      } else {
-        addStaticInputLinkOptions(input, librariesToLink, true);
-      }
-    }
-    return includeRuntimeSolibDir;
-  }
-
   private Map<Artifact, Artifact> generateLtoMap() {
     if (isLtoIndexing || allLtoArtifacts == null) {
       return null;
@@ -453,4 +430,4 @@
     }
     return ltoMap;
   }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/Link.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/Link.java
index daf26b6..74142be 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/Link.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/Link.java
@@ -396,9 +396,12 @@
         // deps is true, in which case this code only computes the list of inputs for the link
         // action (so the order isn't critical).
         if (passMembersToLinkCmd || (deps && needMembersForLink)) {
-          delayList = LinkerInputs
-              .simpleLinkerInputs(inputLibrary.getObjectFiles(), ArtifactCategory.OBJECT_FILE)
-              .iterator();
+          delayList =
+              LinkerInputs.simpleLinkerInputs(
+                      inputLibrary.getObjectFiles(),
+                      ArtifactCategory.OBJECT_FILE,
+                      /* disableWholeArchive= */ false)
+                  .iterator();
         }
 
         if (!(passMembersToLinkCmd || (deps && useStartEndLib(inputLibrary, archiveType)))) {
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 4d74748..81fa782 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
@@ -50,11 +50,10 @@
   @Nullable private final FeatureConfiguration featureConfiguration;
   private final ImmutableList<Artifact> buildInfoHeaderArtifacts;
   private final Iterable<LinkerInput> linkerInputs;
-  private final Iterable<LinkerInput> runtimeInputs;
   private final LinkTargetType linkTargetType;
   private final LinkStaticness linkStaticness;
   private final ImmutableList<String> linkopts;
-  @Nullable private final PathFragment runtimeSolibDir;
+  @Nullable private final PathFragment toolchainLibrariesSolibDir;
   private final boolean nativeDeps;
   private final boolean useTestOnlyFlags;
 
@@ -66,11 +65,10 @@
       String forcedToolPath,
       ImmutableList<Artifact> buildInfoHeaderArtifacts,
       Iterable<LinkerInput> linkerInputs,
-      Iterable<LinkerInput> runtimeInputs,
       LinkTargetType linkTargetType,
       LinkStaticness linkStaticness,
       ImmutableList<String> linkopts,
-      @Nullable PathFragment runtimeSolibDir,
+      @Nullable PathFragment toolchainLibrariesSolibDir,
       boolean nativeDeps,
       boolean useTestOnlyFlags,
       @Nullable Artifact paramFile,
@@ -83,11 +81,10 @@
     this.featureConfiguration = featureConfiguration;
     this.buildInfoHeaderArtifacts = Preconditions.checkNotNull(buildInfoHeaderArtifacts);
     this.linkerInputs = Preconditions.checkNotNull(linkerInputs);
-    this.runtimeInputs = Preconditions.checkNotNull(runtimeInputs);
     this.linkTargetType = Preconditions.checkNotNull(linkTargetType);
     this.linkStaticness = Preconditions.checkNotNull(linkStaticness);
     this.linkopts = linkopts;
-    this.runtimeSolibDir = runtimeSolibDir;
+    this.toolchainLibrariesSolibDir = toolchainLibrariesSolibDir;
     this.nativeDeps = nativeDeps;
     this.useTestOnlyFlags = useTestOnlyFlags;
     this.paramFile = paramFile;
@@ -108,11 +105,6 @@
     return linkerInputs;
   }
 
-  /** Returns the runtime inputs to the linker. */
-  public Iterable<LinkerInput> getRuntimeInputs() {
-    return runtimeInputs;
-  }
-
   /**
    * Returns the current type of link target set.
    */
@@ -147,8 +139,9 @@
    * libraries either do not exist (because they do not come from the depot) or they are in the
    * regular solib directory.
    */
-  @Nullable public PathFragment getRuntimeSolibDir() {
-    return runtimeSolibDir;
+  @Nullable
+  public PathFragment getToolchainLibrariesSolibDir() {
+    return toolchainLibrariesSolibDir;
   }
 
   /**
@@ -422,11 +415,10 @@
     private String forcedToolPath;
     private ImmutableList<Artifact> buildInfoHeaderArtifacts = ImmutableList.of();
     private Iterable<LinkerInput> linkerInputs = ImmutableList.of();
-    private Iterable<LinkerInput> runtimeInputs = ImmutableList.of();
     @Nullable private LinkTargetType linkTargetType;
     private LinkStaticness linkStaticness = LinkStaticness.FULLY_STATIC;
     private ImmutableList<String> linkopts = ImmutableList.of();
-    @Nullable private PathFragment runtimeSolibDir;
+    @Nullable private PathFragment toolchainLibrariesSolibDir;
     private boolean nativeDeps;
     private boolean useTestOnlyFlags;
     @Nullable private Artifact paramFile;
@@ -461,11 +453,10 @@
           forcedToolPath,
           buildInfoHeaderArtifacts,
           linkerInputs,
-          runtimeInputs,
           linkTargetType,
           linkStaticness,
           linkopts,
-          runtimeSolibDir,
+          toolchainLibrariesSolibDir,
           nativeDeps,
           useTestOnlyFlags,
           paramFile,
@@ -507,11 +498,6 @@
       return this;
     }
 
-    public Builder setRuntimeInputs(ImmutableList<LinkerInput> runtimeInputs) {
-      this.runtimeInputs = runtimeInputs;
-      return this;
-    }
-
     /**
      * Sets the linker options. These are passed to the linker in addition to the other linker
      * options like linker inputs, symbol count options, etc. The {@link #build} method throws an
@@ -573,8 +559,8 @@
       return this;
     }
 
-    public Builder setRuntimeSolibDir(PathFragment runtimeSolibDir) {
-      this.runtimeSolibDir = runtimeSolibDir;
+    public Builder setToolchainLibrariesSolibDir(PathFragment toolchainLibrariesSolibDir) {
+      this.toolchainLibrariesSolibDir = toolchainLibrariesSolibDir;
       return this;
     }
   }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkerInput.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkerInput.java
index 3b0c361..c0692cd 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkerInput.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkerInput.java
@@ -58,4 +58,7 @@
    * Returns whether we must keep debug symbols for this input.
    */
   boolean isMustKeepDebug();
+
+  /** If true, Bazel will not wrap this input in whole-archive block. */
+  boolean disableWholeArchive();
 }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkerInputs.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkerInputs.java
index a71c384..ad811e0 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkerInputs.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/LinkerInputs.java
@@ -36,9 +36,11 @@
   public static class SimpleLinkerInput implements LinkerInput {
     private final Artifact artifact;
     private final ArtifactCategory category;
+    private final boolean disableWholeArchive;
 
     @AutoCodec.Instantiator
-    public SimpleLinkerInput(Artifact artifact, ArtifactCategory category) {
+    public SimpleLinkerInput(
+        Artifact artifact, ArtifactCategory category, boolean disableWholeArchive) {
       String basename = artifact.getFilename();
       switch (category) {
         case STATIC_LIBRARY:
@@ -61,6 +63,7 @@
       }
       this.artifact = Preconditions.checkNotNull(artifact);
       this.category = category;
+      this.disableWholeArchive = disableWholeArchive;
     }
 
     @Override
@@ -121,6 +124,11 @@
     public boolean isMustKeepDebug() {
       return false;
     }
+
+    @Override
+    public boolean disableWholeArchive() {
+      return disableWholeArchive;
+    }
   }
 
   /**
@@ -130,7 +138,7 @@
   @ThreadSafety.Immutable
   private static class FakeLinkerInput extends SimpleLinkerInput {
     private FakeLinkerInput(Artifact artifact) {
-      super(artifact, ArtifactCategory.OBJECT_FILE);
+      super(artifact, ArtifactCategory.OBJECT_FILE, /* disableWholeArchive= */ false);
       Preconditions.checkState(Link.OBJECT_FILETYPES.matches(artifact.getFilename()));
     }
 
@@ -264,6 +272,11 @@
     public boolean isMustKeepDebug() {
       return false;
     }
+
+    @Override
+    public boolean disableWholeArchive() {
+      return false;
+    }
   }
 
   /** This class represents a library that may contain object files. */
@@ -411,28 +424,31 @@
     public boolean isMustKeepDebug() {
       return this.mustKeepDebug;
     }
+
+    @Override
+    public boolean disableWholeArchive() {
+      return false;
+    }
   }
 
   //////////////////////////////////////////////////////////////////////////////////////
   // Public factory constructors:
   //////////////////////////////////////////////////////////////////////////////////////
 
-  /**
-   * Creates linker input objects for non-library files.
-   */
-  public static Iterable<LinkerInput> simpleLinkerInputs(Iterable<Artifact> input,
-      final ArtifactCategory category) {
-    return Iterables.transform(input, artifact -> simpleLinkerInput(artifact, category));
+  /** Creates linker input objects for non-library files. */
+  public static Iterable<LinkerInput> simpleLinkerInputs(
+      Iterable<Artifact> input, final ArtifactCategory category, boolean disableWholeArchive) {
+    return Iterables.transform(
+        input, artifact -> simpleLinkerInput(artifact, category, disableWholeArchive));
   }
 
-  /**
-   * Creates a linker input for which we do not know what objects files it consists of.
-   */
-  public static LinkerInput simpleLinkerInput(Artifact artifact, ArtifactCategory category) {
+  /** Creates a linker input for which we do not know what objects files it consists of. */
+  public static LinkerInput simpleLinkerInput(
+      Artifact artifact, ArtifactCategory category, boolean disableWholeArchive) {
     // This precondition check was in place and *most* of the tests passed with them; the only
     // exception is when you mention a generated .a file in the srcs of a cc_* rule.
     // Preconditions.checkArgument(!ARCHIVE_LIBRARY_FILETYPES.contains(artifact.getFileType()));
-    return new SimpleLinkerInput(artifact, category);
+    return new SimpleLinkerInput(artifact, category, disableWholeArchive);
   }
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/NativeLibraryNestedSetBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/java/NativeLibraryNestedSetBuilder.java
index c7a953d..2767d50 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/NativeLibraryNestedSetBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/NativeLibraryNestedSetBuilder.java
@@ -45,7 +45,9 @@
    */
   public NativeLibraryNestedSetBuilder addAll(Iterable<Artifact> deps) {
     for (Artifact dep : deps) {
-      builder.add(new LinkerInputs.SimpleLinkerInput(dep, ArtifactCategory.DYNAMIC_LIBRARY));
+      builder.add(
+          new LinkerInputs.SimpleLinkerInput(
+              dep, ArtifactCategory.DYNAMIC_LIBRARY, /* disableWholeArchive= */ false));
     }
     return this;
   }
@@ -112,7 +114,9 @@
     for (Artifact artifact : FileType.filterList(
         dep.getProvider(FileProvider.class).getFilesToBuild(),
         CppFileTypes.SHARED_LIBRARY)) {
-      builder.add(new LinkerInputs.SimpleLinkerInput(artifact, ArtifactCategory.DYNAMIC_LIBRARY));
+      builder.add(
+          new LinkerInputs.SimpleLinkerInput(
+              artifact, ArtifactCategory.DYNAMIC_LIBRARY, /* disableWholeArchive= */ false));
     }
   }
 }
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 beb4734..83ed1d7 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
@@ -334,7 +334,7 @@
             builder.setUseTestOnlyFlags(
                 attributesToFlip.contains(NonStaticAttributes.USE_TEST_ONLY_FLAGS));
             builder.setFake(attributesToFlip.contains(NonStaticAttributes.FAKE));
-            builder.setRuntimeSolibDir(
+            builder.setToolchainLibrariesSolibDir(
                 attributesToFlip.contains(NonStaticAttributes.RUNTIME_SOLIB_DIR)
                     ? null
                     : PathFragment.create("so1"));