// Copyright 2014 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 com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.ActionRegistry;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.FailAction;
import com.google.devtools.build.lib.analysis.FileProvider;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.actions.ActionConstructionContext;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.analysis.skylark.SymbolGenerator;
import com.google.devtools.build.lib.cmdline.Label;
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.RuleClass.ConfiguredTargetFactory.RuleErrorException;
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.CcToolchainVariables.VariablesExtension;
import com.google.devtools.build.lib.rules.cpp.CppLinkAction.LinkArtifactFactory;
import com.google.devtools.build.lib.rules.cpp.LibraryToLink.CcLinkingContext;
import com.google.devtools.build.lib.rules.cpp.LibraryToLink.CcLinkingContext.Linkstamp;
import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType;
import com.google.devtools.build.lib.rules.cpp.Link.LinkerOrArchiver;
import com.google.devtools.build.lib.rules.cpp.Link.LinkingMode;
import com.google.devtools.build.lib.rules.cpp.Link.Picness;
import com.google.devtools.build.lib.skylarkbuildapi.cpp.LinkingInfoApi;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;

/**
 * A class to create C/C++ link actions in a way that is consistent with cc_library. Rules that
 * generate source files and emulate cc_library on top of that should use this class instead of the
 * lower-level APIs in CppHelper and CppLinkActionBuilder.
 *
 * <p>Rules that want to use this class are required to have implicit dependencies on the toolchain,
 * the STL, and so on. Optionally, they can also have copts, and malloc attributes, but note that
 * these require explicit calls to the corresponding setter methods.
 */
public final class CcLinkingHelper {

  /** Contains the providers as well as the linking outputs. */
  // TODO(plf): Only used by Skylark API. Remove after migrating.
  @Deprecated
  public static final class LinkingInfo implements LinkingInfoApi {
    private final CcLinkingContext ccLinkingContext;
    private final CcLinkingOutputs linkingOutputs;

    public LinkingInfo(CcLinkingContext ccLinkingContext, CcLinkingOutputs linkingOutputs) {
      this.ccLinkingContext = ccLinkingContext;
      this.linkingOutputs = linkingOutputs;
    }

    @Override
    public CcLinkingContext getCcLinkingContext() {
      return ccLinkingContext;
    }

    @Override
    public CcLinkingOutputs getCcLinkingOutputs() {
      return linkingOutputs;
    }
  }

  private final CppSemantics semantics;
  private final BuildConfiguration configuration;
  private final CppConfiguration cppConfiguration;

  private final List<Artifact> nonCodeLinkerInputs = new ArrayList<>();
  private final List<String> linkopts = new ArrayList<>();
  private final List<CcLinkingContext> ccLinkingContexts = new ArrayList<>();
  private final NestedSetBuilder<Artifact> linkstamps = NestedSetBuilder.stableOrder();
  private final List<Artifact> linkActionInputs = new ArrayList<>();

  @Nullable private Artifact linkerOutputArtifact;
  private LinkTargetType staticLinkType = LinkTargetType.STATIC_LIBRARY;
  private LinkTargetType dynamicLinkType = LinkTargetType.NODEPS_DYNAMIC_LIBRARY;
  private boolean neverlink;

  private boolean emitInterfaceSharedLibraries;
  private boolean shouldCreateDynamicLibrary = true;
  private boolean shouldCreateStaticLibraries = true;
  private boolean willOnlyBeLinkedIntoDynamicLibraries;
  private final List<VariablesExtension> variablesExtensions = new ArrayList<>();
  private boolean useTestOnlyFlags;
  private Artifact pdbFile;
  private Artifact defFile;
  private LinkingMode linkingMode = LinkingMode.DYNAMIC;
  private boolean fake;
  private boolean nativeDeps;
  private boolean wholeArchive;
  private LinkArtifactFactory linkArtifactFactory = CppLinkAction.DEFAULT_ARTIFACT_FACTORY;
  private final ImmutableList.Builder<String> additionalLinkstampDefines = ImmutableList.builder();

  private final FeatureConfiguration featureConfiguration;
  private final CcToolchainProvider ccToolchain;
  private final FdoContext fdoContext;
  private String linkedArtifactNameSuffix = "";

  private final ActionConstructionContext actionConstructionContext;
  private final Label label;
  private final ActionRegistry actionRegistry;
  private final RuleErrorConsumer ruleErrorConsumer;
  private final SymbolGenerator<?> symbolGenerator;

  private Artifact grepIncludes;
  private boolean isStampingEnabled;
  private boolean isTestOrTestOnlyTarget;

  /**
   * Creates a CcLinkingHelper that outputs artifacts in a given configuration.
   *
   * @param ruleErrorConsumer the RuleErrorConsumer
   * @param label the Label of the rule being built
   * @param actionRegistry the ActionRegistry of the rule being built
   * @param actionConstructionContext the ActionConstructionContext of the rule being built
   * @param semantics CppSemantics for the build
   * @param featureConfiguration activated features and action configs for the build
   * @param ccToolchain the C++ toolchain provider for the build
   * @param fdoContext the C++ FDO optimization support provider for the build
   * @param configuration the configuration that gives the directory of output artifacts
   */
  public CcLinkingHelper(
      RuleErrorConsumer ruleErrorConsumer,
      Label label,
      ActionRegistry actionRegistry,
      ActionConstructionContext actionConstructionContext,
      CppSemantics semantics,
      FeatureConfiguration featureConfiguration,
      CcToolchainProvider ccToolchain,
      FdoContext fdoContext,
      BuildConfiguration configuration,
      CppConfiguration cppConfiguration,
      SymbolGenerator<?> symbolGenerator) {
    this.semantics = Preconditions.checkNotNull(semantics);
    this.featureConfiguration = Preconditions.checkNotNull(featureConfiguration);
    this.ccToolchain = Preconditions.checkNotNull(ccToolchain);
    this.fdoContext = Preconditions.checkNotNull(fdoContext);
    this.configuration = Preconditions.checkNotNull(configuration);
    this.cppConfiguration = cppConfiguration;
    this.ruleErrorConsumer = ruleErrorConsumer;
    this.label = label;
    this.actionRegistry = actionRegistry;
    this.actionConstructionContext = actionConstructionContext;
    this.symbolGenerator = symbolGenerator;
  }

  /** Sets fields that overlap for cc_library and cc_binary rules. */
  public CcLinkingHelper fromCommon(RuleContext ruleContext, CcCommon common) {
    addCcLinkingContexts(
        CppHelper.getLinkingContextsFromDeps(
            ImmutableList.copyOf(ruleContext.getPrerequisites("deps", Mode.TARGET))));
    addNonCodeLinkerInputs(common.getLinkerScripts());
    return this;
  }

  public CcLinkingHelper setNativeDeps(boolean nativeDeps) {
    this.nativeDeps = nativeDeps;
    return this;
  }

  public CcLinkingHelper setWholeArchive(boolean wholeArchive) {
    this.wholeArchive = wholeArchive;
    return this;
  }

  public CcLinkingHelper addAdditionalLinkstampDefines(List<String> additionalLinkstampDefines) {
    this.additionalLinkstampDefines.addAll(additionalLinkstampDefines);
    return this;
  }

  /** Adds the corresponding non-code files as linker inputs. */
  public CcLinkingHelper addNonCodeLinkerInputs(Iterable<Artifact> nonCodeLinkerInputs) {
    for (Artifact nonCodeLinkerInput : nonCodeLinkerInputs) {
      String basename = nonCodeLinkerInput.getFilename();
      Preconditions.checkArgument(!Link.OBJECT_FILETYPES.matches(basename));
      Preconditions.checkArgument(!Link.ARCHIVE_LIBRARY_FILETYPES.matches(basename));
      Preconditions.checkArgument(!Link.SHARED_LIBRARY_FILETYPES.matches(basename));
      this.nonCodeLinkerInputs.add(nonCodeLinkerInput);
    }
    return this;
  }

  /** Adds the given options as linker options to the link command. */
  public CcLinkingHelper addLinkopts(Iterable<String> linkopts) {
    Iterables.addAll(this.linkopts, linkopts);
    return this;
  }

  /**
   * Adds additional {@link CcLinkingContext} that will be used everywhere where CcLinkingInfos were
   * obtained from deps.
   */
  public CcLinkingHelper addCcLinkingContexts(Iterable<CcLinkingContext> ccLinkingContexts) {
    Iterables.addAll(this.ccLinkingContexts, ccLinkingContexts);
    return this;
  }

  /**
   * Adds the given linkstamps. Note that linkstamps are usually not compiled at the library level,
   * but only in the dependent binary rules.
   */
  public CcLinkingHelper addLinkstamps(Iterable<? extends TransitiveInfoCollection> linkstamps) {
    for (TransitiveInfoCollection linkstamp : linkstamps) {
      this.linkstamps.addTransitive(linkstamp.getProvider(FileProvider.class).getFilesToBuild());
    }
    return this;
  }

  /** Adds the given artifact to the input of any generated link actions. */
  public CcLinkingHelper addLinkActionInput(Artifact input) {
    Preconditions.checkNotNull(input);
    this.linkActionInputs.add(input);
    return this;
  }

  /** Adds a variableExtension to template the crosstool. */
  public CcLinkingHelper addVariableExtension(VariablesExtension variableExtension) {
    Preconditions.checkNotNull(variableExtension);
    this.variablesExtensions.add(variableExtension);
    return this;
  }

  /**
   * Overrides the path for the generated dynamic library - this should only be called if the
   * dynamic library is an implicit or explicit output of the rule, i.e., if it is accessible by
   * name from other rules in the same package. Set to {@code null} to use the default computation.
   */
  public CcLinkingHelper setLinkerOutputArtifact(@Nullable Artifact linkerOutputArtifact) {
    this.linkerOutputArtifact = linkerOutputArtifact;
    return this;
  }

  /**
   * Marks the output of this rule as alwayslink, i.e., the corresponding symbols will be retained
   * by the linker even if they are not otherwise used. This is useful for libraries that register
   * themselves somewhere during initialization.
   *
   * <p>This only sets the link type (see {@link #setStaticLinkType}), either to a static library or
   * to an alwayslink static library (blaze uses a different file extension to signal alwayslink to
   * downstream code).
   */
  public CcLinkingHelper setAlwayslink(boolean alwayslink) {
    staticLinkType =
        alwayslink ? LinkTargetType.ALWAYS_LINK_STATIC_LIBRARY : LinkTargetType.STATIC_LIBRARY;
    return this;
  }

  /**
   * Directly set the link type. This can be used instead of {@link #setAlwayslink}. Setting
   * anything other than a static link causes this class to skip the link action creation. This
   * exists only for Objective-C.
   */
  @Deprecated
  public CcLinkingHelper setStaticLinkType(LinkTargetType linkType) {
    Preconditions.checkNotNull(linkType);
    Preconditions.checkState(linkType.linkerOrArchiver() == LinkerOrArchiver.ARCHIVER);
    this.staticLinkType = linkType;
    return this;
  }

  /**
   * Marks the resulting code as neverlink, i.e., the code will not be linked into dependent
   * libraries or binaries - the header files are still available.
   */
  public CcLinkingHelper setNeverLink(boolean neverlink) {
    this.neverlink = neverlink;
    return this;
  }

  /*
   * Adds a suffix for paths of linked artifacts. Normally their paths are derived solely from rule
   * labels. In the case of multiple callers (e.g., aspects) acting on a single rule, they may
   * generate the same linked artifact and therefore lead to artifact conflicts. This method
   * provides a way to avoid this artifact conflict by allowing different callers acting on the same
   * rule to provide a suffix that will be used to scope their own linked artifacts.
   */
  public CcLinkingHelper setLinkedArtifactNameSuffix(String suffix) {
    this.linkedArtifactNameSuffix = Preconditions.checkNotNull(suffix);
    return this;
  }

  /**
   * Enables the optional generation of interface dynamic libraries - this is only used when the
   * linker generates a dynamic library, and only if the crosstool supports it. The default is not
   * to generate interface dynamic libraries.
   */
  public CcLinkingHelper emitInterfaceSharedLibraries(boolean emitInterfaceSharedLibraries) {
    this.emitInterfaceSharedLibraries = emitInterfaceSharedLibraries;
    return this;
  }

  /**
   * This enables or disables the generation of a dynamic library link action. The default is to
   * generate a dynamic library. Note that the selection between dynamic or static linking is
   * performed at the binary rule level.
   */
  public CcLinkingHelper setShouldCreateDynamicLibrary(boolean emitDynamicLibrary) {
    this.shouldCreateDynamicLibrary = emitDynamicLibrary;
    return this;
  }

  /**
   * When shouldCreateStaticLibraries is true, there are no actions created for static libraries.
   */
  public CcLinkingHelper setShouldCreateStaticLibraries(boolean emitStaticLibraries) {
    this.shouldCreateStaticLibraries = emitStaticLibraries;
    return this;
  }

  /**
   * Create the C++ link actions, and the corresponding linking related providers.
   *
   * @throws RuleErrorException
   */
  public CcLinkingOutputs link(CcCompilationOutputs ccOutputs)
      throws RuleErrorException, InterruptedException {
    Preconditions.checkNotNull(ccOutputs);

    // Create link actions (only if there are object files or if explicitly requested).
    CcLinkingOutputs ccLinkingOutputs = CcLinkingOutputs.EMPTY;
    // On some systems, the linker gives an error message if there are no input files. Even with
    // the check above, this can still happen if there is a .nopic.o or .o files in srcs, but no
    // other files. To fix that, we'd have to check for each link action individually.
    //
    // An additional pre-existing issue is that the header check tokens are dropped if we don't
    // generate any link actions, effectively disabling header checking in some cases.
    if (staticLinkType.linkerOrArchiver() == LinkerOrArchiver.ARCHIVER) {
      // TODO(bazel-team): This can't create the link action for a cc_binary yet.
      ccLinkingOutputs = createCcLinkActions(ccOutputs);
    }
    return ccLinkingOutputs;
  }

  public CcLinkingContext buildCcLinkingContextFromLibrariesToLink(
      ImmutableCollection<LibraryToLink> libraryToLinks,
      CcCompilationContext ccCompilationContext) {
    NestedSetBuilder<Linkstamp> linkstampBuilder = NestedSetBuilder.stableOrder();
    for (Artifact linkstamp : linkstamps.build()) {
      linkstampBuilder.add(
          new Linkstamp(
              linkstamp,
              ccCompilationContext.getDeclaredIncludeSrcs(),
              actionConstructionContext.getActionKeyContext()));
    }
    CcLinkingContext ccLinkingContext = CcLinkingContext.EMPTY;
    if (!neverlink) {
      // We want an empty set if there are no link options. We have to make sure we don't
      // create a LinkOptions instance that contains an empty list.
      ccLinkingContext =
          CcLinkingContext.builder()
              .addUserLinkFlags(
                  linkopts.isEmpty()
                      ? NestedSetBuilder.emptySet(Order.LINK_ORDER)
                      : NestedSetBuilder.create(
                          Order.LINK_ORDER,
                          CcLinkingContext.LinkOptions.of(linkopts, symbolGenerator)))
              .addLibraries(
                  NestedSetBuilder.<LibraryToLink>linkOrder().addAll(libraryToLinks).build())
              .addNonCodeInputs(
                  NestedSetBuilder.<Artifact>linkOrder().addAll(nonCodeLinkerInputs).build())
              .addLinkstamps(linkstampBuilder.build())
              .build();
    }
    ImmutableList.Builder<CcLinkingContext> mergedCcLinkingContexts = ImmutableList.builder();
    mergedCcLinkingContexts.add(ccLinkingContext);
    mergedCcLinkingContexts.addAll(ccLinkingContexts);
    return CcLinkingContext.merge(mergedCcLinkingContexts.build());
  }

  /**
   * Constructs the C++ linker actions. It generally generates two actions, one for a static library
   * and one for a dynamic library. If PIC is required for shared libraries, but not for binaries,
   * it additionally creates a third action to generate a PIC static library. If PIC is required for
   * shared libraries and binaries, then only PIC actions are registered.
   *
   * <p>For dynamic libraries, this method can additionally create an interface shared library that
   * can be used for linking, but doesn't contain any executable code. This increases the number of
   * cache hits for link actions. Call {@link #emitInterfaceSharedLibraries(boolean)} to enable this
   * behavior.
   *
   * @throws RuleErrorException
   */
  private CcLinkingOutputs createCcLinkActions(CcCompilationOutputs ccOutputs)
      throws RuleErrorException, InterruptedException {
    // For now only handle static links. Note that the dynamic library link below ignores
    // staticLinkType.
    // TODO(bazel-team): Either support non-static links or move this check to setStaticLinkType().
    Preconditions.checkState(
        staticLinkType.linkerOrArchiver() == LinkerOrArchiver.ARCHIVER,
        "can only handle static links");

    LibraryToLink.Builder libraryToLinkBuilder = LibraryToLink.builder();
    boolean usePicForBinaries =
        CppHelper.usePicForBinaries(ccToolchain, cppConfiguration, featureConfiguration);
    boolean usePicForDynamicLibs =
        ccToolchain.usePicForDynamicLibraries(cppConfiguration, featureConfiguration);

    PathFragment labelName = PathFragment.create(label.getName());
    String libraryIdentifier =
        actionConstructionContext
            .getPackageDirectory()
            .getRelative(labelName.replaceName("lib" + labelName.getBaseName()))
            .getPathString();

    if (shouldCreateStaticLibraries) {
      createNoPicAndPicStaticLibraries(
          libraryToLinkBuilder,
          usePicForBinaries,
          usePicForDynamicLibs,
          libraryIdentifier,
          ccOutputs);
    }

    boolean hasBuiltDynamicLibrary = false;
    CcLinkingOutputs.Builder ccLinkingOutputsBuilder = CcLinkingOutputs.builder();
    if (shouldCreateDynamicLibrary) {
      boolean usePic =
          (!dynamicLinkType.isExecutable() && usePicForDynamicLibs)
              || (dynamicLinkType.isExecutable() && usePicForBinaries);
      hasBuiltDynamicLibrary =
          createDynamicLibrary(
              ccLinkingOutputsBuilder,
              libraryToLinkBuilder,
              usePic,
              libraryIdentifier,
              ccOutputs);
    }

    if (hasBuiltDynamicLibrary || shouldCreateStaticLibraries) {
      ccLinkingOutputsBuilder.setLibraryToLink(libraryToLinkBuilder.build());
    }

    return ccLinkingOutputsBuilder.build();
  }

  public CcLinkingHelper setWillOnlyBeLinkedIntoDynamicLibraries(
      boolean willOnlyBeLinkedIntoDynamicLibraries) {
    this.willOnlyBeLinkedIntoDynamicLibraries = willOnlyBeLinkedIntoDynamicLibraries;
    return this;
  }

  public CcLinkingHelper setUseTestOnlyFlags(boolean useTestOnlyFlags) {
    this.useTestOnlyFlags = useTestOnlyFlags;
    return this;
  }

  /** Used to set the runfiles path for test rules' dynamic libraries. */
  public CcLinkingHelper setTestOrTestOnlyTarget(boolean isTestOrTestOnlyTarget) {
    this.isTestOrTestOnlyTarget = isTestOrTestOnlyTarget;
    return this;
  }

  /**
   * Used to test the grep-includes tool. This is needing during linking because of linkstamping.
   */
  public CcLinkingHelper setGrepIncludes(Artifact grepIncludes) {
    this.grepIncludes = grepIncludes;
    return this;
  }

  /** Whether linkstamping is enabled. */
  public CcLinkingHelper setIsStampingEnabled(boolean isStampingEnabled) {
    this.isStampingEnabled = isStampingEnabled;
    return this;
  }

  public CcLinkingHelper setLinkingMode(LinkingMode linkingMode) {
    this.linkingMode = linkingMode;
    return this;
  }

  public CcLinkingHelper setDynamicLinkType(LinkTargetType dynamicLinkType) {
    this.dynamicLinkType = dynamicLinkType;
    return this;
  }

  public CcLinkingHelper setFake(boolean fake) {
    this.fake = fake;
    return this;
  }

  public CcLinkingHelper setPdbFile(Artifact pdbFile) {
    this.pdbFile = pdbFile;
    return this;
  }

  public CcLinkingHelper setDefFile(Artifact defFile) {
    this.defFile = defFile;
    return this;
  }

  /** Needed for NativeDepsHelper. It is unclear whether native deps will be in the Starlark API. */
  @Deprecated
  public CcLinkingHelper setLinkArtifactFactory(LinkArtifactFactory linkArtifactFactory) {
    this.linkArtifactFactory = linkArtifactFactory;
    return this;
  }

  private void createNoPicAndPicStaticLibraries(
      LibraryToLink.Builder libraryToLinkBuilder,
      boolean usePicForBinaries,
      boolean usePicForDynamicLibs,
      String libraryIdentifier,
      CcCompilationOutputs ccOutputs)
      throws RuleErrorException, InterruptedException {
    // Create static library (.a). The staticLinkType only reflects whether the library is
    // alwayslink or not. The PIC-ness is determined by whether we need to use PIC or not. There
    // are four cases:
    // for (usePicForDynamicLibs usePicForBinaries):
    //
    // (1) (false false) -> no pic code is when toolchain and cppOptions don't need pic code for
    //  dynamic libraries or binaries
    // (2) (true false)  -> shared libraries as pic, but not binaries
    // (3) (true true)   -> both shared libraries and binaries as pic
    // (4) (false true) -> only pic files generated when toolchain needs pic for shared libraries
    //  and {@link #willOnlyBeLinkedIntoDynamicLibraries} is set to true.

    // In case (3), we always need PIC, so only create one static library containing the PIC
    // object files. The name therefore does not match the content.
    //
    // Presumably, it is done this way because the .a file is an implicit output of every
    // cc_library rule, so we can't use ".pic.a" that in the always-PIC case.

    // If the crosstool is configured to select an output artifact, we use that selection.
    // Otherwise, we use linux defaults.
    boolean createNoPicAction;
    boolean createPicAction;
    if (willOnlyBeLinkedIntoDynamicLibraries) {
      createNoPicAction = !usePicForDynamicLibs;
      createPicAction = usePicForDynamicLibs;
    } else {
      createNoPicAction = !usePicForBinaries;
      createPicAction = usePicForBinaries || usePicForDynamicLibs;
    }

    if (createNoPicAction) {
      LinkerInputs.LibraryToLink staticLibrary =
          registerActionForStaticLibrary(
                  staticLinkType, ccOutputs, /* usePic= */ false, libraryIdentifier)
              .getOutputLibrary();
      libraryToLinkBuilder
          .setLibraryIdentifier(staticLibrary.getLibraryIdentifier())
          .setStaticLibrary(staticLibrary.getArtifact())
          .setObjectFiles(ImmutableList.copyOf(staticLibrary.getObjectFiles()))
          .setLtoCompilationContext(staticLibrary.getLtoCompilationContext())
          .setSharedNonLtoBackends(staticLibrary.getSharedNonLtoBackends())
          .setAlwayslink(
              staticLibrary.getArtifactCategory() == ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY);
    }

    if (createPicAction) {
      LinkTargetType linkTargetTypeUsedForNaming;
      if (!createNoPicAction) {
        // Only PIC library created, name does not match content.
        linkTargetTypeUsedForNaming = staticLinkType;
      } else {
        linkTargetTypeUsedForNaming =
            (staticLinkType == LinkTargetType.ALWAYS_LINK_STATIC_LIBRARY)
                ? LinkTargetType.ALWAYS_LINK_PIC_STATIC_LIBRARY
                : LinkTargetType.PIC_STATIC_LIBRARY;
      }
      LinkerInputs.LibraryToLink picStaticLibrary =
          registerActionForStaticLibrary(
                  linkTargetTypeUsedForNaming, ccOutputs, /* usePic= */ true, libraryIdentifier)
              .getOutputLibrary();
      libraryToLinkBuilder
          .setLibraryIdentifier(picStaticLibrary.getLibraryIdentifier())
          .setPicStaticLibrary(picStaticLibrary.getArtifact())
          .setPicObjectFiles(ImmutableList.copyOf(picStaticLibrary.getObjectFiles()))
          .setPicLtoCompilationContext(picStaticLibrary.getLtoCompilationContext())
          .setPicSharedNonLtoBackends(picStaticLibrary.getSharedNonLtoBackends())
          .setAlwayslink(
              picStaticLibrary.getArtifactCategory() == ArtifactCategory.ALWAYSLINK_STATIC_LIBRARY);
    }
  }

  private CppLinkAction registerActionForStaticLibrary(
      LinkTargetType linkTargetTypeUsedForNaming,
      CcCompilationOutputs ccOutputs,
      boolean usePic,
      String libraryIdentifier)
      throws RuleErrorException, InterruptedException {
    Artifact linkedArtifact = getLinkedArtifact(linkTargetTypeUsedForNaming);
    CppLinkAction action =
        newLinkActionBuilder(linkedArtifact)
            .addObjectFiles(ccOutputs.getObjectFiles(usePic))
            .addNonCodeInputs(nonCodeLinkerInputs)
            .addLtoCompilationContext(ccOutputs.getLtoCompilationContext())
            .setUsePicForLtoBackendActions(usePic)
            .setLinkType(linkTargetTypeUsedForNaming)
            .setLinkingMode(LinkingMode.STATIC)
            .addActionInputs(linkActionInputs)
            .setLibraryIdentifier(libraryIdentifier)
            .addVariablesExtensions(variablesExtensions)
            .build();
    actionConstructionContext.registerAction(action);
    return action;
  }

  private boolean createDynamicLibrary(
      CcLinkingOutputs.Builder ccLinkingOutputs,
      LibraryToLink.Builder libraryToLinkBuilder,
      boolean usePic,
      String libraryIdentifier,
      CcCompilationOutputs ccOutputs)
      throws RuleErrorException, InterruptedException {
    boolean hasBuiltDynamicLibrary = false;
    // Create dynamic library.
    Artifact soImpl;
    String mainLibraryIdentifier;
    if (linkerOutputArtifact == null) {
      // If the crosstool is configured to select an output artifact, we use that selection.
      // Otherwise, we use linux defaults.
      soImpl = getLinkedArtifact(LinkTargetType.NODEPS_DYNAMIC_LIBRARY);
      mainLibraryIdentifier = libraryIdentifier;
    } else {
      // This branch is only used for vestigial Google-internal rules where the name of the output
      // file is explicitly specified in the BUILD file and as such, is platform-dependent. Thus,
      // we just hardcode some reasonable logic to compute the library identifier and hope that this
      // will eventually go away.
      soImpl = linkerOutputArtifact;
      mainLibraryIdentifier =
          FileSystemUtils.removeExtension(soImpl.getRootRelativePath().getPathString());
    }

    List<String> sonameLinkopts = ImmutableList.of();
    Artifact soInterface = null;
    if (CppHelper.useInterfaceSharedLibraries(cppConfiguration, ccToolchain, featureConfiguration)
        && emitInterfaceSharedLibraries) {
      soInterface = getLinkedArtifact(LinkTargetType.INTERFACE_DYNAMIC_LIBRARY);
      // TODO(b/28946988): Remove this hard-coded flag.
      if (!featureConfiguration.isEnabled(CppRuleClasses.TARGETS_WINDOWS)) {
        sonameLinkopts =
            ImmutableList.of(
                "-Wl,-soname="
                    + SolibSymlinkAction.getDynamicLibrarySoname(
                        soImpl.getRootRelativePath(), /* preserveName= */ false));
      }
    }

    CppLinkActionBuilder dynamicLinkActionBuilder =
        newLinkActionBuilder(soImpl)
            .setWholeArchive(wholeArchive)
            .setNativeDeps(nativeDeps)
            .setAdditionalLinkstampDefines(additionalLinkstampDefines.build())
            .setInterfaceOutput(soInterface)
            .addNonCodeInputs(ccOutputs.getHeaderTokenFiles())
            .addLtoCompilationContext(ccOutputs.getLtoCompilationContext())
            .setLinkType(dynamicLinkType)
            .setLinkingMode(linkingMode)
            .setFake(fake)
            .addActionInputs(linkActionInputs)
            .addLinkopts(linkopts)
            .addLinkopts(sonameLinkopts)
            .addNonCodeInputs(nonCodeLinkerInputs)
            .addVariablesExtensions(variablesExtensions);

    if (fake) {
      dynamicLinkActionBuilder.addFakeObjectFiles(ccOutputs.getObjectFiles(usePic));
    } else {
      dynamicLinkActionBuilder.addObjectFiles(ccOutputs.getObjectFiles(usePic));
    }

    if (!dynamicLinkType.isExecutable()) {
      dynamicLinkActionBuilder.setLibraryIdentifier(mainLibraryIdentifier);
    }

    if (linkingMode == LinkingMode.DYNAMIC) {
      dynamicLinkActionBuilder.setRuntimeInputs(
          ArtifactCategory.DYNAMIC_LIBRARY,
          ccToolchain.getDynamicRuntimeLinkMiddleman(ruleErrorConsumer, featureConfiguration),
          ccToolchain.getDynamicRuntimeLinkInputs(ruleErrorConsumer, featureConfiguration));
    } else {
      dynamicLinkActionBuilder.setRuntimeInputs(
          ArtifactCategory.STATIC_LIBRARY,
          ccToolchain.getStaticRuntimeLinkMiddleman(ruleErrorConsumer, featureConfiguration),
          ccToolchain.getStaticRuntimeLinkInputs(ruleErrorConsumer, featureConfiguration));
    }

    // On Windows, we cannot build a shared library with symbols unresolved, so here we
    // dynamically link to all its dependencies, even for LinkTargetType.NODEPS_DYNAMIC_LIBRARY.
    boolean shouldLinkTransitively =
        featureConfiguration.isEnabled(CppRuleClasses.TARGETS_WINDOWS)
            || dynamicLinkType != LinkTargetType.NODEPS_DYNAMIC_LIBRARY;

    if (shouldLinkTransitively) {
      CcLinkingContext ccLinkingContext = CcLinkingContext.merge(ccLinkingContexts);
      List<LinkerInputs.LibraryToLink> libraries =
          convertLibraryToLinkListToLinkerInputList(
              ccLinkingContext.getLibraries(),
              linkingMode != LinkingMode.DYNAMIC,
              dynamicLinkType.isDynamicLibrary());
      dynamicLinkActionBuilder.addLinkParams(
          libraries,
          ccLinkingContext.getFlattenedUserLinkFlags(),
          ccLinkingContext.getLinkstamps().toList(),
          ccLinkingContext.getNonCodeInputs().toList(),
          ruleErrorConsumer);
    }

    if (pdbFile != null) {
      dynamicLinkActionBuilder.addActionOutput(pdbFile);
    }

    if (defFile != null) {
      dynamicLinkActionBuilder.setDefFile(defFile);
    }

    if (dynamicLinkActionBuilder.hasLtoBitcodeInputs()
        && featureConfiguration.isEnabled(CppRuleClasses.THIN_LTO)) {
      dynamicLinkActionBuilder.setLtoIndexing(true);
      dynamicLinkActionBuilder.setUsePicForLtoBackendActions(usePic);
      CppLinkAction indexAction = dynamicLinkActionBuilder.build();
      if (indexAction != null) {
        actionConstructionContext.registerAction(indexAction);
      }

      dynamicLinkActionBuilder.setLtoIndexing(false);
    }

    if (dynamicLinkActionBuilder.getAllLtoBackendArtifacts() != null) {
      ccLinkingOutputs.addAllLtoArtifacts(dynamicLinkActionBuilder.getAllLtoBackendArtifacts());
    }
    CppLinkAction dynamicLinkAction = dynamicLinkActionBuilder.build();
    ccLinkingOutputs.addLinkActionInputs(dynamicLinkAction.getInputs());
    actionConstructionContext.registerAction(dynamicLinkAction);

    LinkerInputs.LibraryToLink dynamicLibrary = dynamicLinkAction.getOutputLibrary();
    LinkerInputs.LibraryToLink interfaceLibrary = dynamicLinkAction.getInterfaceOutputLibrary();

    // If shared library has neverlink=1, then leave it untouched. Otherwise,
    // create a mangled symlink for it and from now on reference it through
    // mangled name only.
    //
    // When COPY_DYNAMIC_LIBRARIES_TO_BINARY is enabled, we don't need to create the special
    // solibDir, instead we use the original interface library and dynamic library.
    if (dynamicLibrary != null) {
      hasBuiltDynamicLibrary = true;
      libraryToLinkBuilder.setLibraryIdentifier(dynamicLibrary.getLibraryIdentifier());
      if (neverlink
          || featureConfiguration.isEnabled(CppRuleClasses.COPY_DYNAMIC_LIBRARIES_TO_BINARY)) {
        if (interfaceLibrary != null) {
          libraryToLinkBuilder.setInterfaceLibrary(interfaceLibrary.getArtifact());
        }
        libraryToLinkBuilder.setDynamicLibrary(dynamicLibrary.getArtifact());
      } else {
        Artifact implLibraryLinkArtifact =
            SolibSymlinkAction.getDynamicLibrarySymlink(
                /* actionRegistry= */ actionRegistry,
                /* actionConstructionContext= */ actionConstructionContext,
                ccToolchain.getSolibDirectory(),
                dynamicLibrary.getArtifact(),
                /* preserveName= */ false,
                /* prefixConsumer= */ false);
        libraryToLinkBuilder.setDynamicLibrary(implLibraryLinkArtifact);
        libraryToLinkBuilder.setResolvedSymlinkDynamicLibrary(dynamicLibrary.getArtifact());

        if (interfaceLibrary != null) {
          Artifact libraryLinkArtifact =
              SolibSymlinkAction.getDynamicLibrarySymlink(
                  /* actionRegistry= */ actionRegistry,
                  /* actionConstructionContext= */ actionConstructionContext,
                  ccToolchain.getSolibDirectory(),
                  interfaceLibrary.getArtifact(),
                  /* preserveName= */ false,
                  /* prefixConsumer= */ false);
          libraryToLinkBuilder.setInterfaceLibrary(libraryLinkArtifact);
          libraryToLinkBuilder.setResolvedSymlinkInterfaceLibrary(interfaceLibrary.getArtifact());
        }
      }
    }
    return hasBuiltDynamicLibrary;
  }

  private CppLinkActionBuilder newLinkActionBuilder(Artifact outputArtifact) {
    return new CppLinkActionBuilder(
            ruleErrorConsumer,
            actionConstructionContext,
            label,
            outputArtifact,
            configuration,
            ccToolchain,
            fdoContext,
            featureConfiguration,
            semantics)
        .setGrepIncludes(grepIncludes)
        .setIsStampingEnabled(isStampingEnabled)
        .setTestOrTestOnlyTarget(isTestOrTestOnlyTarget)
        .setLinkerFiles(ccToolchain.getLinkerFiles())
        .setLinkArtifactFactory(linkArtifactFactory)
        .setUseTestOnlyFlags(useTestOnlyFlags);
  }

  /**
   * Returns the linked artifact resulting from a linking of the given type. Consults the feature
   * configuration to obtain an action_config that provides the artifact. If the feature
   * configuration provides no artifact, uses a default.
   *
   * <p>We cannot assume that the feature configuration contains an action_config for the link
   * action, because the linux link action depends on hardcoded values in
   * LinkCommandLine.getRawLinkArgv(), which are applied on the condition that an action_config is
   * not present. TODO(b/30393154): Assert that the given link action has an action_config.
   *
   * @throws RuleErrorException
   */
  private Artifact getLinkedArtifact(LinkTargetType linkTargetType) throws RuleErrorException {
      String maybePicName = label.getName() + linkedArtifactNameSuffix;
      if (linkTargetType.picness() == Picness.PIC) {
        maybePicName =
            CppHelper.getArtifactNameForCategory(
                ruleErrorConsumer, ccToolchain, ArtifactCategory.PIC_FILE, maybePicName);
      }
      String linkedName =
          CppHelper.getArtifactNameForCategory(
              ruleErrorConsumer, ccToolchain, linkTargetType.getLinkerOutput(), maybePicName);
      PathFragment artifactFragment =
          PathFragment.create(label.getName()).getParentDirectory().getRelative(linkedName);

    Artifact result =
        actionConstructionContext.getPackageRelativeArtifact(
            artifactFragment,
            configuration.getBinDirectory(label.getPackageIdentifier().getRepository()));

    // If the linked artifact is not the linux default, then a FailAction is generated for the
    // linux default to satisfy the requirement of the implicit output.
    // TODO(b/30132703): Remove the implicit outputs of cc_library.
    Artifact linuxDefault =
        CppHelper.getLinuxLinkedArtifact(
            label,
            actionConstructionContext,
            configuration,
            linkTargetType,
            linkedArtifactNameSuffix);
    if (!result.equals(linuxDefault)) {
      actionConstructionContext.registerAction(
          new FailAction(
              actionConstructionContext.getActionOwner(),
              ImmutableList.of(linuxDefault),
              String.format(
                  "the given toolchain supports creation of %s instead of %s",
                  linuxDefault.getExecPathString(), result.getExecPathString())));
    }

    return result;
  }

  private static List<LinkerInputs.LibraryToLink> convertLibraryToLinkListToLinkerInputList(
      NestedSet<LibraryToLink> librariesToLink, boolean staticMode, boolean forDynamicLibrary) {
    ImmutableList.Builder<LinkerInputs.LibraryToLink> librariesToLinkBuilder =
        ImmutableList.builder();
    for (LibraryToLink libraryToLink : librariesToLink) {
      LinkerInputs.LibraryToLink staticLibraryToLink =
          libraryToLink.getStaticLibrary() == null ? null : libraryToLink.getStaticLibraryToLink();
      LinkerInputs.LibraryToLink picStaticLibraryToLink =
          libraryToLink.getPicStaticLibrary() == null
              ? null
              : libraryToLink.getPicStaticLibraryToLink();
      LinkerInputs.LibraryToLink libraryToLinkToUse = null;
      if (staticMode) {
        if (forDynamicLibrary) {
          if (picStaticLibraryToLink != null) {
            libraryToLinkToUse = picStaticLibraryToLink;
          } else if (staticLibraryToLink != null) {
            libraryToLinkToUse = staticLibraryToLink;
          }
        } else {
          if (staticLibraryToLink != null) {
            libraryToLinkToUse = staticLibraryToLink;
          } else if (picStaticLibraryToLink != null) {
            libraryToLinkToUse = picStaticLibraryToLink;
          }
        }
        if (libraryToLinkToUse == null) {
          if (libraryToLink.getInterfaceLibrary() != null) {
            libraryToLinkToUse = libraryToLink.getInterfaceLibraryToLink();
          } else if (libraryToLink.getDynamicLibrary() != null) {
            libraryToLinkToUse = libraryToLink.getDynamicLibraryToLink();
          }
        }
      } else {
        if (libraryToLink.getInterfaceLibrary() != null) {
          libraryToLinkToUse = libraryToLink.getInterfaceLibraryToLink();
        } else if (libraryToLink.getDynamicLibrary() != null) {
          libraryToLinkToUse = libraryToLink.getDynamicLibraryToLink();
        }
        if (libraryToLinkToUse == null) {
          if (forDynamicLibrary) {
            if (picStaticLibraryToLink != null) {
              libraryToLinkToUse = picStaticLibraryToLink;
            } else if (staticLibraryToLink != null) {
              libraryToLinkToUse = staticLibraryToLink;
            }
          } else {
            if (staticLibraryToLink != null) {
              libraryToLinkToUse = staticLibraryToLink;
            } else if (picStaticLibraryToLink != null) {
              libraryToLinkToUse = picStaticLibraryToLink;
            }
          }
        }
      }
      Preconditions.checkNotNull(libraryToLinkToUse);
      librariesToLinkBuilder.add(libraryToLinkToUse);
    }
    return librariesToLinkBuilder.build();
  }
}
