// 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 static com.google.devtools.build.lib.packages.BuildType.LABEL;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.FailAction;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.analysis.AnalysisUtils;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.MakeVariableSupplier.MapBackedMakeVariableSupplier;
import com.google.devtools.build.lib.analysis.OutputGroupInfo;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.Runfiles;
import com.google.devtools.build.lib.analysis.RunfilesProvider;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
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.test.InstrumentedFilesInfo;
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.AttributeMap;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction;
import com.google.devtools.build.lib.packages.RawAttributeMapper;
import com.google.devtools.build.lib.rules.cpp.CcCommon.CcFlagsSupplier;
import com.google.devtools.build.lib.rules.cpp.CcCompilationHelper.CompilationInfo;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.rules.cpp.LibraryToLink.CcLinkingContext;
import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.Type;
import com.google.devtools.build.lib.util.FileTypeSet;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * A ConfiguredTarget for <code>cc_library</code> rules.
 */
public abstract class CcLibrary implements RuleConfiguredTargetFactory {

  /** A string constant for the name of archive library(.a, .lo) output group. */
  public static final String ARCHIVE_LIBRARY_OUTPUT_GROUP_NAME = "archive";

  /** A string constant for the name of dynamic library output group. */
  public static final String DYNAMIC_LIBRARY_OUTPUT_GROUP_NAME = "dynamic_library";

  private final CppSemantics semantics;

  protected CcLibrary(CppSemantics semantics) {
    this.semantics = semantics;
  }

  // These file extensions don't generate object files.
  private static final FileTypeSet NO_OBJECT_GENERATING_FILETYPES = FileTypeSet.of(
      CppFileTypes.CPP_HEADER, CppFileTypes.ARCHIVE, CppFileTypes.PIC_ARCHIVE,
      CppFileTypes.ALWAYS_LINK_LIBRARY, CppFileTypes.ALWAYS_LINK_PIC_LIBRARY,
      CppFileTypes.SHARED_LIBRARY, CppFileTypes.VERSIONED_SHARED_LIBRARY);

  @Override
  public ConfiguredTarget create(RuleContext context)
      throws InterruptedException, RuleErrorException, ActionConflictException {
    RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(context);
    boolean linkStatic = context.attributes().get("linkstatic", Type.BOOLEAN);
    init(
        semantics,
        context,
        builder,
        /* additionalCopts= */ ImmutableList.of(),
        /* soFilename= */ null,
        context.attributes().get("alwayslink", Type.BOOLEAN),
        /* neverLink= */ false,
        linkStatic,
        /* addDynamicRuntimeInputArtifactsToRunfiles= */ false);
    return builder.build();
  }

  public static void init(
      CppSemantics semantics,
      RuleContext ruleContext,
      RuleConfiguredTargetBuilder targetBuilder,
      ImmutableList<String> additionalCopts,
      PathFragment soFilename,
      boolean alwaysLink,
      boolean neverLink,
      boolean linkStatic,
      boolean addDynamicRuntimeInputArtifactsToRunfiles)
      throws RuleErrorException, InterruptedException {

    semantics.validateDeps(ruleContext);
    if (ruleContext.hasErrors()) {
      return;
    }

    final CcCommon common = new CcCommon(ruleContext);
    common.reportInvalidOptions(ruleContext);

    CcToolchainProvider ccToolchain = common.getToolchain();
    CppConfiguration cppConfiguration = ruleContext.getFragment(CppConfiguration.class);

    ImmutableMap.Builder<String, String> toolchainMakeVariables = ImmutableMap.builder();
    ccToolchain.addGlobalMakeVariables(toolchainMakeVariables);
    ruleContext.initConfigurationMakeVariableContext(
        new MapBackedMakeVariableSupplier(toolchainMakeVariables.build()),
        new CcFlagsSupplier(ruleContext));

    FdoContext fdoContext = common.getFdoContext();
    FeatureConfiguration featureConfiguration =
        CcCommon.configureFeaturesOrReportRuleError(ruleContext, ccToolchain);
    PrecompiledFiles precompiledFiles = new PrecompiledFiles(ruleContext);

    semantics.validateAttributes(ruleContext);
    if (ruleContext.hasErrors()) {
      return;
    }

    ImmutableList<TransitiveInfoCollection> deps =
        ImmutableList.copyOf(ruleContext.getPrerequisites("deps", Mode.TARGET));
    CppHelper.checkProtoLibrariesInDeps(ruleContext, deps);
    if (ruleContext.hasErrors()) {
      return;
    }
    CcCompilationHelper compilationHelper =
        new CcCompilationHelper(
                ruleContext,
                ruleContext,
                ruleContext.getLabel(),
                CppHelper.getGrepIncludes(ruleContext),
                semantics,
                featureConfiguration,
                ccToolchain,
                fdoContext)
            .fromCommon(common, additionalCopts)
            .addSources(common.getSources())
            .addPrivateHeaders(common.getPrivateHeaders())
            .addPublicHeaders(common.getHeaders())
            .setCodeCoverageEnabled(CcCompilationHelper.isCodeCoverageEnabled(ruleContext))
            .addCcCompilationContexts(
                Streams.stream(AnalysisUtils.getProviders(deps, CcInfo.PROVIDER))
                    .map(CcInfo::getCcCompilationContext)
                    .collect(ImmutableList.toImmutableList()))
            .addCcCompilationContexts(
                ImmutableList.of(CcCompilationHelper.getStlCcCompilationContext(ruleContext)))
            .addQuoteIncludeDirs(semantics.getQuoteIncludes(ruleContext))
            .setHeadersCheckingMode(semantics.determineHeadersCheckingMode(ruleContext));

    CcLinkingHelper linkingHelper =
        new CcLinkingHelper(
                ruleContext,
                ruleContext.getLabel(),
                ruleContext,
                ruleContext,
                semantics,
                featureConfiguration,
                ccToolchain,
                fdoContext,
                ruleContext.getConfiguration(),
                ruleContext.getFragment(CppConfiguration.class),
                ruleContext.getSymbolGenerator())
            .fromCommon(ruleContext, common)
            .setGrepIncludes(CppHelper.getGrepIncludes(ruleContext))
            .setTestOrTestOnlyTarget(ruleContext.isTestOnlyTarget())
            .addLinkopts(common.getLinkopts())
            .emitInterfaceSharedLibraries(true)
            .setAlwayslink(alwaysLink)
            .setNeverLink(neverLink)
            .addLinkstamps(ruleContext.getPrerequisites("linkstamp", Mode.TARGET));

    Artifact soImplArtifact = null;
    boolean supportsDynamicLinker = ccToolchain.supportsDynamicLinker(featureConfiguration);
    // TODO(djasper): This is hacky. We should actually try to figure out whether we generate
    // ccOutputs.
    boolean createDynamicLibrary =
        !linkStatic
            && supportsDynamicLinker
            && (appearsToHaveObjectFiles(ruleContext.attributes())
                || featureConfiguration.isEnabled(CppRuleClasses.HEADER_MODULE_CODEGEN));
    if (soFilename != null) {
      if (!soFilename.getPathString().endsWith(".so")) { // Sanity check.
        ruleContext.attributeError("outs", "file name must end in '.so'");
      }
      if (createDynamicLibrary) {
        soImplArtifact = ruleContext.getBinArtifact(soFilename);
      }
    }

    if (ruleContext.getRule().isAttrDefined("srcs", BuildType.LABEL_LIST)) {
      ruleContext.checkSrcsSamePackage(true);
    }
    if (ruleContext.getRule().isAttrDefined("textual_hdrs", BuildType.LABEL_LIST)) {
      compilationHelper.addPublicTextualHeaders(
          ruleContext.getPrerequisiteArtifacts("textual_hdrs", Mode.TARGET).list());
    }
    if (ruleContext.getRule().isAttrDefined("include_prefix", Type.STRING)
        && ruleContext.attributes().isAttributeValueExplicitlySpecified("include_prefix")) {
      compilationHelper.setIncludePrefix(
          ruleContext.attributes().get("include_prefix", Type.STRING));
    }
    if (ruleContext.getRule().isAttrDefined("strip_include_prefix", Type.STRING)
        && ruleContext.attributes().isAttributeValueExplicitlySpecified("strip_include_prefix")) {
      compilationHelper.setStripIncludePrefix(
          ruleContext.attributes().get("strip_include_prefix", Type.STRING));
    }

    if (common.getLinkopts().contains("-static")) {
      ruleContext.attributeWarning("linkopts", "Using '-static' here won't work. "
                                   + "Did you mean to use 'linkstatic=1' instead?");
    }

    linkingHelper.setShouldCreateDynamicLibrary(createDynamicLibrary);
    linkingHelper.setLinkerOutputArtifact(soImplArtifact);

    // If the reason we're not creating a dynamic library is that the toolchain
    // doesn't support it, then register an action which complains when triggered,
    // which only happens when some rule explicitly depends on the dynamic library.
    if (!createDynamicLibrary && !supportsDynamicLinker) {
      ImmutableList.Builder<Artifact> dynamicLibraries = ImmutableList.builder();
      dynamicLibraries.add(
          CppHelper.getLinkedArtifact(
              ruleContext,
              ccToolchain,
              ruleContext.getConfiguration(),
              LinkTargetType.NODEPS_DYNAMIC_LIBRARY));
      if (CppHelper.useInterfaceSharedLibraries(
          cppConfiguration, ccToolchain, featureConfiguration)) {
        dynamicLibraries.add(
            CppHelper.getLinkedArtifact(
                ruleContext,
                ccToolchain,
                ruleContext.getConfiguration(),
                LinkTargetType.INTERFACE_DYNAMIC_LIBRARY));
      }
      ruleContext.registerAction(new FailAction(ruleContext.getActionOwner(),
          dynamicLibraries.build(), "Toolchain does not support dynamic linking"));
    } else if (!createDynamicLibrary
        && ruleContext.attributes().isConfigurable("srcs")) {
      // If "srcs" is configurable, the .so output is always declared because the logic that
      // determines implicit outs doesn't know which value of "srcs" will ultimately get chosen.
      // Here, where we *do* have the correct value, it may not contain any source files to
      // generate an .so with. If that's the case, register a fake generating action to prevent
      // a "no generating action for this artifact" error.
      ImmutableList.Builder<Artifact> dynamicLibraries = ImmutableList.builder();
      dynamicLibraries.add(
          CppHelper.getLinkedArtifact(
              ruleContext,
              ccToolchain,
              ruleContext.getConfiguration(),
              LinkTargetType.NODEPS_DYNAMIC_LIBRARY));
      if (CppHelper.useInterfaceSharedLibraries(
          cppConfiguration, ccToolchain, featureConfiguration)) {
        dynamicLibraries.add(
            CppHelper.getLinkedArtifact(
                ruleContext,
                ccToolchain,
                ruleContext.getConfiguration(),
                LinkTargetType.INTERFACE_DYNAMIC_LIBRARY));
      }
      ruleContext.registerAction(new FailAction(ruleContext.getActionOwner(),
          dynamicLibraries.build(), "configurable \"srcs\" triggers an implicit .so output "
          + "even though there are no sources to compile in this configuration"));
    }

    CompilationInfo compilationInfo = compilationHelper.compile();
    CcCompilationOutputs precompiledFilesObjects =
        CcCompilationOutputs.builder()
            .addObjectFiles(precompiledFiles.getObjectFiles(/* usePic= */ true))
            .addPicObjectFiles(precompiledFiles.getObjectFiles(/* usePic= */ true))
            .build();
    CcCompilationOutputs ccCompilationOutputs =
        CcCompilationOutputs.builder()
            .merge(precompiledFilesObjects)
            .merge(compilationInfo.getCcCompilationOutputs())
            .build();

    // Generate .a and .so outputs even without object files to fulfill the rule class
    // contract wrt. implicit output files, if the contract says so. Behavior here differs
    // between Bazel and Blaze.
    CcLinkingOutputs ccLinkingOutputs = CcLinkingOutputs.EMPTY;
    if (ruleContext.getRule().getImplicitOutputsFunction() != ImplicitOutputsFunction.NONE
        || !ccCompilationOutputs.isEmpty()) {
      if (featureConfiguration.isEnabled(CppRuleClasses.TARGETS_WINDOWS)) {
        // If windows_export_all_symbols feature is enabled, bazel parses object files to generate
        // DEF file and use it to export symbols. The generated DEF file won't be used if a custom
        // DEF file is specified by win_def_file attribute.
        if (CppHelper.shouldUseGeneratedDefFile(ruleContext, featureConfiguration)) {
          try {
            Artifact generatedDefFile =
                CppHelper.createDefFileActions(
                    ruleContext,
                    ruleContext.getPrerequisiteArtifact("$def_parser", Mode.HOST),
                    ccCompilationOutputs.getObjectFiles(false),
                    ccToolchain
                        .getFeatures()
                        .getArtifactNameForCategory(
                            ArtifactCategory.DYNAMIC_LIBRARY, ruleContext.getLabel().getName()));
            linkingHelper.setDefFile(generatedDefFile);
          } catch (EvalException e) {
            ruleContext.throwWithRuleError(e.getMessage());
            throw new IllegalStateException("Should not be reached");
          }
        }

        // If user specifies a custom DEF file, then we use this one instead of the generated one.
        Artifact customDefFile = null;
        if (ruleContext.isAttrDefined("win_def_file", LABEL)) {
          customDefFile = ruleContext.getPrerequisiteArtifact("win_def_file", Mode.TARGET);
          if (customDefFile != null) {
            linkingHelper.setDefFile(customDefFile);
          }
        }
      }
      ccLinkingOutputs = linkingHelper.link(ccCompilationOutputs);
    }

    ImmutableSortedMap.Builder<String, NestedSet<Artifact>> outputGroups =
        ImmutableSortedMap.naturalOrder();
    if (!ccLinkingOutputs.isEmpty()) {
      outputGroups.putAll(
          addLinkerOutputArtifacts(
              ruleContext,
              ccToolchain,
              cppConfiguration,
              ruleContext.getConfiguration(),
              ccCompilationOutputs,
              featureConfiguration));
    }
    List<LibraryToLink> precompiledLibraries =
        convertPrecompiledLibrariesToLibraryToLink(
            common, ruleContext.getFragment(CppConfiguration.class).forcePic(), precompiledFiles);

    if (!ccCompilationOutputs.isEmpty()) {
      checkIfLinkOutputsCollidingWithPrecompiledFiles(
          ruleContext, ccLinkingOutputs, precompiledLibraries);
    }

    ImmutableList<LibraryToLink> libraryToLinks =
        createLibrariesToLinkList(
            ccLinkingOutputs.getLibraryToLink(),
            precompiledLibraries,
            ccCompilationOutputs.isEmpty());

    CcLinkingContext ccLinkingContext =
        linkingHelper.buildCcLinkingContextFromLibrariesToLink(
            neverLink ? ImmutableList.of() : libraryToLinks,
            compilationInfo.getCcCompilationContext());
    CcNativeLibraryProvider ccNativeLibraryProvider =
        CppHelper.collectNativeCcLibraries(
            ruleContext.getPrerequisites("deps", Mode.TARGET), libraryToLinks);

    /*
     * We always generate a static library, even if there aren't any source files.
     * This keeps things simpler by avoiding special cases when making use of the library.
     * For example, this is needed to ensure that building a library with "bazel build"
     * will also build all of the library's "deps".
     * However, we only generate a dynamic library if there are source files.
     */
    // For now, we don't add the precompiled libraries to the files to build.

    NestedSetBuilder<Artifact> filesBuilder = NestedSetBuilder.stableOrder();
    if (!ccLinkingOutputs.isEmpty()) {
      LibraryToLink artifactsToBuild = ccLinkingOutputs.getLibraryToLink();
      if (artifactsToBuild.getStaticLibrary() != null) {
        filesBuilder.add(artifactsToBuild.getStaticLibrary());
      }
      if (artifactsToBuild.getPicStaticLibrary() != null) {
        filesBuilder.add(artifactsToBuild.getPicStaticLibrary());
      }
      if (!featureConfiguration.isEnabled(CppRuleClasses.TARGETS_WINDOWS)) {
        if (artifactsToBuild.getResolvedSymlinkDynamicLibrary() != null) {
          filesBuilder.add(artifactsToBuild.getResolvedSymlinkDynamicLibrary());
        } else if (artifactsToBuild.getDynamicLibrary() != null) {
          filesBuilder.add(artifactsToBuild.getDynamicLibrary());
        }
        if (artifactsToBuild.getResolvedSymlinkInterfaceLibrary() != null) {
          filesBuilder.add(artifactsToBuild.getResolvedSymlinkInterfaceLibrary());
        } else if (artifactsToBuild.getInterfaceLibrary() != null) {
          filesBuilder.add(artifactsToBuild.getInterfaceLibrary());
        }
      }
    }

    if (!featureConfiguration.isEnabled(CppRuleClasses.HEADER_MODULE_CODEGEN)) {
      warnAboutEmptyLibraries(ruleContext, compilationInfo.getCcCompilationOutputs(), linkStatic);
    }
    NestedSet<Artifact> filesToBuild = filesBuilder.build();

    List<Artifact> instrumentedObjectFiles = new ArrayList<>();
    instrumentedObjectFiles.addAll(compilationInfo.getCcCompilationOutputs().getObjectFiles(false));
    instrumentedObjectFiles.addAll(compilationInfo.getCcCompilationOutputs().getObjectFiles(true));
    InstrumentedFilesInfo instrumentedFilesProvider =
        common.getInstrumentedFilesProvider(
            instrumentedObjectFiles,
            /* withBaselineCoverage= */ true,
            /* virtualToOriginalHeaders= */ NestedSetBuilder.create(Order.STABLE_ORDER));
    CppHelper.maybeAddStaticLinkMarkerProvider(targetBuilder, ruleContext);

    Runfiles.Builder builder = new Runfiles.Builder(ruleContext.getWorkspaceName());
    builder.addDataDeps(ruleContext);
    builder.add(ruleContext, RunfilesProvider.DEFAULT_RUNFILES);
    if (addDynamicRuntimeInputArtifactsToRunfiles) {
      try {
        builder.addTransitiveArtifacts(
            ccToolchain.getDynamicRuntimeLinkInputs(featureConfiguration));
      } catch (EvalException e) {
        e.printStackTrace();
      }
    }
    Runfiles runfiles = builder.build();
    Runfiles.Builder defaultRunfiles =
        new Runfiles.Builder(ruleContext.getWorkspaceName())
            .merge(runfiles)
            .addArtifacts(LibraryToLink.getDynamicLibrariesForRuntime(!neverLink, libraryToLinks));

    Runfiles.Builder dataRunfiles =
        new Runfiles.Builder(ruleContext.getWorkspaceName())
            .merge(runfiles)
            .addArtifacts(
                LibraryToLink.getDynamicLibrariesForRuntime(
                    /* linkingStatically= */ false, libraryToLinks));

    @SuppressWarnings("unchecked")
    CppDebugFileProvider cppDebugFileProvider =
        CcCompilationHelper.buildCppDebugFileProvider(
            compilationInfo.getCcCompilationOutputs(),
            (List<TransitiveInfoCollection>) ruleContext.getPrerequisites("deps", Mode.TARGET));
    Map<String, NestedSet<Artifact>> currentOutputGroups =
        CcCompilationHelper.buildOutputGroupsForEmittingCompileProviders(
            compilationInfo.getCcCompilationOutputs(),
            compilationInfo.getCcCompilationContext(),
            ruleContext.getFragment(CppConfiguration.class),
            ccToolchain,
            featureConfiguration,
            ruleContext);
    CcSkylarkApiProvider.maybeAdd(ruleContext, targetBuilder);
    targetBuilder
        .setFilesToBuild(filesToBuild)
        .addProvider(cppDebugFileProvider)
        .addProvider(ccNativeLibraryProvider)
        .addNativeDeclaredProvider(
            CcInfo.builder()
                .setCcCompilationContext(compilationInfo.getCcCompilationContext())
                .setCcLinkingContext(ccLinkingContext)
                .build())
        .addOutputGroups(
            CcCommon.mergeOutputGroups(ImmutableList.of(currentOutputGroups, outputGroups.build())))
        .addNativeDeclaredProvider(instrumentedFilesProvider)
        .addProvider(RunfilesProvider.withData(defaultRunfiles.build(), dataRunfiles.build()))
        .addOutputGroup(
            OutputGroupInfo.HIDDEN_TOP_LEVEL,
            collectHiddenTopLevelArtifacts(
                ruleContext, ccToolchain, ccCompilationOutputs, featureConfiguration))
        .addOutputGroup(
            CcCompilationHelper.HIDDEN_HEADER_TOKENS,
            CcCompilationHelper.collectHeaderTokens(
                ruleContext,
                ruleContext.getFragment(CppConfiguration.class),
                ccCompilationOutputs));
  }

  private static NestedSet<Artifact> collectHiddenTopLevelArtifacts(
      RuleContext ruleContext,
      CcToolchainProvider toolchain,
      CcCompilationOutputs ccCompilationOutputs,
      FeatureConfiguration featureConfiguration) {
    // Ensure that we build all the dependencies, otherwise users may get confused.
    NestedSetBuilder<Artifact> artifactsToForceBuilder = NestedSetBuilder.stableOrder();
    CppConfiguration cppConfiguration = ruleContext.getFragment(CppConfiguration.class);
    boolean processHeadersInDependencies = cppConfiguration.processHeadersInDependencies();
    boolean usePic = toolchain.usePicForDynamicLibraries(cppConfiguration, featureConfiguration);
    artifactsToForceBuilder.addTransitive(
        ccCompilationOutputs.getFilesToCompile(processHeadersInDependencies, usePic));
    for (OutputGroupInfo dep :
        ruleContext.getPrerequisites(
            "deps", Mode.TARGET, OutputGroupInfo.SKYLARK_CONSTRUCTOR)) {
      artifactsToForceBuilder.addTransitive(
          dep.getOutputGroup(OutputGroupInfo.HIDDEN_TOP_LEVEL));
    }
    return artifactsToForceBuilder.build();
  }

  private static void warnAboutEmptyLibraries(RuleContext ruleContext,
      CcCompilationOutputs ccCompilationOutputs,
      boolean linkstaticAttribute) {
    if (ccCompilationOutputs.getObjectFiles(false).isEmpty()
        && ccCompilationOutputs.getObjectFiles(true).isEmpty()) {
      if (!linkstaticAttribute && appearsToHaveObjectFiles(ruleContext.attributes())) {
        ruleContext.attributeWarning("linkstatic",
            "setting 'linkstatic=1' is recommended if there are no object files");
      }
    } else {
      if (!linkstaticAttribute && !appearsToHaveObjectFiles(ruleContext.attributes())) {
        Artifact element = Iterables.getFirst(
            ccCompilationOutputs.getObjectFiles(false),
            ccCompilationOutputs.getObjectFiles(true).get(0));
        ruleContext.attributeWarning("srcs",
             "this library appears at first glance to have no object files, "
             + "but on closer inspection it does have something to link, e.g. "
             + element.prettyPrint() + ". "
             + "(You may have used some very confusing rule names in srcs? "
             + "Or the library consists entirely of a linker script?) "
             + "Bazel assumed linkstatic=1, but this may be inappropriate. "
             + "You may need to add an explicit '.cc' file to 'srcs'. "
             + "Alternatively, add 'linkstatic=1' to suppress this warning");
      }
    }
  }

  /**
   * Returns true if the rule (which must be a cc_library rule) appears to have object files.
   * This only looks at the rule itself, not at any other rules (from this package or other
   * packages) that it might reference.
   *
   * <p>In some cases, this may return "true" even though the rule actually has no object files.
   * For example, it will return true for a rule such as
   * <code>cc_library(name = 'foo', srcs = [':bar'])</code> because we can't tell what ':bar' is;
   * it might be a genrule that generates a source file, or it might be a genrule that generates a
   * header file. Likewise,
   * <code>cc_library(name = 'foo', srcs = select({':a': ['foo.cc'], ':b': []}))</code> returns
   * "true" even though the sources *may* be empty. This reflects the fact that there's no way
   * to tell which value "srcs" will take without knowing the rule's configuration.
   *
   * <p>In other cases, this may return "false" even though the rule actually does have object
   * files. For example, it will return false for a rule such as
   * <code>cc_library(name = 'foo', srcs = ['bar.h'])</code> but as in the other example above,
   * we can't tell whether 'bar.h' is a file name or a rule name, and 'bar.h' could in fact be the
   * name of a genrule that generates a source file.
   */
  public static boolean appearsToHaveObjectFiles(AttributeMap rule) {
    if ((rule instanceof RawAttributeMapper) && rule.isConfigurable("srcs")) {
      // Since this method gets called by loading phase logic (e.g. the cc_library implicit outputs
      // function), the attribute mapper may not be able to resolve configurable attributes. When
      // that's the case, there's no way to know which value a configurable "srcs" will take, so
      // we conservatively assume object files are possible.
      return true;
    }

    List<Label> srcs = rule.get("srcs", BuildType.LABEL_LIST);
    if (srcs != null) {
      for (Label srcfile : srcs) {
        /*
         * We cheat a little bit here by looking at the file extension
         * of the Label treated as file name.  In general that might
         * not necessarily work, because of the possibility that the
         * user might give a rule a funky name ending in one of these
         * extensions, e.g.
         *    genrule(name = 'foo.h', outs = ['foo.cc'], ...) // Funky rule name!
         *    cc_library(name = 'bar', srcs = ['foo.h']) // This DOES have object files.
         */
        if (!NO_OBJECT_GENERATING_FILETYPES.matches(srcfile.getName())) {
          return true;
        }
      }
    }
    return false;
  }

  /**
   * Adds linker output artifacts to the given map, to be registered on the configured target as
   * output groups.
   */
  private static Map<String, NestedSet<Artifact>> addLinkerOutputArtifacts(
      RuleContext ruleContext,
      CcToolchainProvider ccToolchain,
      CppConfiguration cppConfiguration,
      BuildConfiguration configuration,
      CcCompilationOutputs ccCompilationOutputs,
      FeatureConfiguration featureConfiguration)
      throws RuleErrorException {

    NestedSetBuilder<Artifact> archiveFile = new NestedSetBuilder<>(Order.STABLE_ORDER);
    NestedSetBuilder<Artifact> dynamicLibrary = new NestedSetBuilder<>(Order.STABLE_ORDER);

    ImmutableSortedMap.Builder<String, NestedSet<Artifact>> outputGroups =
        ImmutableSortedMap.naturalOrder();
    if (!ruleContext.attributes().has("alwayslink", Type.BOOLEAN)
        || !ruleContext.attributes().has("linkstatic", Type.BOOLEAN)) {
      return outputGroups.build();
    }

    if (ruleContext.attributes().get("alwayslink", Type.BOOLEAN)) {
      archiveFile.add(
          CppHelper.getLinkedArtifact(
              ruleContext,
              ccToolchain,
              configuration,
              Link.LinkTargetType.ALWAYS_LINK_STATIC_LIBRARY,
              /* linkedArtifactNameSuffix= */ ""));
    } else {
      archiveFile.add(
          CppHelper.getLinkedArtifact(
              ruleContext,
              ccToolchain,
              configuration,
              Link.LinkTargetType.STATIC_LIBRARY,
              /* linkedArtifactNameSuffix= */ ""));
    }

    if (!ruleContext.attributes().get("linkstatic", Type.BOOLEAN)
        && !ccCompilationOutputs.isEmpty()) {
      dynamicLibrary.add(
          CppHelper.getLinkedArtifact(
              ruleContext,
              ccToolchain,
              configuration,
              Link.LinkTargetType.NODEPS_DYNAMIC_LIBRARY,
              /* linkedArtifactNameSuffix= */ ""));

      if (CppHelper.useInterfaceSharedLibraries(
          cppConfiguration, ccToolchain, featureConfiguration)) {
        dynamicLibrary.add(
            CppHelper.getLinkedArtifact(
                ruleContext,
                ccToolchain,
                configuration,
                LinkTargetType.INTERFACE_DYNAMIC_LIBRARY,
                /* linkedArtifactNameSuffix= */ ""));
      }
    }

    outputGroups.put(ARCHIVE_LIBRARY_OUTPUT_GROUP_NAME, archiveFile.build());
    outputGroups.put(DYNAMIC_LIBRARY_OUTPUT_GROUP_NAME, dynamicLibrary.build());
    return outputGroups.build();
  }

  private static ImmutableList<LibraryToLink> createLibrariesToLinkList(
      @Nullable LibraryToLink outputLibrary,
      List<LibraryToLink> precompiledLibraries,
      boolean ccCompilationOutputsIsEmpty) {
    ImmutableList.Builder<LibraryToLink> librariesToLink = ImmutableList.builder();
    librariesToLink.addAll(precompiledLibraries);

    // For cc_library if it contains precompiled libraries we link them. If it contains normal
    // sources we link them as well, if it doesn't contain normal sources, then we don't do
    // anything else if there were  precompiled libraries. However, if there are no precompiled
    // libraries and there are no normal sources, then we use the implicitly created link output
    // files if they exist.
    if (!ccCompilationOutputsIsEmpty
        || (precompiledLibraries.isEmpty()
            && isContentsOfCcLinkingOutputsImplicitlyCreated(
                ccCompilationOutputsIsEmpty, outputLibrary == null))) {
      if (outputLibrary != null) {
        librariesToLink.add(outputLibrary);
      }
    }

    return librariesToLink.build();
  }

  private static boolean isContentsOfCcLinkingOutputsImplicitlyCreated(
      boolean ccCompilationOutputsIsEmpty, boolean ccLinkingOutputsIsEmpty) {
    return ccCompilationOutputsIsEmpty && !ccLinkingOutputsIsEmpty;
  }

  private static Map<String, Artifact> buildMapIdentifierToArtifact(Iterable<Artifact> artifacts) {
    ImmutableMap.Builder<String, Artifact> libraries = ImmutableMap.builder();
    for (Artifact artifact : artifacts) {
      libraries.put(CcLinkingOutputs.libraryIdentifierOf(artifact), artifact);
    }
    return libraries.build();
  }

  /*
   * Add the libraries from srcs, if any. For static/mostly static
   * linking we setup the dynamic libraries if there are no static libraries
   * to choose from. Path to the libraries will be mangled to avoid using
   * absolute path names on the -rpath, but library filenames will be
   * preserved (since some libraries might have SONAME tag) - symlink will
   * be created to the parent directory instead.
   *
   * For compatibility with existing BUILD files, any ".a" or ".lo" files listed in
   * srcs are assumed to be position-independent code, or at least suitable for
   * inclusion in shared libraries, unless they end with ".nopic.a" or ".nopic.lo".
   *
   * Note that some target platforms do not require shared library code to be PIC.
   */
  private static List<LibraryToLink> convertPrecompiledLibrariesToLibraryToLink(
      CcCommon common, boolean forcePic, PrecompiledFiles precompiledFiles) {
    ImmutableList.Builder<LibraryToLink> librariesToLink = ImmutableList.builder();

    Map<String, Artifact> staticLibraries =
        buildMapIdentifierToArtifact(precompiledFiles.getStaticLibraries());
    Map<String, Artifact> picStaticLibraries =
        buildMapIdentifierToArtifact(precompiledFiles.getPicStaticLibraries());
    Map<String, Artifact> alwayslinkStaticLibraries =
        buildMapIdentifierToArtifact(precompiledFiles.getAlwayslinkStaticLibraries());
    Map<String, Artifact> alwayslinkPicStaticLibraries =
        buildMapIdentifierToArtifact(precompiledFiles.getPicAlwayslinkLibraries());
    Map<String, Artifact> dynamicLibraries =
        buildMapIdentifierToArtifact(precompiledFiles.getSharedLibraries());

    Set<String> identifiersUsed = new HashSet<>();
    for (Map.Entry<String, Artifact> staticLibraryEntry :
        Iterables.concat(staticLibraries.entrySet(), alwayslinkStaticLibraries.entrySet())) {
      LibraryToLink.Builder libraryToLinkBuilder = LibraryToLink.builder();
      String identifier = staticLibraryEntry.getKey();
      libraryToLinkBuilder.setLibraryIdentifier(identifier);
      boolean hasPic = picStaticLibraries.containsKey(identifier);
      boolean hasAlwaysPic = alwayslinkPicStaticLibraries.containsKey(identifier);
      if (hasPic || hasAlwaysPic) {
        Artifact picStaticLibrary = null;
        if (hasPic) {
          picStaticLibrary = picStaticLibraries.get(identifier);
        } else {
          picStaticLibrary = alwayslinkPicStaticLibraries.get(identifier);
        }
        libraryToLinkBuilder.setPicStaticLibrary(picStaticLibrary);
      }
      if (!forcePic || !(hasPic || hasAlwaysPic)) {
        libraryToLinkBuilder.setStaticLibrary(staticLibraryEntry.getValue());
      }
      if (dynamicLibraries.containsKey(identifier)) {
        Artifact library = dynamicLibraries.get(identifier);
        Artifact symlink = common.getDynamicLibrarySymlink(library, true);
        libraryToLinkBuilder.setDynamicLibrary(symlink);
        libraryToLinkBuilder.setResolvedSymlinkDynamicLibrary(library);
      }
      libraryToLinkBuilder.setAlwayslink(alwayslinkStaticLibraries.containsKey(identifier));
      identifiersUsed.add(identifier);
      librariesToLink.add(libraryToLinkBuilder.build());
    }

    for (Map.Entry<String, Artifact> picStaticLibraryEntry :
        Iterables.concat(picStaticLibraries.entrySet(), alwayslinkPicStaticLibraries.entrySet())) {
      String identifier = picStaticLibraryEntry.getKey();
      if (identifiersUsed.contains(identifier)) {
        continue;
      }
      LibraryToLink.Builder libraryToLinkBuilder = LibraryToLink.builder();
      libraryToLinkBuilder.setLibraryIdentifier(identifier);
      libraryToLinkBuilder.setPicStaticLibrary(picStaticLibraryEntry.getValue());
      if (dynamicLibraries.containsKey(identifier)) {
        Artifact library = dynamicLibraries.get(identifier);
        Artifact symlink = common.getDynamicLibrarySymlink(library, true);
        libraryToLinkBuilder.setDynamicLibrary(symlink);
        libraryToLinkBuilder.setResolvedSymlinkDynamicLibrary(library);
      }
      libraryToLinkBuilder.setAlwayslink(alwayslinkPicStaticLibraries.containsKey(identifier));
      identifiersUsed.add(identifier);
      librariesToLink.add(libraryToLinkBuilder.build());
    }

    for (Map.Entry<String, Artifact> dynamicLibraryEntry : dynamicLibraries.entrySet()) {
      String identifier = dynamicLibraryEntry.getKey();
      if (identifiersUsed.contains(identifier)) {
        continue;
      }
      LibraryToLink.Builder libraryToLinkBuilder = LibraryToLink.builder();
      libraryToLinkBuilder.setLibraryIdentifier(identifier);
      Artifact library = dynamicLibraryEntry.getValue();
      Artifact symlink = common.getDynamicLibrarySymlink(library, true);
      libraryToLinkBuilder.setDynamicLibrary(symlink);
      libraryToLinkBuilder.setResolvedSymlinkDynamicLibrary(library);
      librariesToLink.add(libraryToLinkBuilder.build());
    }
    return librariesToLink.build();
  }



  private static void checkIfLinkOutputsCollidingWithPrecompiledFiles(
      RuleContext ruleContext,
      CcLinkingOutputs ccLinkingOutputs,
      List<LibraryToLink> precompiledLibraries) {
    String identifier = ccLinkingOutputs.getLibraryToLink().getLibraryIdentifier();
    for (LibraryToLink precompiledLibrary : precompiledLibraries) {
      if (identifier.equals(precompiledLibrary.getLibraryIdentifier())) {
        ruleContext.ruleError(
            "Can't put library with identifier '"
                + precompiledLibrary.getLibraryIdentifier()
                + "' into the srcs of a "
                + ruleContext.getRuleClassNameForLogging()
                + " with the same name ("
                + ruleContext.getRule().getName()
                + ") which also contains other code or objects to link");
      }
    }
  }
}
