// Copyright 2016 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.build.lib.rules.cpp;

import static java.nio.charset.StandardCharsets.ISO_8859_1;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.ActionOwner;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ParameterFile;
import com.google.devtools.build.lib.analysis.AnalysisEnvironment;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.collect.CollectionUtils;
import com.google.devtools.build.lib.collect.ImmutableIterable;
import com.google.devtools.build.lib.collect.IterablesChain;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.packages.RuleErrorConsumer;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.Variables.VariablesExtension;
import com.google.devtools.build.lib.rules.cpp.CppLinkAction.Context;
import com.google.devtools.build.lib.rules.cpp.CppLinkAction.LinkArtifactFactory;
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.rules.cpp.Link.Staticness;
import com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink;
import com.google.devtools.build.lib.util.Preconditions;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

/** Builder class to construct {@link CppLinkAction}s. */
public class CppLinkActionBuilder {

  /** A build variable for clang flags that set the root of the linker search path. */
  public static final String RUNTIME_ROOT_FLAGS_VARIABLE = "runtime_root_flags";

  /** A build variable for entries in the linker search path. */
  public static final String RUNTIME_ROOT_ENTRIES_VARIABLE = "runtime_root_entries";

  /**
   * A build variable for options applying to specific libraries in the linker invocation that
   * either identify a library to be linked or add a directory to the runtime library search path.
   */
  public static final String LIBOPTS_VARIABLE = "libopts";

  /**
   * A build variable for flags providing files to link as inputs in the linker invocation that
   * should not go in a -whole_archive block.
   */
  public static final String LINKER_INPUT_PARAMS_VARIABLE = "linker_input_params";

  /**
   * A build variable for flags providing files to link as inputs in the linker invocation that
   * should go in a -whole_archive block.
   */
  public static final String WHOLE_ARCHIVE_LINKER_INPUT_PARAMS_VARIABLE =
      "whole_archive_linker_params";

  /** A build variable whose presence indicates that whole archive flags should be applied. */
  public static final String GLOBAL_WHOLE_ARCHIVE_VARIABLE = "global_whole_archive";

  /** A build variable for the execpath of the output of the linker. */
  public static final String OUTPUT_EXECPATH_VARIABLE = "output_execpath";

  /**
   * A build variable that is set to indicate a mostly static linking for which the linked binary
   * should be piped to /dev/null.
   */
  public static final String SKIP_MOSTLY_STATIC_VARIABLE = "skip_mostly_static";

  /** A build variable giving a path to which to write symbol counts. */
  public static final String SYMBOL_COUNTS_OUTPUT_VARIABLE = "symbol_counts_output";

  /** A build variable giving linkstamp paths. */
  public static final String LINKSTAMP_PATHS_VARIABLE = "linkstamp_paths";

  /** A build variable whose presence indicates that PIC code should be generated. */
  public static final String FORCE_PIC_VARIABLE = "force_pic";

  // Builder-only
  // Null when invoked from tests (e.g. via createTestBuilder).
  @Nullable private final RuleContext ruleContext;
  private final AnalysisEnvironment analysisEnvironment;
  private final Artifact output;

  // can be null for CppLinkAction.createTestBuilder()
  @Nullable private final CcToolchainProvider toolchain;
  private Artifact interfaceOutput;
  private Artifact symbolCounts;
  private PathFragment runtimeSolibDir;
  protected final BuildConfiguration configuration;
  private final CppConfiguration cppConfiguration;
  private FeatureConfiguration featureConfiguration;

  // Morally equivalent with {@link Context}, except these are mutable.
  // Keep these in sync with {@link Context}.
  private final Set<LinkerInput> objectFiles = new LinkedHashSet<>();
  private final Set<Artifact> nonCodeInputs = new LinkedHashSet<>();
  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 final NestedSetBuilder<Artifact> compilationInputs = NestedSetBuilder.stableOrder();
  private final Set<Artifact> linkstamps = new LinkedHashSet<>();
  private List<String> linkstampOptions = new ArrayList<>();
  private final List<String> linkopts = new ArrayList<>();
  private LinkTargetType linkType = LinkTargetType.STATIC_LIBRARY;
  private LinkStaticness linkStaticness = LinkStaticness.FULLY_STATIC;
  private String libraryIdentifier = null;
  private List<Artifact> ltoBitcodeFiles = new ArrayList<>();

  private boolean fake;
  private boolean isNativeDeps;
  private boolean useTestOnlyFlags;
  private boolean wholeArchive;
  private LinkArtifactFactory linkArtifactFactory = CppLinkAction.DEFAULT_ARTIFACT_FACTORY;

  private boolean isLTOIndexing = false;
  private Iterable<LTOBackendArtifacts> allLTOArtifacts = null;
  
  private final List<VariablesExtension> variablesExtensions = new ArrayList<>();
  private final List<Artifact> linkActionInputs = new ArrayList<>();

  /**
   * Creates a builder that builds {@link CppLinkAction} instances.
   *
   * @param ruleContext the rule that owns the action
   * @param output the output artifact
   */
  public CppLinkActionBuilder(RuleContext ruleContext, Artifact output) {
    this(
        ruleContext,
        output,
        ruleContext.getConfiguration(),
        ruleContext.getAnalysisEnvironment(),
        CppHelper.getToolchain(ruleContext));
  }

  /**
   * Creates a builder that builds {@link CppLinkAction} instances.
   *
   * @param ruleContext the rule that owns the action
   * @param output the output artifact
   */
  public CppLinkActionBuilder(
      RuleContext ruleContext,
      Artifact output,
      BuildConfiguration configuration,
      CcToolchainProvider toolchain) {
    this(ruleContext, output, configuration, ruleContext.getAnalysisEnvironment(), toolchain);
  }

  /**
   * Creates a builder that builds {@link CppLinkAction}s.
   *
   * @param ruleContext the rule that owns the action
   * @param output the output artifact
   * @param configuration the configuration used to determine the tool chain and the default link
   *     options
   */
  private CppLinkActionBuilder(
      @Nullable RuleContext ruleContext,
      Artifact output,
      BuildConfiguration configuration,
      AnalysisEnvironment analysisEnvironment,
      CcToolchainProvider toolchain) {
    this.ruleContext = ruleContext;
    this.analysisEnvironment = Preconditions.checkNotNull(analysisEnvironment);
    this.output = Preconditions.checkNotNull(output);
    this.configuration = Preconditions.checkNotNull(configuration);
    this.cppConfiguration = configuration.getFragment(CppConfiguration.class);
    this.toolchain = toolchain;
    if (cppConfiguration.supportsEmbeddedRuntimes() && toolchain != null) {
      runtimeSolibDir = toolchain.getDynamicRuntimeSolibDir();
    }
  }

  /**
   * Given a Context, creates a Builder that builds {@link CppLinkAction}s. Note well: Keep the
   * Builder->Context and Context->Builder transforms consistent!
   *
   * @param ruleContext the rule that owns the action
   * @param output the output artifact
   * @param linkContext an immutable CppLinkAction.Context from the original builder
   */
  public CppLinkActionBuilder(
      RuleContext ruleContext,
      Artifact output,
      Context linkContext,
      BuildConfiguration configuration) {
    // These Builder-only fields get set in the constructor:
    //   ruleContext, analysisEnvironment, outputPath, configuration, runtimeSolibDir
    this(
        ruleContext,
        output,
        configuration,
        ruleContext.getAnalysisEnvironment(),
        CppHelper.getToolchain(ruleContext));
    Preconditions.checkNotNull(linkContext);

    // All linkContext fields should be transferred to this Builder.
    this.objectFiles.addAll(linkContext.objectFiles);
    this.nonCodeInputs.addAll(linkContext.nonCodeInputs);
    this.libraries.addTransitive(linkContext.libraries);
    this.crosstoolInputs = linkContext.crosstoolInputs;
    this.runtimeMiddleman = linkContext.runtimeMiddleman;
    this.runtimeInputs = linkContext.runtimeInputs;
    this.runtimeType = linkContext.runtimeType;
    this.compilationInputs.addTransitive(linkContext.compilationInputs);
    this.linkstamps.addAll(linkContext.linkstamps);
    this.linkopts.addAll(linkContext.linkopts);
    this.linkType = linkContext.linkType;
    this.linkStaticness = linkContext.linkStaticness;
    this.fake = linkContext.fake;
    this.isNativeDeps = linkContext.isNativeDeps;
    this.useTestOnlyFlags = linkContext.useTestOnlyFlags;
  }

  /** Returns the action name for purposes of querying the crosstool. */
  private String getActionName() {
    return linkType.getActionName();
  }
  
  /** Returns linker inputs that are not libraries. */
  public Set<LinkerInput> getObjectFiles() {
    return objectFiles;
  }

  public Set<Artifact> getNonCodeInputs() {
    return nonCodeInputs;
  }

  /**
   * Returns linker inputs that are libraries.
   */
  public NestedSetBuilder<LibraryToLink> getLibraries() {
    return libraries;
  }

  /**
   * Returns inputs arising from the crosstool.
   */
  public NestedSet<Artifact> getCrosstoolInputs() {
    return this.crosstoolInputs;
  }
  
  /**
   * Returns the runtime middleman artifact.
   */
  public Artifact getRuntimeMiddleman() {
    return this.runtimeMiddleman;
  }
  
  /**
   * Returns runtime inputs for this link action.
   */
  public NestedSet<Artifact> getRuntimeInputs() {
    return this.runtimeInputs;
  }

  public ArtifactCategory getRuntimeType() {
    return runtimeType;
  }

  /**
   * Returns compilation inputs for this link action.
   */
  public final NestedSetBuilder<Artifact> getCompilationInputs() {
    return this.compilationInputs;
  }
  
  /**
   * Returns linkstamps for this link action.
   */
  public final Set<Artifact> getLinkstamps() {
    return this.linkstamps;
  }
  /**
   * Returns linkstamp options for this link action.
   */
  public List<String> getLinkstampOptions() {
    return this.linkstampOptions;
  }
  
  /**
   * Returns command line options for this link action.
   */
  public final List<String> getLinkopts() {
    return this.linkopts;
  }
  
  /**
   * Returns the type of this link action.
   */
  public LinkTargetType getLinkType() {
    return this.linkType;
  }
  /**
   * Returns the staticness of this link action.
   */
  public LinkStaticness getLinkStaticness() {
    return this.linkStaticness;
  }
  /**
   * Returns lto bitcode files for this link action.
   */
  public List<Artifact> getLtoBitcodeFiles() {
    return this.ltoBitcodeFiles;
  }

  /**
   * Returns true for a cc_fake_binary.
   */
  public boolean isFake() {
    return this.fake;
  }
  
  /**
   * Returns true for native dependencies of another language.
   */
  public boolean isNativeDeps() {
    return this.isNativeDeps;
  }
 
  public CppLinkActionBuilder setLinkArtifactFactory(LinkArtifactFactory linkArtifactFactory) {
    this.linkArtifactFactory = linkArtifactFactory;
    return this;
  }
  
  /**
   * Returns true if this link action uses test only flags.
   */
  public boolean useTestOnlyFlags() {
    return this.useTestOnlyFlags;
  }

  private Iterable<LTOBackendArtifacts> createLTOArtifacts(
      PathFragment ltoOutputRootPrefix, NestedSet<LibraryToLink> uniqueLibraries) {
    Set<Artifact> compiled = new LinkedHashSet<>();
    for (LibraryToLink lib : uniqueLibraries) {
      Iterables.addAll(compiled, lib.getLTOBitcodeFiles());
    }

    // This flattens the set of object files, so for M binaries and N .o files,
    // this is O(M*N). If we had a nested set of .o files, we could have O(M + N) instead.
    Map<PathFragment, Artifact> allBitcode = new HashMap<>();
    for (LibraryToLink lib : uniqueLibraries) {
      if (!lib.containsObjectFiles()) {
        continue;
      }
      for (Artifact a : lib.getObjectFiles()) {
        if (compiled.contains(a)) {
          allBitcode.put(a.getExecPath(), a);
        }
      }
    }
    for (LinkerInput input : objectFiles) {
      if (this.ltoBitcodeFiles.contains(input.getArtifact())) {
        allBitcode.put(input.getArtifact().getExecPath(), input.getArtifact());
      }
    }

    ImmutableList.Builder<LTOBackendArtifacts> ltoOutputs = ImmutableList.builder();
    for (Artifact a : allBitcode.values()) {
      LTOBackendArtifacts ltoArtifacts =
          new LTOBackendArtifacts(
              ltoOutputRootPrefix, a, allBitcode, ruleContext, configuration, linkArtifactFactory);
      ltoOutputs.add(ltoArtifacts);
    }
    return ltoOutputs.build();
  }

  @VisibleForTesting
  boolean canSplitCommandLine() {
    if (toolchain == null || !toolchain.supportsParamFiles()) {
      return false;
    }

    switch (linkType) {
        // We currently can't split dynamic library links if they have interface outputs. That was
        // probably an unintended side effect of the change that introduced interface outputs.
      case DYNAMIC_LIBRARY:
        return interfaceOutput == null;
      case EXECUTABLE:
      case STATIC_LIBRARY:
      case PIC_STATIC_LIBRARY:
      case ALWAYS_LINK_STATIC_LIBRARY:
      case ALWAYS_LINK_PIC_STATIC_LIBRARY:
        return true;

      default:
        return false;
    }
  }

  /** Builds the Action as configured and returns it. */
  public CppLinkAction build() throws InterruptedException {
    Preconditions.checkState(
        (libraryIdentifier == null) == (linkType == LinkTargetType.EXECUTABLE));
    if (interfaceOutput != null && (fake || linkType != LinkTargetType.DYNAMIC_LIBRARY)) {
      throw new RuntimeException(
          "Interface output can only be used " + "with non-fake DYNAMIC_LIBRARY targets");
    }

    final ImmutableList<Artifact> buildInfoHeaderArtifacts =
        !linkstamps.isEmpty()
            ? analysisEnvironment.getBuildInfo(ruleContext, CppBuildInfo.KEY, configuration)
            : ImmutableList.<Artifact>of();

    boolean needWholeArchive =
        wholeArchive
            || needWholeArchive(linkStaticness, linkType, linkopts, isNativeDeps, cppConfiguration);

    NestedSet<LibraryToLink> uniqueLibraries = libraries.build();
    final Iterable<Artifact> objectArtifacts = LinkerInputs.toLibraryArtifacts(objectFiles);

    final Iterable<LinkerInput> linkerInputs =
        IterablesChain.<LinkerInput>builder()
            .add(ImmutableList.copyOf(objectFiles))
            .add(
                ImmutableIterable.from(
                    Link.mergeInputsCmdLine(
                        uniqueLibraries, needWholeArchive, cppConfiguration.archiveType())))
            .build();

    // ruleContext can only be null during testing. This is kind of ugly.
    final ImmutableSet<String> features =
        (ruleContext == null) ? ImmutableSet.<String>of() : ruleContext.getFeatures();

    // For backwards compatibility, and for tests, we permit the link action to be
    // instantiated without a feature configuration.
    if (featureConfiguration == null) {
      if (toolchain != null) {
        featureConfiguration =
            CcCommon.configureFeatures(ruleContext, toolchain, CcLibraryHelper.SourceCategory.CC);
      } else {
        featureConfiguration = CcCommon.configureFeatures(ruleContext);
      }
    }

    final LibraryToLink outputLibrary = linkType == LinkTargetType.EXECUTABLE
        ? null
        : LinkerInputs.newInputLibrary(output,
            linkType.getLinkerOutput(),
            libraryIdentifier,
            objectArtifacts, this.ltoBitcodeFiles);
    final LibraryToLink interfaceOutputLibrary =
        (interfaceOutput == null)
            ? null
            : LinkerInputs.newInputLibrary(interfaceOutput,
                ArtifactCategory.DYNAMIC_LIBRARY,
                libraryIdentifier,
                objectArtifacts, this.ltoBitcodeFiles);

    final ImmutableMap<Artifact, Artifact> linkstampMap =
        mapLinkstampsToOutputs(linkstamps, ruleContext, configuration, output, linkArtifactFactory);

    PathFragment ltoOutputRootPrefix = null;
    if (isLTOIndexing && allLTOArtifacts == null) {
      ltoOutputRootPrefix =
          FileSystemUtils.appendExtension(
              output.getRootRelativePath(), ".lto");
      allLTOArtifacts = createLTOArtifacts(ltoOutputRootPrefix, uniqueLibraries);
    }

    PathFragment linkerParamsFileRootPath = null;
    @Nullable Artifact linkerParamsFile = null;
    if (allLTOArtifacts != null) {
      // Create artifact for the file that the LTO indexing step will emit
      // object file names into for any that were included in the link as
      // determined by the linker's symbol resolution. It will be used to
      // provide the inputs for the subsequent final native object link.
      // Note that the paths emitted into this file will have their prefixes
      // replaced with the final output directory, so they will be the paths
      // of the native object files not the input bitcode files.
      linkerParamsFileRootPath =
          ParameterFile.derivePath(output.getRootRelativePath(), "lto-final");
      linkerParamsFile =
          linkArtifactFactory.create(ruleContext, configuration, linkerParamsFileRootPath);
    }

    final ImmutableList<Artifact> actionOutputs;
    if (isLTOIndexing) {
      ImmutableList.Builder<Artifact> builder = ImmutableList.builder();
      for (LTOBackendArtifacts ltoA : allLTOArtifacts) {
        ltoA.addIndexingOutputs(builder);
      }
      if (linkerParamsFile != null) {
        builder.add(linkerParamsFile);
      }
      actionOutputs = builder.build();
    } else {
      actionOutputs =
          constructOutputs(
              output,
              linkstampMap.values(),
              interfaceOutputLibrary == null ? null : interfaceOutputLibrary.getArtifact(),
              symbolCounts);
    }

    ImmutableList<LinkerInput> runtimeLinkerInputs =
        ImmutableList.copyOf(LinkerInputs.simpleLinkerInputs(runtimeInputs, runtimeType));

    // Add build variables necessary to template link args into the crosstool.
    Variables.Builder buildVariablesBuilder = new Variables.Builder();
    CppLinkVariablesExtension variablesExtension =
        isLTOIndexing
            ? new CppLinkVariablesExtension(
                configuration,
                linkstampMap,
                needWholeArchive,
                linkerInputs,
                runtimeLinkerInputs,
                null,
                linkerParamsFile,
                ltoOutputRootPrefix)
            : new CppLinkVariablesExtension(
                configuration,
                linkstampMap,
                needWholeArchive,
                linkerInputs,
                runtimeLinkerInputs,
                output,
                linkerParamsFile,
                PathFragment.EMPTY_FRAGMENT);
    variablesExtension.addVariables(buildVariablesBuilder);
    for (VariablesExtension extraVariablesExtension : variablesExtensions) {
      extraVariablesExtension.addVariables(buildVariablesBuilder);
    }
    Variables buildVariables = buildVariablesBuilder.build();

    PathFragment paramRootPath =
        ParameterFile.derivePath(output.getRootRelativePath(), (isLTOIndexing) ? "lto-index" : "2");

    @Nullable
    final Artifact paramFile =
        canSplitCommandLine()
            ? linkArtifactFactory.create(ruleContext, configuration, paramRootPath)
            : null;

    Preconditions.checkArgument(
        linkType != LinkTargetType.INTERFACE_DYNAMIC_LIBRARY,
        "you can't link an interface dynamic library directly");
    if (linkType != LinkTargetType.DYNAMIC_LIBRARY) {
      Preconditions.checkArgument(
          interfaceOutput == null,
          "interface output may only be non-null for dynamic library links");
    }
    if (linkType.staticness() == Staticness.STATIC) {
      // solib dir must be null for static links
      runtimeSolibDir = null;

      Preconditions.checkArgument(
          linkStaticness == LinkStaticness.FULLY_STATIC, "static library link must be static");
      Preconditions.checkArgument(
          symbolCounts == null, "the symbol counts output must be null for static links");
      Preconditions.checkArgument(
          !isNativeDeps, "the native deps flag must be false for static links");
      Preconditions.checkArgument(
          !needWholeArchive, "the need whole archive flag must be false for static links");
    }

    LinkCommandLine.Builder linkCommandLineBuilder =
        new LinkCommandLine.Builder(configuration, getOwner(), ruleContext)
            .setLinkerInputs(linkerInputs)
            .setRuntimeInputs(runtimeLinkerInputs)
            .setLinkTargetType(linkType)
            .setLinkStaticness(linkStaticness)
            .setFeatures(features)
            .setRuntimeSolibDir(linkType.staticness() == Staticness.STATIC ? null : runtimeSolibDir)
            .setNativeDeps(isNativeDeps)
            .setUseTestOnlyFlags(useTestOnlyFlags)
            .setParamFile(paramFile)
            .setToolchain(toolchain)
            .setBuildVariables(buildVariables)
            .setFeatureConfiguration(featureConfiguration);

    // TODO(b/30228443): Refactor noWholeArchiveInputs into action_configs, and remove this.
    if (needWholeArchive) {
      linkCommandLineBuilder.setNoWholeArchiveFlags(variablesExtension.getNoWholeArchiveInputs());
    }

    if (!isLTOIndexing) {
      linkCommandLineBuilder
          .setOutput(output)
          .setInterfaceOutput(interfaceOutput)
          .setBuildInfoHeaderArtifacts(buildInfoHeaderArtifacts)
          .setInterfaceSoBuilder(getInterfaceSoBuilder())
          .setLinkstamps(linkstampMap)
          .setLinkopts(ImmutableList.copyOf(linkopts))
          .addLinkstampCompileOptions(linkstampOptions);
    } else {
      List<String> opts = new ArrayList<>(linkopts);
      opts.addAll(featureConfiguration.getCommandLine("lto-indexing", buildVariables));
      linkCommandLineBuilder.setLinkopts(ImmutableList.copyOf(opts));
    }

    LinkCommandLine linkCommandLine = linkCommandLineBuilder.build();

    // Compute the set of inputs - we only need stable order here.
    NestedSetBuilder<Artifact> dependencyInputsBuilder = NestedSetBuilder.stableOrder();
    dependencyInputsBuilder.addTransitive(crosstoolInputs);
    dependencyInputsBuilder.addAll(linkActionInputs);
    if (runtimeMiddleman != null) {
      dependencyInputsBuilder.add(runtimeMiddleman);
    }
    if (!isLTOIndexing) {
      dependencyInputsBuilder.addAll(buildInfoHeaderArtifacts);
      dependencyInputsBuilder.addAll(linkstamps);
      dependencyInputsBuilder.addTransitive(compilationInputs.build());
    }

    Iterable<Artifact> expandedInputs =
        LinkerInputs.toLibraryArtifacts(
            Link.mergeInputsDependencies(
                uniqueLibraries, needWholeArchive, cppConfiguration.archiveType()));
    Iterable<Artifact> expandedNonLibraryInputs = LinkerInputs.toLibraryArtifacts(objectFiles);

    if (!isLTOIndexing && allLTOArtifacts != null) {
      // We are doing LTO, and this is the real link, so substitute
      // the LTO bitcode files with the real object files they were translated into.
      Map<Artifact, Artifact> ltoMapping = new HashMap<>();
      for (LTOBackendArtifacts a : allLTOArtifacts) {
        ltoMapping.put(a.getBitcodeFile(), a.getObjectFile());
      }

      // Handle libraries.
      List<Artifact> renamedInputs = new ArrayList<>();
      for (Artifact a : expandedInputs) {
        Artifact renamed = ltoMapping.get(a);
        renamedInputs.add(renamed == null ? a : renamed);
      }
      expandedInputs = renamedInputs;

      // Handle non-libraries.
      List<Artifact> renamedNonLibraryInputs = new ArrayList<>();
      for (Artifact a : expandedNonLibraryInputs) {
        Artifact renamed = ltoMapping.get(a);
        renamedNonLibraryInputs.add(renamed == null ? a : renamed);
      }
      expandedNonLibraryInputs = renamedNonLibraryInputs;
    } else if (isLTOIndexing && allLTOArtifacts != null) {
      for (LTOBackendArtifacts a : allLTOArtifacts) {
        List<String> argv = new ArrayList<>();
        argv.addAll(cppConfiguration.getLinkOptions());
        argv.addAll(cppConfiguration.getCompilerOptions(features));
        a.setCommandLine(argv);
      }
    }

    // getPrimaryInput returns the first element, and that is a public interface - therefore the
    // order here is important.
    IterablesChain.Builder<Artifact> inputsBuilder =
        IterablesChain.<Artifact>builder()
            .add(ImmutableList.copyOf(expandedNonLibraryInputs))
            .add(ImmutableList.copyOf(nonCodeInputs))
            .add(dependencyInputsBuilder.build())
            .add(ImmutableIterable.from(expandedInputs));

    if (linkerParamsFile != null && !isLTOIndexing) {
      inputsBuilder.add(ImmutableList.of(linkerParamsFile));
    }
    if (linkCommandLine.getParamFile() != null) {
      inputsBuilder.add(ImmutableList.of(linkCommandLine.getParamFile()));
      Action parameterFileWriteAction =
          new ParameterFileWriteAction(
              getOwner(),
              paramFile,
              linkCommandLine.paramCmdLine(),
              ParameterFile.ParameterFileType.UNQUOTED,
              ISO_8859_1);
      analysisEnvironment.registerAction(parameterFileWriteAction);
    }

    Map<String, String> toolchainEnv =
        featureConfiguration.getEnvironmentVariables(getActionName(), buildVariables);

    // If the crosstool uses action_configs to configure cc compilation, collect execution info
    // from there, otherwise, use no execution info.
    // TODO(b/27903698): Assert that the crosstool has an action_config for this action.
    ImmutableSet.Builder<String> executionRequirements = ImmutableSet.<String>builder();
    if (featureConfiguration.actionIsConfigured(getActionName())) {
      executionRequirements.addAll(
          featureConfiguration.getToolForAction(getActionName()).getExecutionRequirements());
    }

    return new CppLinkAction(
        getOwner(),
        inputsBuilder.deduplicate().build(),
        actionOutputs,
        cppConfiguration,
        outputLibrary,
        output,
        interfaceOutputLibrary,
        fake,
        isLTOIndexing,
        allLTOArtifacts,
        linkCommandLine,
        toolchainEnv,
        executionRequirements.build());
  }

  /** The default heuristic on whether we need to use whole-archive for the link. */
  private static boolean needWholeArchive(
      LinkStaticness staticness,
      LinkTargetType type,
      Collection<String> linkopts,
      boolean isNativeDeps,
      CppConfiguration cppConfig) {
    boolean fullyStatic = (staticness == LinkStaticness.FULLY_STATIC);
    boolean mostlyStatic = (staticness == LinkStaticness.MOSTLY_STATIC);
    boolean sharedLinkopts =
        type == LinkTargetType.DYNAMIC_LIBRARY
            || linkopts.contains("-shared")
            || cppConfig.getLinkOptions().contains("-shared");
    return (isNativeDeps || cppConfig.legacyWholeArchive())
        && (fullyStatic || mostlyStatic)
        && sharedLinkopts;
  }

  private static ImmutableList<Artifact> constructOutputs(
      Artifact primaryOutput, Collection<Artifact> outputList, Artifact... outputs) {
    return new ImmutableList.Builder<Artifact>()
        .add(primaryOutput)
        .addAll(outputList)
        .addAll(CollectionUtils.asListWithoutNulls(outputs))
        .build();
  }

  /**
   * Translates a collection of linkstamp source files to an immutable mapping from source files to
   * object files. In other words, given a set of source files, this method determines the output
   * path to which each file should be compiled.
   *
   * @param linkstamps collection of linkstamp source files
   * @param ruleContext the rule for which this link is being performed
   * @param outputBinary the binary output path for this link
   * @return an immutable map that pairs each source file with the corresponding object file that
   *     should be fed into the link
   */
  public static ImmutableMap<Artifact, Artifact> mapLinkstampsToOutputs(
      Collection<Artifact> linkstamps,
      RuleContext ruleContext,
      BuildConfiguration configuration,
      Artifact outputBinary,
      LinkArtifactFactory linkArtifactFactory) {
    ImmutableMap.Builder<Artifact, Artifact> mapBuilder = ImmutableMap.builder();

    PathFragment outputBinaryPath = outputBinary.getRootRelativePath();
    PathFragment stampOutputDirectory =
        outputBinaryPath
            .getParentDirectory()
            .getRelative("_objs")
            .getRelative(outputBinaryPath.getBaseName());

    for (Artifact linkstamp : linkstamps) {
      PathFragment stampOutputPath =
          stampOutputDirectory.getRelative(
              FileSystemUtils.replaceExtension(linkstamp.getRootRelativePath(), ".o"));
      mapBuilder.put(
          linkstamp,
          // Note that link stamp actions can be shared between link actions that output shared
          // native dep libraries.
          linkArtifactFactory.create(ruleContext, configuration, stampOutputPath));
    }
    return mapBuilder.build();
  }

  protected ActionOwner getOwner() {
    return ruleContext.getActionOwner();
  }

  protected Artifact getInterfaceSoBuilder() {
    return analysisEnvironment.getEmbeddedToolArtifact(CppRuleClasses.BUILD_INTERFACE_SO);
  }

  /** Set the crosstool inputs required for the action. */
  public CppLinkActionBuilder setCrosstoolInputs(NestedSet<Artifact> inputs) {
    this.crosstoolInputs = inputs;
    return this;
  }

  /** Sets the feature configuration for the action. */
  public CppLinkActionBuilder setFeatureConfiguration(FeatureConfiguration featureConfiguration) {
    this.featureConfiguration = featureConfiguration;
    return this;
  }

  /**
   * This is the LTO indexing step, rather than the real link.
   *
   * <p>When using this, build() will store allLTOArtifacts as a side-effect so the next build()
   * call can emit the real link. Do not call addInput() between the two build() calls.
   */
  public CppLinkActionBuilder setLTOIndexing(boolean ltoIndexing) {
    this.isLTOIndexing = ltoIndexing;
    return this;
  }

  /** Sets the C++ runtime library inputs for the action. */
  public CppLinkActionBuilder setRuntimeInputs(
      ArtifactCategory runtimeType, Artifact middleman, NestedSet<Artifact> inputs) {
    Preconditions.checkArgument((middleman == null) == inputs.isEmpty());
    this.runtimeType = runtimeType;
    this.runtimeMiddleman = middleman;
    this.runtimeInputs = inputs;
    return this;
  }

  /** Adds a variables extension to template the toolchain for this link action. */
  public CppLinkActionBuilder addVariablesExtension(VariablesExtension variablesExtension) {
    this.variablesExtensions.add(variablesExtension);
    return this;
  }

  /** Adds variables extensions to template the toolchain for this link action. */
  public CppLinkActionBuilder addVariablesExtensions(List<VariablesExtension> variablesExtensions) {
    for (VariablesExtension variablesExtension : variablesExtensions) {
      addVariablesExtension(variablesExtension);
    }
     return this;
   }
  
  /**
   * Sets the interface output of the link. A non-null argument can only be provided if the link
   * type is {@code DYNAMIC_LIBRARY} and fake is false.
   */
  public CppLinkActionBuilder setInterfaceOutput(Artifact interfaceOutput) {
    this.interfaceOutput = interfaceOutput;
    return this;
  }

  public CppLinkActionBuilder setSymbolCountsOutput(Artifact symbolCounts) {
    this.symbolCounts = symbolCounts;
    return this;
  }

  /**
   * Add additional inputs needed for the linkstamp compilation that is being done as part of the
   * link.
   */
  public CppLinkActionBuilder addCompilationInputs(Iterable<Artifact> inputs) {
    this.compilationInputs.addAll(inputs);
    return this;
  }

  public CppLinkActionBuilder addTransitiveCompilationInputs(NestedSet<Artifact> inputs) {
    this.compilationInputs.addTransitive(inputs);
    return this;
  }

  private void addObjectFile(LinkerInput input) {
    String name = input.getArtifact().getFilename();
    Preconditions.checkArgument(Link.OBJECT_FILETYPES.matches(name), name);
    this.objectFiles.add(input);
  }

  public CppLinkActionBuilder addLTOBitcodeFiles(Iterable<Artifact> files) {
    for (Artifact a : files) {
      ltoBitcodeFiles.add(a);
    }
    return this;
  }

  /**
   * Adds a single object file to the set of inputs.
   */
  public CppLinkActionBuilder addObjectFile(Artifact input) {
    addObjectFile(LinkerInputs.simpleLinkerInput(input, ArtifactCategory.OBJECT_FILE));
    return this;
  }

  /**
   * Adds object files to the linker action.
   */
  public CppLinkActionBuilder addObjectFiles(Iterable<Artifact> inputs) {
    for (Artifact input : inputs) {
      addObjectFile(LinkerInputs.simpleLinkerInput(input, ArtifactCategory.OBJECT_FILE));
    }
    return this;
  }

  /**
   * Adds non-code files to the set of inputs. They will not be passed to the linker command line
   * unless that is explicitly modified, too.
   */
  public CppLinkActionBuilder addNonCodeInputs(Iterable<Artifact> inputs) {
    for (Artifact input : inputs) {
      addNonCodeInput(input);
    }

    return this;
  }

  /**
   * Adds a single non-code file to the set of inputs. It will not be passed to the linker command
   * line unless that is explicitly modified, too.
   */
  public CppLinkActionBuilder addNonCodeInput(Artifact input) {
    String basename = input.getFilename();
    Preconditions.checkArgument(!Link.ARCHIVE_LIBRARY_FILETYPES.matches(basename), basename);
    Preconditions.checkArgument(!Link.SHARED_LIBRARY_FILETYPES.matches(basename), basename);
    Preconditions.checkArgument(!Link.OBJECT_FILETYPES.matches(basename), basename);

    this.nonCodeInputs.add(input);
    return this;
  }

  public CppLinkActionBuilder addFakeObjectFiles(Iterable<Artifact> inputs) {
    for (Artifact input : inputs) {
      addObjectFile(LinkerInputs.fakeLinkerInput(input));
    }
    return this;
  }

  private void checkLibrary(LibraryToLink input) {
    String name = input.getArtifact().getFilename();
    Preconditions.checkArgument(
        Link.ARCHIVE_LIBRARY_FILETYPES.matches(name) || Link.SHARED_LIBRARY_FILETYPES.matches(name),
        "'%s' is not a library file",
        input);
  }

  /**
   * Adds a single artifact to the set of inputs. The artifact must be an archive or a shared
   * library. Note that all directly added libraries are implicitly ordered before all nested sets
   * added with {@link #addLibraries}, even if added in the opposite order.
   */
  public CppLinkActionBuilder addLibrary(LibraryToLink input) {
    checkLibrary(input);
    libraries.add(input);
    return this;
  }

  /**
   * Adds multiple artifact to the set of inputs. The artifacts must be archives or shared
   * libraries.
   */
  public CppLinkActionBuilder addLibraries(NestedSet<LibraryToLink> inputs) {
    for (LibraryToLink input : inputs) {
      checkLibrary(input);
    }
    this.libraries.addTransitive(inputs);
    return this;
  }

  /**
   * Sets the type of ELF file to be created (.a, .so, .lo, executable). The default is {@link
   * LinkTargetType#STATIC_LIBRARY}.
   */
  public CppLinkActionBuilder setLinkType(LinkTargetType linkType) {
    this.linkType = linkType;
    return this;
  }

  /**
   * Sets the degree of "staticness" of the link: fully static (static binding of all symbols),
   * mostly static (use dynamic binding only for symbols from glibc), dynamic (use dynamic binding
   * wherever possible). The default is {@link LinkStaticness#FULLY_STATIC}.
   */
  public CppLinkActionBuilder setLinkStaticness(LinkStaticness linkStaticness) {
    this.linkStaticness = linkStaticness;
    return this;
  }

  /**
   * Sets the identifier of the library produced by the action. See
   * {@link LinkerInputs.LibraryToLink#getLibraryIdentifier()}
   */
  public CppLinkActionBuilder setLibraryIdentifier(String libraryIdentifier) {
    this.libraryIdentifier = libraryIdentifier;
    return this;
  }

  /**
   * Adds a C++ source file which will be compiled at link time. This is used to embed various
   * values from the build system into binaries to identify their provenance.
   *
   * <p>Link stamps are also automatically added to the inputs.
   */
  public CppLinkActionBuilder addLinkstamps(Map<Artifact, NestedSet<Artifact>> linkstamps) {
    this.linkstamps.addAll(linkstamps.keySet());
    // Add inputs for linkstamping.
    if (!linkstamps.isEmpty()) {
      for (Map.Entry<Artifact, NestedSet<Artifact>> entry : linkstamps.entrySet()) {
        addCompilationInputs(entry.getValue());
      }
    }
    return this;
  }

  public CppLinkActionBuilder addLinkstampCompilerOptions(ImmutableList<String> linkstampOptions) {
    this.linkstampOptions = linkstampOptions;
    return this;
  }

  /** Adds an additional linker option. */
  public CppLinkActionBuilder addLinkopt(String linkopt) {
    this.linkopts.add(linkopt);
    return this;
  }

  /**
   * Adds multiple linker options at once.
   *
   * @see #addLinkopt(String)
   */
  public CppLinkActionBuilder addLinkopts(Collection<String> linkopts) {
    this.linkopts.addAll(linkopts);
    return this;
  }

  /**
   * Merges the given link params into this builder by calling {@link #addLinkopts}, {@link
   * #addLibraries}, and {@link #addLinkstamps}.
   */
  public CppLinkActionBuilder addLinkParams(
      CcLinkParams linkParams, RuleErrorConsumer errorListener) throws InterruptedException {
    addLinkopts(linkParams.flattenedLinkopts());
    addLibraries(linkParams.getLibraries());
    ExtraLinkTimeLibraries extraLinkTimeLibraries = linkParams.getExtraLinkTimeLibraries();
    if (extraLinkTimeLibraries != null) {
      for (ExtraLinkTimeLibrary extraLibrary : extraLinkTimeLibraries.getExtraLibraries()) {
        addLibraries(extraLibrary.buildLibraries(ruleContext));
      }
    }
    addLinkstamps(CppHelper.resolveLinkstamps(errorListener, linkParams));
    return this;
  }

  /** Sets whether this link action will be used for a cc_fake_binary; false by default. */
  public CppLinkActionBuilder setFake(boolean fake) {
    this.fake = fake;
    return this;
  }

  /** Sets whether this link action is used for a native dependency library. */
  public CppLinkActionBuilder setNativeDeps(boolean isNativeDeps) {
    this.isNativeDeps = isNativeDeps;
    return this;
  }

  /**
   * Setting this to true overrides the default whole-archive computation and force-enables whole
   * archives for every archive in the link. This is only necessary for linking executable binaries
   * that are supposed to export symbols.
   *
   * <p>Usually, the link action while use whole archives for dynamic libraries that are native deps
   * (or the legacy whole archive flag is enabled), and that are not dynamically linked.
   *
   * <p>(Note that it is possible to build dynamic libraries with cc_binary rules by specifying
   * linkshared = 1, and giving the rule a name that matches the pattern {@code
   * lib&lt;name&gt;.so}.)
   */
  public CppLinkActionBuilder setWholeArchive(boolean wholeArchive) {
    this.wholeArchive = wholeArchive;
    return this;
  }

  /**
   * Sets whether this link action should use test-specific flags (e.g. $EXEC_ORIGIN instead of
   * $ORIGIN for the solib search path or lazy binding); false by default.
   */
  public CppLinkActionBuilder setUseTestOnlyFlags(boolean useTestOnlyFlags) {
    this.useTestOnlyFlags = useTestOnlyFlags;
    return this;
  }

  /**
   * 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;
    return this;
  }
  
  /**
   * Sets extra input artifacts to the link action.
   */
  public CppLinkActionBuilder addActionInputs(Collection<Artifact> inputs) {
    this.linkActionInputs.addAll(inputs);
    return this;
  }

  private static class LinkArgCollector {
    String rpathRoot;
    List<String> rpathEntries;
    Set<String> libopts;
    List<String> linkerInputParams;
    List<String> wholeArchiveLinkerInputParams;
    List<String> noWholeArchiveInputs;

    public void setRpathRoot(String rPathRoot) {
      this.rpathRoot = rPathRoot;
    }

    public void setRpathEntries(List<String> rpathEntries) {
      this.rpathEntries = rpathEntries;
    }

    public void setLibopts(Set<String> libopts) {
      this.libopts = libopts;
    }

    public void setLinkerInputParams(List<String> linkerInputParams) {
      this.linkerInputParams = linkerInputParams;
    }

    public void setWholeArchiveLinkerInputParams(List<String> wholeArchiveInputParams) {
      this.wholeArchiveLinkerInputParams = wholeArchiveInputParams;
    }

    public void setNoWholeArchiveInputs(List<String> noWholeArchiveInputs) {
      this.noWholeArchiveInputs = noWholeArchiveInputs;
    }

    public String getRpathRoot() {
      return rpathRoot;
    }

    public List<String> getRpathEntries() {
      return rpathEntries;
    }

    public Set<String> getLibopts() {
      return libopts;
    }

    public List<String> getLinkerInputParams() {
      return linkerInputParams;
    }

    public List<String> getWholeArchiveLinkerInputParams() {
      return wholeArchiveLinkerInputParams;
    }

    public List<String> getNoWholeArchiveInputs() {
      return noWholeArchiveInputs;
    }
  }

  private class CppLinkVariablesExtension implements VariablesExtension {

    private final BuildConfiguration configuration;
    private final ImmutableMap<Artifact, Artifact> linkstampMap;
    private final boolean needWholeArchive;
    private final Iterable<LinkerInput> linkerInputs;
    private final ImmutableList<LinkerInput> runtimeLinkerInputs;
    private final Artifact outputArtifact;
    private final Artifact linkerParamsFile;
    private final PathFragment ltoOutputRootPrefix;

    private final LinkArgCollector linkArgCollector = new LinkArgCollector();

    public CppLinkVariablesExtension(
        BuildConfiguration configuration,
        ImmutableMap<Artifact, Artifact> linkstampMap,
        boolean needWholeArchive,
        Iterable<LinkerInput> linkerInputs,
        ImmutableList<LinkerInput> runtimeLinkerInputs,
        Artifact output,
        Artifact linkerParamsFile,
        PathFragment ltoOutputRootPrefix) {
      this.configuration = configuration;
      this.linkstampMap = linkstampMap;
      this.needWholeArchive = needWholeArchive;
      this.linkerInputs = linkerInputs;
      this.runtimeLinkerInputs = runtimeLinkerInputs;
      this.outputArtifact = output;
      this.linkerParamsFile = linkerParamsFile;
      this.ltoOutputRootPrefix = ltoOutputRootPrefix;

      addInputFileLinkOptions(linkArgCollector);
    }

    /**
     * Returns linker parameters indicating libraries that should not be linked inside a
     * --whole_archive block.
     *
     * <p>TODO(b/30228443): Refactor into action configs
     */
    public List<String> getNoWholeArchiveInputs() {
      return linkArgCollector.getNoWholeArchiveInputs();
    }

    @Override
    public void addVariables(Variables.Builder buildVariables) {

      // symbol counting
      if (symbolCounts != null) {
        buildVariables.addVariable(SYMBOL_COUNTS_OUTPUT_VARIABLE, symbolCounts.getExecPathString());
      }

      // linkstamp
      ImmutableSet.Builder<String> linkstampPaths = ImmutableSet.<String>builder();
      for (Artifact linkstampOutput : linkstampMap.values()) {
        linkstampPaths.add(linkstampOutput.getExecPathString());
      }

      buildVariables.addSequenceVariable(LINKSTAMP_PATHS_VARIABLE, linkstampPaths.build());

      // pic
      boolean forcePic = cppConfiguration.forcePic();
      if (forcePic) {
        buildVariables.addVariable(FORCE_PIC_VARIABLE, "");
      }

      // rpath
      if (linkArgCollector.getRpathRoot() != null) {
        buildVariables.addVariable(RUNTIME_ROOT_FLAGS_VARIABLE, linkArgCollector.getRpathRoot());
      }

      if (linkArgCollector.getRpathEntries() != null) {
        buildVariables.addSequenceVariable(
            RUNTIME_ROOT_ENTRIES_VARIABLE, linkArgCollector.getRpathEntries());
      }

      buildVariables.addSequenceVariable(LIBOPTS_VARIABLE, linkArgCollector.getLibopts());
      buildVariables.addSequenceVariable(
          LINKER_INPUT_PARAMS_VARIABLE, linkArgCollector.getLinkerInputParams());
      buildVariables.addSequenceVariable(
          WHOLE_ARCHIVE_LINKER_INPUT_PARAMS_VARIABLE,
          linkArgCollector.getWholeArchiveLinkerInputParams());

      // global archive
      if (needWholeArchive) {
        buildVariables.addVariable(GLOBAL_WHOLE_ARCHIVE_VARIABLE, "");
      }

      // mostly static
      if (linkStaticness == LinkStaticness.MOSTLY_STATIC && cppConfiguration.skipStaticOutputs()) {
        buildVariables.addVariable(SKIP_MOSTLY_STATIC_VARIABLE, "");
      }

      // output exec path
      if (this.outputArtifact != null) {
        buildVariables.addVariable(
            OUTPUT_EXECPATH_VARIABLE, this.outputArtifact.getExecPathString());
      }

      if (!ltoOutputRootPrefix.equals(PathFragment.EMPTY_FRAGMENT)) {
        if (linkerParamsFile != null) {
          buildVariables.addVariable(
              "thinlto_optional_params_file", "=" + linkerParamsFile.getExecPathString());
        } else {
          buildVariables.addVariable("thinlto_optional_params_file", "");
        }
        buildVariables.addVariable(
            "thinlto_prefix_replace",
            configuration.getBinDirectory().getExecPathString()
                + ";"
                + configuration.getBinDirectory().getExecPath().getRelative(ltoOutputRootPrefix));
      }

      // Variables arising from the toolchain
      buildVariables
          .addAllVariables(CppHelper.getToolchain(ruleContext).getBuildVariables())
          .build();
      CppHelper.getFdoSupport(ruleContext).getLinkOptions(featureConfiguration, buildVariables);
    }

    private boolean isSharedNativeLibrary() {
      return isNativeDeps && cppConfiguration.shareNativeDeps();
    }

    private boolean inputNeedsWholeArchive(LinkerInput input) {
      if (Link.useStartEndLib(input, cppConfiguration.archiveType())) {
        return false;
      }

      return input.getArtifactCategory() == ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY
           && !wholeArchive && !needWholeArchive;
    }

    /**
     * When linking a shared library fully or mostly static then we need to link in *all* dependent
     * files, not just what the shared library needs for its own code. This is done by wrapping all
     * objects/libraries with -Wl,-whole-archive and -Wl,-no-whole-archive. For this case the
     * globalNeedWholeArchive parameter must be set to true. Otherwise only library objects (.lo)
     * need to be wrapped with -Wl,-whole-archive and -Wl,-no-whole-archive.
     *
     * <p>TODO: Factor out of the bazel binary into build variables for crosstool action_configs.
     */
    private void addInputFileLinkOptions(LinkArgCollector linkArgCollector) {

      // Used to collect -L and -Wl,-rpath options, ensuring that each used only once.
      Set<String> libOpts = new LinkedHashSet<>();

      // List of command line parameters that need to be placed *outside* of
      // --whole-archive ... --no-whole-archive.
      List<String> noWholeArchiveInputs = new ArrayList<>();

      PathFragment solibDir =
          configuration
              .getBinDirectory(ruleContext.getRule().getRepository())
              .getExecPath()
              .getRelative(cppConfiguration.getSolibDirectory());
      String runtimeSolibName = runtimeSolibDir != null ? runtimeSolibDir.getBaseName() : null;
      boolean runtimeRpath =
          runtimeSolibDir != null
              && (linkType == LinkTargetType.DYNAMIC_LIBRARY
                  || (linkType == LinkTargetType.EXECUTABLE
                      && linkStaticness == LinkStaticness.DYNAMIC));

      String rpathRoot = null;
      List<String> runtimeRpathEntries = new ArrayList<>();

      if (output != null) {
        String origin =
            useTestOnlyFlags && cppConfiguration.supportsExecOrigin()
                ? "$EXEC_ORIGIN/"
                : "$ORIGIN/";
        if (runtimeRpath) {
          runtimeRpathEntries.add("-Wl,-rpath," + origin + runtimeSolibName + "/");
        }

        // Calculate the correct relative value for the "-rpath" link option (which sets
        // the search path for finding shared libraries).
        if (isSharedNativeLibrary()) {
          // 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
          // them.
          //
          // Note that we have to do this because $ORIGIN points to different paths for
          // different targets. In other words, blaze-bin/d1/d2/d3/a_shareddeps.so and
          // blaze-bin/d4/b_shareddeps.so have different path depths. The first could
          // reference a standard blaze-bin/_solib_[arch] via $ORIGIN/../../../_solib[arch],
          // and the second could use $ORIGIN/../_solib_[arch]. But since this is a shared
          // artifact, both are symlinks to the same place, so
          // there's no *one* RPATH setting that fits all targets involved in the sharing.
          rpathRoot =
              "-Wl,-rpath," + origin + ":" + origin + cppConfiguration.getSolibDirectory() + "/";
          if (runtimeRpath) {
            runtimeRpathEntries.add("-Wl,-rpath," + origin + "../" + runtimeSolibName + "/");
          }
        } 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) {
            runtimeRpathEntries.add(
                "-Wl,-rpath,"
                    + origin
                    + Strings.repeat("../", output.getRootRelativePath().segmentCount() - 1)
                    + runtimeSolibName
                    + "/");
          }

          rpathRoot =
              "-Wl,-rpath,"
                  + origin
                  + Strings.repeat("../", output.getRootRelativePath().segmentCount() - 1)
                  + cppConfiguration.getSolibDirectory()
                  + "/";

          if (isNativeDeps) {
            // We also retain the $ORIGIN/ path to solibs that are in _solib_<arch>, as opposed to
            // the package directory)
            if (runtimeRpath) {
              runtimeRpathEntries.add("-Wl,-rpath," + origin + "../" + runtimeSolibName + "/");
            }
            rpathRoot += ":" + origin;
          }
        }
      }

      boolean includeSolibDir = false;

      Map<Artifact, Artifact> ltoMap = null;
      if (!isLTOIndexing && (allLTOArtifacts != null)) {
        // TODO(bazel-team): The LTO final link can only work if there are individual .o files on
        // the command line. Rather than crashing, this should issue a nice error. We will get
        // this by
        // 1) moving supports_start_end_lib to a toolchain feature
        // 2) having thin_lto require start_end_lib
        // As a bonus, we can rephrase --nostart_end_lib as --features=-start_end_lib and get rid
        // of a command line option.

        Preconditions.checkState(cppConfiguration.useStartEndLib());
        ltoMap = new HashMap<>();
        for (LTOBackendArtifacts l : allLTOArtifacts) {
          ltoMap.put(l.getBitcodeFile(), l.getObjectFile());
        }
      }

      List<String> wholeArchiveInputParams = new ArrayList<>();
      List<String> standardArchiveInputParams = new ArrayList<>();

      for (LinkerInput input : linkerInputs) {
        if (input.getArtifactCategory() == ArtifactCategory.DYNAMIC_LIBRARY) {
          PathFragment libDir = input.getArtifact().getExecPath().getParentDirectory();
          Preconditions.checkState(
              libDir.startsWith(solibDir),
              "Artifact '%s' is not under directory '%s'.",
              input.getArtifact(),
              solibDir);
          if (libDir.equals(solibDir)) {
            includeSolibDir = true;
          }
          addDynamicInputLinkOptions(
              input, standardArchiveInputParams, libOpts, solibDir, rpathRoot);
        } else {
          addStaticInputLinkOptions(
              input, wholeArchiveInputParams, standardArchiveInputParams, ltoMap);
        }
      }

      boolean includeRuntimeSolibDir = false;

      for (LinkerInput input : runtimeLinkerInputs) {
        List<String> optionsList = needWholeArchive
            ? noWholeArchiveInputs : standardArchiveInputParams;

        if (input.getArtifactCategory() == ArtifactCategory.DYNAMIC_LIBRARY) {
          PathFragment libDir = input.getArtifact().getExecPath().getParentDirectory();
          Preconditions.checkState(
              runtimeSolibDir != null && libDir.equals(runtimeSolibDir),
              "Artifact '%s' is not under directory '%s'.",
              input.getArtifact(),
              solibDir);
          includeRuntimeSolibDir = true;
          addDynamicInputLinkOptions(input, optionsList, libOpts, solibDir, rpathRoot);
        } else {
          addStaticInputLinkOptions(input,
              needWholeArchive ? noWholeArchiveInputs : wholeArchiveInputParams,
              needWholeArchive ? noWholeArchiveInputs : standardArchiveInputParams,
              ltoMap);
        }
      }
      if (linkerParamsFile != null && ltoOutputRootPrefix.equals(PathFragment.EMPTY_FRAGMENT)) {
        standardArchiveInputParams.add("-Wl,@" + linkerParamsFile.getExecPathString());
      }

      // rpath ordering matters for performance; first add the one where most libraries are found.
      if (includeSolibDir && rpathRoot != null) {
        linkArgCollector.setRpathRoot(rpathRoot);
      }
      if (includeRuntimeSolibDir) {
        linkArgCollector.setRpathEntries(runtimeRpathEntries);
      }

      linkArgCollector.setLibopts(libOpts);

      linkArgCollector.setLinkerInputParams(standardArchiveInputParams);
      linkArgCollector.setWholeArchiveLinkerInputParams(wholeArchiveInputParams);
      linkArgCollector.setNoWholeArchiveInputs(noWholeArchiveInputs);

      if (ltoMap != null) {
        Preconditions.checkState(ltoMap.isEmpty(), "Still have LTO objects left: %s", ltoMap);
      }
    }

    /** Adds command-line options for a dynamic library input file into options and libOpts. */
    private void addDynamicInputLinkOptions(
        LinkerInput input,
        List<String> options,
        Set<String> libOpts,
        PathFragment solibDir,
        String rpathRoot) {
      Preconditions.checkState(input.getArtifactCategory() == ArtifactCategory.DYNAMIC_LIBRARY);
      Preconditions.checkState(!Link.useStartEndLib(input, cppConfiguration.archiveType()));

      Artifact inputArtifact = input.getArtifact();
      PathFragment libDir = inputArtifact.getExecPath().getParentDirectory();
      if (rpathRoot != null
          && !libDir.equals(solibDir)
          && (runtimeSolibDir == null || !runtimeSolibDir.equals(libDir))) {
        String dotdots = "";
        PathFragment commonParent = solibDir;
        while (!libDir.startsWith(commonParent)) {
          dotdots += "../";
          commonParent = commonParent.getParentDirectory();
        }

        libOpts.add(rpathRoot + dotdots + libDir.relativeTo(commonParent).getPathString());
      }

      libOpts.add("-L" + inputArtifact.getExecPath().getParentDirectory().getPathString());

      String name = inputArtifact.getFilename();
      if (CppFileTypes.SHARED_LIBRARY.matches(name)) {
        String libName = name.replaceAll("(^lib|\\.(so|dylib)$)", "");
        options.add("-l" + libName);
      } else {
        // Interface shared objects have a non-standard extension
        // that the linker won't be able to find.  So use the
        // filename directly rather than a -l option.  Since the
        // library has an SONAME attribute, this will work fine.
        options.add(inputArtifact.getExecPathString());
      }
    }

    /**
     * Adds command-line options for a static library or non-library input into options.
     *
     * @param ltoMap is a mutable list of exec paths that should be on the command-line, which must
     *     be supplied for LTO final links.
     */
    private void addStaticInputLinkOptions(
        LinkerInput input, List<String> wholeArchiveOptions, List<String> standardOptions,
        @Nullable Map<Artifact, Artifact> ltoMap) {
      Preconditions.checkState(!(input.getArtifactCategory() == ArtifactCategory.DYNAMIC_LIBRARY));
      // If we had any LTO artifacts, ltoMap whould be non-null. In that case,
      // we should have created a linkerParamsFile which the LTO indexing
      // step will populate with the exec paths that correspond to the LTO
      // artifacts that the linker decided to include based on symbol resolution.
      // Those files will be included directly in the link (and not wrapped
      // in --start-lib/--end-lib) to ensure consistency between the two link
      // steps.
      Preconditions.checkState(ltoMap == null || linkerParamsFile != null);

      // start-lib/end-lib library: adds its input object files.
      if (Link.useStartEndLib(input, cppConfiguration.archiveType())) {
        Iterable<Artifact> archiveMembers = input.getObjectFiles();
        if (!Iterables.isEmpty(archiveMembers)) {
          List<String> nonLTOArchiveMembers = new ArrayList<>();
          for (Artifact member : archiveMembers) {
            if (ltoMap != null && ltoMap.remove(member) != null) {
              // The LTO artifacts that should be included in the final link
              // are listed in the linkerParamsFile. When ltoMap is non-null
              // the backend artifact may be missing due to libraries that list .o
              // files explicitly, or generate .o files from assembler.
              continue;
            }
            nonLTOArchiveMembers.add(member.getExecPathString());
          }
          if (!nonLTOArchiveMembers.isEmpty()) {
            standardOptions.add("-Wl,--start-lib");
            standardOptions.addAll(nonLTOArchiveMembers);
            standardOptions.add("-Wl,--end-lib");
          }
        }
      } else {
        List<String> options = inputNeedsWholeArchive(input)
            ? wholeArchiveOptions : standardOptions;
        // For anything else, add the input directly.
        Artifact inputArtifact = input.getArtifact();

        if (ltoMap != null && ltoMap.remove(inputArtifact) != null) {
          // The LTO artifacts that should be included in the final link
          // are listed in the linkerParamsFile.
          return;
        }

        if (input.isFake()) {
          options.add(Link.FAKE_OBJECT_PREFIX + inputArtifact.getExecPathString());
        } else {
          options.add(inputArtifact.getExecPathString());
        }
      }
    }
  }
}
