// 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 static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import static com.google.devtools.build.lib.packages.BuildType.NODEP_LABEL;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams;
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.Artifact.SpecialArtifact;
import com.google.devtools.build.lib.actions.FailAction;
import com.google.devtools.build.lib.actions.MiddlemanFactory;
import com.google.devtools.build.lib.actions.ParamFileInfo;
import com.google.devtools.build.lib.actions.ParameterFile;
import com.google.devtools.build.lib.analysis.AliasProvider;
import com.google.devtools.build.lib.analysis.AnalysisUtils;
import com.google.devtools.build.lib.analysis.Expander;
import com.google.devtools.build.lib.analysis.FileProvider;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.Runfiles;
import com.google.devtools.build.lib.analysis.StaticallyLinkedMarkerProvider;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.actions.ActionConstructionContext;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
import com.google.devtools.build.lib.analysis.actions.FileWriteAction;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.actions.SymlinkAction;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.CompilationMode;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.analysis.platform.ToolchainInfo;
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.packages.Type;
import com.google.devtools.build.lib.rules.cpp.CcLinkingContext.Linkstamp;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.ExpansionException;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration.Tool;
import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType;
import com.google.devtools.build.lib.rules.proto.ProtoInfo;
import com.google.devtools.build.lib.shell.ShellUtils;
import com.google.devtools.build.lib.syntax.EvalException;
import com.google.devtools.build.lib.syntax.StarlarkSemantics;
import com.google.devtools.build.lib.util.FileTypeSet;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;

/**
 * Helper class for functionality shared by cpp related rules.
 *
 * <p>This class can be used only after the loading phase.
 */
public class CppHelper {

  static final PathFragment OBJS = PathFragment.create("_objs");
  static final PathFragment PIC_OBJS = PathFragment.create("_pic_objs");
  static final PathFragment DOTD_FILES = PathFragment.create("_dotd");
  static final PathFragment PIC_DOTD_FILES = PathFragment.create("_pic_dotd");

  // TODO(bazel-team): should this use Link.SHARED_LIBRARY_FILETYPES?
  public static final FileTypeSet SHARED_LIBRARY_FILETYPES =
      FileTypeSet.of(CppFileTypes.SHARED_LIBRARY, CppFileTypes.VERSIONED_SHARED_LIBRARY);

  /** Base label of the c++ toolchain category. */
  public static final String TOOLCHAIN_TYPE_LABEL = "//tools/cpp:toolchain_type";

  private CppHelper() {
    // prevents construction
  }

  /** Returns the malloc implementation for the given target. */
  public static TransitiveInfoCollection mallocForTarget(
      RuleContext ruleContext, String mallocAttrName) {
    if (ruleContext.getFragment(CppConfiguration.class).customMalloc() != null) {
      return ruleContext.getPrerequisite(":default_malloc", Mode.TARGET);
    } else {
      return ruleContext.getPrerequisite(mallocAttrName, Mode.TARGET);
    }
  }

  public static TransitiveInfoCollection mallocForTarget(RuleContext ruleContext) {
    return mallocForTarget(ruleContext, "malloc");
  }

  /**
   * Expands Make variables in a list of string and tokenizes the result. If the package feature
   * no_copts_tokenization is set, tokenize only items consisting of a single make variable.
   *
   * @param ruleContext the ruleContext to be used as the context of Make variable expansion
   * @param attributeName the name of the attribute to use in error reporting
   * @param input the list of strings to expand
   * @return a list of strings containing the expanded and tokenized values for the attribute
   */
  private static List<String> expandMakeVariables(
      RuleContext ruleContext, String attributeName, List<String> input) {
    boolean tokenization = !ruleContext.getFeatures().contains("no_copts_tokenization");

    List<String> tokens = new ArrayList<>();
    Expander expander = ruleContext.getExpander().withDataExecLocations();
    for (String token : input) {
      // Legacy behavior: tokenize all items.
      if (tokenization) {
        expander.tokenizeAndExpandMakeVars(tokens, attributeName, token);
      } else {
        String exp = expander.expandSingleMakeVariable(attributeName, token);
        if (exp != null) {
          try {
            ShellUtils.tokenize(tokens, exp);
          } catch (ShellUtils.TokenizationException e) {
            ruleContext.attributeError(attributeName, e.getMessage());
          }
        } else {
          tokens.add(expander.expand(attributeName, token));
        }
      }
    }
    return ImmutableList.copyOf(tokens);
  }

  /** Returns the tokenized values of the copts attribute to copts. */
  // Called from CcCommon and CcSupport (Google's internal version of proto_library).
  public static ImmutableList<String> getAttributeCopts(RuleContext ruleContext) {
    String attr = "copts";
    Preconditions.checkArgument(ruleContext.getRule().isAttrDefined(attr, Type.STRING_LIST));
    List<String> unexpanded = ruleContext.attributes().get(attr, Type.STRING_LIST);
    return ImmutableList.copyOf(expandMakeVariables(ruleContext, attr, unexpanded));
  }

  // Called from CcCommon.
  static ImmutableList<String> getPackageCopts(RuleContext ruleContext) {
    List<String> unexpanded = ruleContext.getRule().getPackage().getDefaultCopts();
    return ImmutableList.copyOf(expandMakeVariables(ruleContext, "copts", unexpanded));
  }

  /** Tokenizes and expands make variables. */
  public static List<String> expandLinkopts(
      RuleContext ruleContext, String attrName, Iterable<String> values) {
    List<String> result = new ArrayList<>();
    ImmutableMap.Builder<Label, ImmutableCollection<Artifact>> builder = ImmutableMap.builder();

    if (ruleContext.attributes().has("additional_linker_inputs", LABEL_LIST)) {
      for (TransitiveInfoCollection current :
          ruleContext.getPrerequisites("additional_linker_inputs", Mode.TARGET)) {
        builder.put(
            AliasProvider.getDependencyLabel(current),
            current.getProvider(FileProvider.class).getFilesToBuild().toList());
      }
    }

    Expander expander = ruleContext.getExpander(builder.build()).withDataExecLocations();
    for (String value : values) {
      expander.tokenizeAndExpandMakeVars(result, attrName, value);
    }
    return result;
  }

  public static NestedSet<Pair<String, String>> getCoverageEnvironmentIfNeeded(
      RuleContext ruleContext, CppConfiguration cppConfiguration, CcToolchainProvider toolchain)
      throws RuleErrorException {
    if (cppConfiguration.collectCodeCoverage()) {
      NestedSetBuilder<Pair<String, String>> coverageEnvironment =
          NestedSetBuilder.<Pair<String, String>>stableOrder()
              .add(
                  Pair.of(
                      "COVERAGE_GCOV_PATH",
                      toolchain.getToolPathFragment(Tool.GCOV, ruleContext).getPathString()));
      if (cppConfiguration.getFdoInstrument() != null) {
        coverageEnvironment.add(Pair.of("FDO_DIR", cppConfiguration.getFdoInstrument()));
      }
      return coverageEnvironment.build();
    } else {
      return NestedSetBuilder.emptySet(Order.COMPILE_ORDER);
    }
  }

  public static NestedSet<Artifact> getGcovFilesIfNeeded(
      RuleContext ruleContext, CcToolchainProvider toolchain) {
    if (ruleContext.getConfiguration().isCodeCoverageEnabled()) {
      return toolchain.getCoverageFiles();
    } else {
      return NestedSetBuilder.emptySet(Order.STABLE_ORDER);
    }
  }

  /**
   * This almost trivial method looks up the default cc toolchain attribute on the rule context,
   * makes sure that it refers to a rule that has a {@link CcToolchainProvider} (gives an error
   * otherwise), and returns a reference to that {@link CcToolchainProvider}. The method only
   * returns {@code null} if there is no such attribute (this is currently not an error).
   *
   * <p>Be careful to provide explicit attribute name if the rule doesn't store cc_toolchain under
   * the default name.
   */
  @Nullable
  public static CcToolchainProvider getToolchainUsingDefaultCcToolchainAttribute(
      RuleContext ruleContext) {
    CcToolchainProvider defaultToolchain =
        getToolchain(ruleContext, CcToolchain.CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME);
    if (defaultToolchain != null) {
      return defaultToolchain;
    }
    return getToolchain(ruleContext, CcToolchain.CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME_FOR_STARLARK);
  }

  /**
   * Convenience function for finding the dynamic runtime inputs for the current toolchain. Useful
   * for non C++ rules that link against the C++ runtime.
   *
   * <p>This uses the default feature configuration. Do *not* use this method in rules that use a
   * non-default feature configuration, or risk a mismatch.
   */
  public static NestedSet<Artifact> getDefaultCcToolchainDynamicRuntimeInputs(
      RuleContext ruleContext) throws RuleErrorException {
    try {
      return getDefaultCcToolchainDynamicRuntimeInputsFromStarlark(ruleContext);
    } catch (EvalException e) {
      throw ruleContext.throwWithRuleError(e.getMessage());
    }
  }

  /**
   * Convenience function for finding the dynamic runtime inputs for the current toolchain. Useful
   * for Starlark-defined rules that link against the C++ runtime.
   *
   * <p>This uses the default feature configuration. Do *not* use this method in rules that use a
   * non-default feature configuration, or risk a mismatch.
   */
  public static NestedSet<Artifact> getDefaultCcToolchainDynamicRuntimeInputsFromStarlark(
      RuleContext ruleContext) throws EvalException {
    CcToolchainProvider defaultToolchain =
        getToolchainUsingDefaultCcToolchainAttribute(ruleContext);
    if (defaultToolchain == null) {
      return NestedSetBuilder.emptySet(Order.STABLE_ORDER);
    }
    FeatureConfiguration featureConfiguration =
        CcCommon.configureFeaturesOrReportRuleError(ruleContext, defaultToolchain);

    return defaultToolchain.getDynamicRuntimeLinkInputs(featureConfiguration);
  }

  /**
   * Convenience function for finding the static runtime inputs for the current toolchain. Useful
   * for non C++ rules that link against the C++ runtime.
   */
  public static NestedSet<Artifact> getDefaultCcToolchainStaticRuntimeInputs(
      RuleContext ruleContext) throws RuleErrorException {
    CcToolchainProvider defaultToolchain =
        getToolchainUsingDefaultCcToolchainAttribute(ruleContext);
    if (defaultToolchain == null) {
      return NestedSetBuilder.emptySet(Order.STABLE_ORDER);
    }
    FeatureConfiguration featureConfiguration =
        CcCommon.configureFeaturesOrReportRuleError(ruleContext, defaultToolchain);
    try {
      return defaultToolchain.getStaticRuntimeLinkInputs(featureConfiguration);
    } catch (EvalException e) {
      throw ruleContext.throwWithRuleError(e.getMessage());
    }
  }

  /**
   * Makes sure that the given info collection has a {@link CcToolchainProvider} (gives an error
   * otherwise), and returns a reference to that {@link CcToolchainProvider}. The method will only
   * return {@code null}, if the toolchain attribute is undefined for the rule class.
   */
  @Nullable
  public static CcToolchainProvider getToolchain(
      RuleContext ruleContext, String toolchainAttribute) {
    if (!ruleContext.isAttrDefined(toolchainAttribute, LABEL)) {
      // TODO(bazel-team): Report an error or throw an exception in this case.
      return null;
    }
    TransitiveInfoCollection dep = ruleContext.getPrerequisite(toolchainAttribute, Mode.TARGET);
    return getToolchain(ruleContext, dep);
  }

  /**
   * Makes sure that the given info collection has a {@link CcToolchainProvider} (gives an error
   * otherwise), and returns a reference to that {@link CcToolchainProvider}. The method never
   * returns {@code null}, even if there is no toolchain.
   */
  public static CcToolchainProvider getToolchain(
      RuleContext ruleContext, TransitiveInfoCollection dep) {
    Label toolchainType = getToolchainTypeFromRuleClass(ruleContext);
    return getToolchain(ruleContext, dep, toolchainType);
  }

  public static CcToolchainProvider getToolchain(
      RuleContext ruleContext, TransitiveInfoCollection dep, Label toolchainType) {
    if (toolchainType != null && useToolchainResolution(ruleContext)) {
      return getToolchainFromPlatformConstraints(ruleContext, toolchainType);
    }
    return getToolchainFromCrosstoolTop(ruleContext, dep);
  }

  /** Returns the c++ toolchain type, or null if it is not specified on the rule class. */
  public static Label getToolchainTypeFromRuleClass(RuleContext ruleContext) {
    Label toolchainType;
    // TODO(b/65835260): Remove this conditional once j2objc can learn the toolchain type.
    if (ruleContext.attributes().has(CcToolchain.CC_TOOLCHAIN_TYPE_ATTRIBUTE_NAME)) {
      toolchainType =
          ruleContext.attributes().get(CcToolchain.CC_TOOLCHAIN_TYPE_ATTRIBUTE_NAME, NODEP_LABEL);
    } else {
      toolchainType = null;
    }
    return toolchainType;
  }

  private static CcToolchainProvider getToolchainFromPlatformConstraints(
      RuleContext ruleContext, Label toolchainType) {
    return (CcToolchainProvider) ruleContext.getToolchainContext().forToolchainType(toolchainType);
  }

  private static CcToolchainProvider getToolchainFromCrosstoolTop(
      RuleContext ruleContext, TransitiveInfoCollection dep) {
    // TODO(bazel-team): Consider checking this generally at the attribute level.
    if ((dep == null) || (dep.get(ToolchainInfo.PROVIDER) == null)) {
      ruleContext.ruleError("The selected C++ toolchain is not a cc_toolchain rule");
      return CcToolchainProvider.EMPTY_TOOLCHAIN_IS_ERROR;
    }
    return (CcToolchainProvider) dep.get(ToolchainInfo.PROVIDER);
  }

  /** Returns the directory where object files are created. */
  public static PathFragment getObjDirectory(Label ruleLabel, boolean usePic) {
    if (usePic) {
      return AnalysisUtils.getUniqueDirectory(ruleLabel, PIC_OBJS);
    } else {
      return AnalysisUtils.getUniqueDirectory(ruleLabel, OBJS);
    }
  }

  /** Returns the directory where object files are created. */
  private static PathFragment getDotdDirectory(Label ruleLabel, boolean usePic) {
    return AnalysisUtils.getUniqueDirectory(ruleLabel, usePic ? PIC_DOTD_FILES : DOTD_FILES);
  }

  /** Returns the directory where object files are created. */
  public static PathFragment getObjDirectory(Label ruleLabel) {
    return getObjDirectory(ruleLabel, false);
  }

  /**
   * Returns a function that gets the C++ runfiles from a {@link TransitiveInfoCollection} or the
   * empty runfiles instance if it does not contain that provider.
   */
  public static final Function<TransitiveInfoCollection, Runfiles> runfilesFunction(
      RuleContext ruleContext, boolean linkingStatically) {
    final Function<TransitiveInfoCollection, Runfiles> runfilesForLinkingDynamically =
        input -> {
          CcInfo provider = input.get(CcInfo.PROVIDER);
          if (provider == null) {
            return Runfiles.EMPTY;
          } else {
            // Cannot add libraries directly because the nested set has link order.
            NestedSet<Artifact> dynamicLibrariesForRuntime =
                NestedSetBuilder.<Artifact>stableOrder()
                    .addAll(
                        provider
                            .getCcLinkingContext()
                            .getDynamicLibrariesForRuntime(/* linkingStatically= */ false))
                    .build();
            return new Runfiles.Builder(ruleContext.getWorkspaceName())
                .addTransitiveArtifacts(dynamicLibrariesForRuntime)
                .build();
          }
        };

    final Function<TransitiveInfoCollection, Runfiles> runfilesForLinkingStatically =
        input -> {
          CcInfo provider = input.get(CcInfo.PROVIDER);
          if (provider == null) {
            return Runfiles.EMPTY;
          } else {
            // Cannot add libraries directly because the nested set has link order.
            NestedSet<Artifact> dynamicLibrariesForRuntime =
                NestedSetBuilder.<Artifact>stableOrder()
                    .addAll(
                        provider
                            .getCcLinkingContext()
                            .getDynamicLibrariesForRuntime(/* linkingStatically= */ true))
                    .build();
            return new Runfiles.Builder(ruleContext.getWorkspaceName())
                .addTransitiveArtifacts(dynamicLibrariesForRuntime)
                .build();
          }
        };
    return linkingStatically ? runfilesForLinkingStatically : runfilesForLinkingDynamically;
  }

  /**
   * Returns the linked artifact.
   *
   * @param ruleContext the ruleContext to be used to scope the artifact
   * @param config the configuration to be used to scope the artifact
   * @param linkType the type of artifact, used to determine extension
   */
  public static Artifact getLinkedArtifact(
      RuleContext ruleContext,
      CcToolchainProvider ccToolchain,
      BuildConfiguration config,
      LinkTargetType linkType)
      throws RuleErrorException {
    return getLinkedArtifact(
        ruleContext, ccToolchain, config, linkType, /* linkedArtifactNameSuffix= */ "");
  }

  /** Returns the linked artifact with the given suffix. */
  public static Artifact getLinkedArtifact(
      RuleContext ruleContext,
      CcToolchainProvider ccToolchain,
      BuildConfiguration config,
      LinkTargetType linkType,
      String linkedArtifactNameSuffix)
      throws RuleErrorException {
    PathFragment name = PathFragment.create(ruleContext.getLabel().getName());
    try {
      name =
          name.replaceName(
              getArtifactNameForCategory(
                  ruleContext,
                  ccToolchain,
                  linkType.getLinkerOutput(),
                  name.getBaseName()
                      + linkedArtifactNameSuffix
                      + linkType.getPicExtensionWhenApplicable()));
    } catch (RuleErrorException e) {
      ruleContext.throwWithRuleError("Cannot get linked artifact name: " + e.getMessage());
    }

    return getLinkedArtifact(
        ruleContext.getLabel(), ruleContext, config, linkType, linkedArtifactNameSuffix, name);
  }

  public static Artifact getLinkedArtifact(
      Label label,
      ActionConstructionContext actionConstructionContext,
      BuildConfiguration config,
      LinkTargetType linkType,
      String linkedArtifactNameSuffix,
      PathFragment name) {
    Artifact result =
        actionConstructionContext.getPackageRelativeArtifact(
            name, config.getBinDirectory(label.getPackageIdentifier().getRepository()));

    // If the linked artifact is not the linux default, then a FailAction is generated for said
    // linux default to satisfy the requirements of any implicit outputs.
    // TODO(b/30132703): Remove the implicit outputs of cc_library.
    Artifact linuxDefault =
        getLinuxLinkedArtifact(
            label, actionConstructionContext, config, linkType, 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",
                  result.getExecPathString(), linuxDefault.getExecPathString())));
    }

    return result;
  }

  public static Artifact getLinuxLinkedArtifact(
      Label label,
      ActionConstructionContext actionConstructionContext,
      BuildConfiguration config,
      LinkTargetType linkType,
      String linkedArtifactNameSuffix) {
    PathFragment name = PathFragment.create(label.getName());
    if (linkType != LinkTargetType.EXECUTABLE) {
      name =
          name.replaceName(
              "lib"
                  + name.getBaseName()
                  + linkedArtifactNameSuffix
                  + linkType.getPicExtensionWhenApplicable()
                  + linkType.getDefaultExtension());
    }

    return actionConstructionContext.getPackageRelativeArtifact(
        name, config.getBinDirectory(label.getPackageIdentifier().getRepository()));
  }

  /**
   * Emits a warning on the rule if there are identical linkstamp artifacts with different {@code
   * CcCompilationContext}s.
   */
  public static void checkLinkstampsUnique(
      RuleErrorConsumer listener, Iterable<Linkstamp> linkstamps) {
    Map<Artifact, NestedSet<Artifact>> result = new LinkedHashMap<>();
    for (Linkstamp pair : linkstamps) {
      Artifact artifact = pair.getArtifact();
      if (result.containsKey(artifact)) {
        listener.ruleWarning(
            "rule inherits the '"
                + artifact.toDetailString()
                + "' linkstamp file from more than one cc_library rule");
      }
      result.put(artifact, pair.getDeclaredIncludeSrcs());
    }
  }

  // TODO(bazel-team): figure out a way to merge these 2 methods. See the Todo in
  // CcCommonConfiguredTarget.noCoptsMatches().

  /** Returns whether binaries must be compiled with position independent code. */
  public static boolean usePicForBinaries(
      CcToolchainProvider toolchain,
      CppConfiguration cppConfiguration,
      FeatureConfiguration featureConfiguration) {
    return cppConfiguration.forcePic()
        || (toolchain.usePicForDynamicLibraries(cppConfiguration, featureConfiguration)
            && cppConfiguration.getCompilationMode() != CompilationMode.OPT);
  }

  /**
   * Creates a CppModuleMap object for pure c++ builds. The module map artifact becomes a candidate
   * input to a CppCompileAction.
   */
  public static CppModuleMap createDefaultCppModuleMap(
      ActionConstructionContext actionConstructionContext,
      BuildConfiguration configuration,
      Label label,
      String suffix) {
    // Create the module map artifact as a genfile.
    Artifact mapFile =
        actionConstructionContext.getPackageRelativeArtifact(
            PathFragment.create(
                label.getName()
                    + suffix
                    + Iterables.getOnlyElement(CppFileTypes.CPP_MODULE_MAP.getExtensions())),
            configuration.getGenfilesDirectory(label.getPackageIdentifier().getRepository()));
    return new CppModuleMap(mapFile, label.toString());
  }

  /**
   * Returns a middleman for all files to build for the given configured target, substituting shared
   * library artifacts with corresponding solib symlinks. If multiple calls are made, then it
   * returns the same artifact for configurations with the same internal directory.
   *
   * <p>The resulting middleman only aggregates the inputs and must be expanded before populating
   * the set of files necessary to execute an action.
   */
  static List<Artifact> getAggregatingMiddlemanForCppRuntimes(
      RuleContext ruleContext,
      String purpose,
      NestedSet<Artifact> artifacts,
      String solibDir,
      String solibDirOverride,
      BuildConfiguration configuration) {
    return getMiddlemanInternal(
        ruleContext,
        ruleContext.getActionOwner(),
        purpose,
        artifacts,
        true,
        true,
        solibDir,
        solibDirOverride,
        configuration);
  }

  @VisibleForTesting
  public static List<Artifact> getAggregatingMiddlemanForTesting(
      RuleContext ruleContext,
      ActionOwner owner,
      String purpose,
      NestedSet<Artifact> artifacts,
      boolean useSolibSymlinks,
      String solibDir,
      BuildConfiguration configuration) {
    return getMiddlemanInternal(
        ruleContext,
        owner,
        purpose,
        artifacts,
        useSolibSymlinks,
        false,
        solibDir,
        null,
        configuration);
  }

  /** Internal implementation for getAggregatingMiddlemanForCppRuntimes. */
  private static List<Artifact> getMiddlemanInternal(
      RuleContext ruleContext,
      ActionOwner actionOwner,
      String purpose,
      NestedSet<Artifact> artifacts,
      boolean useSolibSymlinks,
      boolean isCppRuntime,
      String solibDir,
      String solibDirOverride,
      BuildConfiguration configuration) {
    MiddlemanFactory factory = ruleContext.getAnalysisEnvironment().getMiddlemanFactory();
    if (useSolibSymlinks) {
      NestedSetBuilder<Artifact> symlinkedArtifacts = NestedSetBuilder.stableOrder();
      for (Artifact artifact : artifacts.toList()) {
        Preconditions.checkState(Link.SHARED_LIBRARY_FILETYPES.matches(artifact.getFilename()));
        symlinkedArtifacts.add(
            isCppRuntime
                ? SolibSymlinkAction.getCppRuntimeSymlink(
                    ruleContext, artifact, solibDir, solibDirOverride)
                : SolibSymlinkAction.getDynamicLibrarySymlink(
                    /* actionRegistry= */ ruleContext,
                    /* actionConstructionContext= */ ruleContext,
                    solibDir,
                    artifact,
                    /* preserveName= */ false,
                    /* prefixConsumer= */ true));
      }
      artifacts = symlinkedArtifacts.build();
      purpose += "_with_solib";
    }
    return ImmutableList.of(
        factory.createMiddlemanAllowMultiple(
            ruleContext.getAnalysisEnvironment(),
            actionOwner,
            ruleContext.getPackageDirectory(),
            purpose,
            artifacts,
            configuration.getMiddlemanDirectory(ruleContext.getRule().getRepository())));
  }

  /** Returns the FDO build subtype. */
  public static String getFdoBuildStamp(
      CppConfiguration cppConfiguration,
      FdoContext fdoContext,
      FeatureConfiguration featureConfiguration) {
    FdoContext.BranchFdoProfile branchFdoProfile = fdoContext.getBranchFdoProfile();
    if (branchFdoProfile != null) {

      if (branchFdoProfile.isAutoFdo()) {
        return featureConfiguration.isEnabled(CppRuleClasses.AUTOFDO) ? "AFDO" : null;
      }
      if (branchFdoProfile.isAutoXBinaryFdo()) {
        return featureConfiguration.isEnabled(CppRuleClasses.XBINARYFDO) ? "XFDO" : null;
      }
    }
    if (cppConfiguration.isCSFdo()) {
      return "CSFDO";
    }
    if (cppConfiguration.isFdo()) {
      return "FDO";
    }
    return null;
  }

  /** Creates an action to strip an executable. */
  public static void createStripAction(
      RuleContext ruleContext,
      CcToolchainProvider toolchain,
      CppConfiguration cppConfiguration,
      Artifact input,
      Artifact output,
      FeatureConfiguration featureConfiguration)
      throws RuleErrorException {
    if (featureConfiguration.isEnabled(CppRuleClasses.NO_STRIPPING)) {
      ruleContext.registerAction(
          SymlinkAction.toArtifact(
              ruleContext.getActionOwner(),
              input,
              output,
              "Symlinking original binary as stripped binary"));
      return;
    }

    if (!featureConfiguration.actionIsConfigured(CppActionNames.STRIP)) {
      ruleContext.ruleError("Expected action_config for 'strip' to be configured.");
      return;
    }

    CcToolchainVariables variables =
        CcToolchainVariables.builder(
                toolchain.getBuildVariables(
                    ruleContext.getConfiguration().getOptions(), cppConfiguration))
            .addStringVariable(
                StripBuildVariables.OUTPUT_FILE.getVariableName(), output.getExecPathString())
            .addStringSequenceVariable(
                StripBuildVariables.STRIPOPTS.getVariableName(), cppConfiguration.getStripOpts())
            .addStringVariable(CcCommon.INPUT_FILE_VARIABLE_NAME, input.getExecPathString())
            .build();
    ImmutableList<String> commandLine =
        getCommandLine(ruleContext, featureConfiguration, variables, CppActionNames.STRIP);
    ImmutableMap.Builder<String, String> executionInfoBuilder = ImmutableMap.builder();
    for (String executionRequirement :
        featureConfiguration.getToolRequirementsForAction(CppActionNames.STRIP)) {
      executionInfoBuilder.put(executionRequirement, "");
    }
    Action[] stripAction =
        new SpawnAction.Builder()
            .addInput(input)
            .addTransitiveInputs(toolchain.getStripFiles())
            .addOutput(output)
            .useDefaultShellEnvironment()
            .setExecutable(
                PathFragment.create(
                    featureConfiguration.getToolPathForAction(CppActionNames.STRIP)))
            .setExecutionInfo(executionInfoBuilder.build())
            .setProgressMessage("Stripping %s for %s", output.prettyPrint(), ruleContext.getLabel())
            .setMnemonic("CcStrip")
            .addCommandLine(CustomCommandLine.builder().addAll(commandLine).build())
            .build(ruleContext);
    ruleContext.registerAction(stripAction);
  }

  public static ImmutableList<String> getCommandLine(
      RuleErrorConsumer ruleErrorConsumer,
      FeatureConfiguration featureConfiguration,
      CcToolchainVariables variables,
      String actionName)
      throws RuleErrorException {
    try {
      return ImmutableList.copyOf(featureConfiguration.getCommandLine(actionName, variables));
    } catch (ExpansionException e) {
      throw ruleErrorConsumer.throwWithRuleError(e.getMessage());
    }
  }

  public static ImmutableMap<String, String> getEnvironmentVariables(
      RuleErrorConsumer ruleErrorConsumer,
      FeatureConfiguration featureConfiguration,
      CcToolchainVariables variables,
      String actionName)
      throws RuleErrorException {
    try {
      return featureConfiguration.getEnvironmentVariables(actionName, variables);
    } catch (ExpansionException e) {
      throw ruleErrorConsumer.throwWithRuleError(e.getMessage());
    }
  }

  public static void maybeAddStaticLinkMarkerProvider(
      RuleConfiguredTargetBuilder builder, RuleContext ruleContext) {
    if (ruleContext.getFeatures().contains("fully_static_link")) {
      builder.add(StaticallyLinkedMarkerProvider.class, new StaticallyLinkedMarkerProvider(true));
    }
  }

  static Artifact getCompileOutputArtifact(
      ActionConstructionContext actionConstructionContext,
      Label label,
      String outputName,
      BuildConfiguration config) {
    PathFragment objectDir = getObjDirectory(label);
    return actionConstructionContext.getDerivedArtifact(
        objectDir.getRelative(outputName),
        config.getBinDirectory(label.getPackageIdentifier().getRepository()));
  }

  /** Returns the corresponding compiled TreeArtifact given the source TreeArtifact. */
  public static SpecialArtifact getCompileOutputTreeArtifact(
      ActionConstructionContext actionConstructionContext,
      Label label,
      Artifact sourceTreeArtifact,
      String outputName,
      boolean usePic) {
    return actionConstructionContext.getTreeArtifact(
        getObjDirectory(label, usePic).getRelative(outputName), sourceTreeArtifact.getRoot());
  }

  /** Returns the corresponding dotd files TreeArtifact given the source TreeArtifact. */
  public static SpecialArtifact getDotdOutputTreeArtifact(
      ActionConstructionContext actionConstructionContext,
      Label label,
      Artifact sourceTreeArtifact,
      String outputName,
      boolean usePic) {
    return actionConstructionContext.getTreeArtifact(
        getDotdDirectory(label, usePic).getRelative(outputName), sourceTreeArtifact.getRoot());
  }

  public static String getArtifactNameForCategory(
      RuleErrorConsumer ruleErrorConsumer,
      CcToolchainProvider toolchain,
      ArtifactCategory category,
      String outputName)
      throws RuleErrorException {
    try {
      return toolchain.getFeatures().getArtifactNameForCategory(category, outputName);
    } catch (EvalException e) {
      ruleErrorConsumer.throwWithRuleError(e.getMessage());
      throw new IllegalStateException("Should not be reached");
    }
  }

  static String getDotdFileName(
      RuleErrorConsumer ruleErrorConsumer,
      CcToolchainProvider toolchain,
      ArtifactCategory outputCategory,
      String outputName)
      throws RuleErrorException {
    String baseName =
        outputCategory == ArtifactCategory.OBJECT_FILE
                || outputCategory == ArtifactCategory.PROCESSED_HEADER
            ? outputName
            : getArtifactNameForCategory(ruleErrorConsumer, toolchain, outputCategory, outputName);

    return getArtifactNameForCategory(
        ruleErrorConsumer, toolchain, ArtifactCategory.INCLUDED_FILE_LIST, baseName);
  }

  /**
   * Returns true when {@link CppRuleClasses#WINDOWS_EXPORT_ALL_SYMBOLS} feature is enabled and
   * {@link CppRuleClasses#NO_WINDOWS_EXPORT_ALL_SYMBOLS} feature is not enabled and no custom DEF
   * file is specified in win_def_file attribute.
   */
  public static boolean shouldUseGeneratedDefFile(
      RuleContext ruleContext, FeatureConfiguration featureConfiguration) {
    return featureConfiguration.isEnabled(CppRuleClasses.WINDOWS_EXPORT_ALL_SYMBOLS)
        && !featureConfiguration.isEnabled(CppRuleClasses.NO_WINDOWS_EXPORT_ALL_SYMBOLS)
        && ruleContext.getPrerequisiteArtifact("win_def_file", Mode.TARGET) == null;
  }

  /**
   * Create actions for parsing object files to generate a DEF file, should only be used when
   * targeting Windows.
   *
   * @param defParser The tool we use to parse object files for generating the DEF file.
   * @param objectFiles A list of object files to parse
   * @param dllName The DLL name to be written into the DEF file, it specifies which DLL is required
   *     at runtime
   * @return The DEF file artifact.
   */
  public static Artifact createDefFileActions(
      RuleContext ruleContext,
      Artifact defParser,
      ImmutableList<Artifact> objectFiles,
      String dllName) {
    Artifact defFile =
        ruleContext.getBinArtifact(
            ruleContext.getLabel().getName()
                + ".gen"
                + Iterables.getOnlyElement(CppFileTypes.WINDOWS_DEF_FILE.getExtensions()));
    CustomCommandLine.Builder argv = new CustomCommandLine.Builder();
    for (Artifact objectFile : objectFiles) {
      argv.addDynamicString(objectFile.getExecPathString());
    }

    ruleContext.registerAction(
        new SpawnAction.Builder()
            .addInputs(objectFiles)
            .addOutput(defFile)
            .setExecutable(defParser)
            .useDefaultShellEnvironment()
            .addCommandLine(
                CustomCommandLine.builder().addExecPath(defFile).addDynamicString(dllName).build())
            .addCommandLine(
                argv.build(),
                ParamFileInfo.builder(ParameterFile.ParameterFileType.SHELL_QUOTED)
                    .setCharset(UTF_8)
                    .setUseAlways(true)
                    .build())
            .setMnemonic("DefParser")
            .build(ruleContext));
    return defFile;
  }

  /**
   * Create action for generating an empty DEF file without any exports, should only be used when
   * targeting Windows.
   *
   * @return The artifact of an empty DEF file.
   */
  private static Artifact createEmptyDefFileAction(RuleContext ruleContext) {
    Artifact trivialDefFile =
        ruleContext.getBinArtifact(
            ruleContext.getLabel().getName()
                + ".gen.empty"
                + Iterables.getOnlyElement(CppFileTypes.WINDOWS_DEF_FILE.getExtensions()));
    ruleContext.registerAction(FileWriteAction.create(ruleContext, trivialDefFile, "", false));
    return trivialDefFile;
  }

  /**
   * Decide which DEF file should be used for the linking action.
   *
   * @return The artifact of the DEF file that should be used for the linking action.
   */
  public static Artifact getWindowsDefFileForLinking(
      RuleContext ruleContext,
      Artifact customDefFile,
      Artifact generatedDefFile,
      FeatureConfiguration featureConfiguration) {
    // 1. If a custom DEF file is specified in win_def_file attribute, use it.
    // 2. If a generated DEF file is available and should be used, use it.
    // 3. Otherwise, we use an empty DEF file to ensure the import library will be generated.
    if (customDefFile != null) {
      return customDefFile;
    } else if (generatedDefFile != null
        && CppHelper.shouldUseGeneratedDefFile(ruleContext, featureConfiguration)) {
      return generatedDefFile;
    } else {
      return createEmptyDefFileAction(ruleContext);
    }
  }

  /**
   * Returns true if the build implied by the given config and toolchain uses --start-lib/--end-lib
   * ld options.
   */
  public static boolean useStartEndLib(
      CppConfiguration config,
      CcToolchainProvider toolchain,
      FeatureConfiguration featureConfiguration) {
    return config.startEndLibIsRequested() && toolchain.supportsStartEndLib(featureConfiguration);
  }

  /**
   * Returns the type of archives being used by the build implied by the given config and toolchain.
   */
  public static Link.ArchiveType getArchiveType(
      CppConfiguration config,
      CcToolchainProvider toolchain,
      FeatureConfiguration featureConfiguration) {
    return useStartEndLib(config, toolchain, featureConfiguration)
        ? Link.ArchiveType.START_END_LIB
        : Link.ArchiveType.REGULAR;
  }

  /**
   * Returns true if interface shared objects should be used in the build implied by the given
   * cppConfiguration and toolchain.
   */
  public static boolean useInterfaceSharedLibraries(
      CppConfiguration cppConfiguration,
      CcToolchainProvider toolchain,
      FeatureConfiguration featureConfiguration) {
    return toolchain.supportsInterfaceSharedLibraries(featureConfiguration)
        && cppConfiguration.getUseInterfaceSharedLibraries();
  }

  public static CcNativeLibraryProvider collectNativeCcLibraries(
      List<? extends TransitiveInfoCollection> deps, List<LibraryToLink> libraries) {
    NestedSetBuilder<LibraryToLink> result = NestedSetBuilder.linkOrder();
    result.addAll(libraries);
    for (CcNativeLibraryProvider dep :
        AnalysisUtils.getProviders(deps, CcNativeLibraryProvider.class)) {
      result.addTransitive(dep.getTransitiveCcNativeLibraries());
    }
    return new CcNativeLibraryProvider(result.build());
  }

  public static void checkProtoLibrariesInDeps(
      RuleErrorConsumer ruleErrorConsumer, Iterable<TransitiveInfoCollection> deps) {
    for (TransitiveInfoCollection dep : deps) {
      if (dep.get(ProtoInfo.PROVIDER) != null && dep.get(CcInfo.PROVIDER) == null) {
        ruleErrorConsumer.attributeError(
            "deps",
            String.format("proto_library '%s' does not produce output for C++", dep.getLabel()));
      }
    }
  }

  static boolean useToolchainResolution(RuleContext ruleContext) {
    CppOptions cppOptions =
        Preconditions.checkNotNull(
            ruleContext.getConfiguration().getOptions().get(CppOptions.class));

    return cppOptions.enableCcToolchainResolution;
  }

  public static ImmutableList<CcCompilationContext> getCompilationContextsFromDeps(
      List<TransitiveInfoCollection> deps) {
    return Streams.stream(AnalysisUtils.getProviders(deps, CcInfo.PROVIDER))
        .map(CcInfo::getCcCompilationContext)
        .collect(ImmutableList.toImmutableList());
  }

  public static CcDebugInfoContext mergeCcDebugInfoContexts(
      CcCompilationOutputs compilationOutputs, Iterable<CcInfo> deps) {
    ImmutableList.Builder<CcDebugInfoContext> contexts = ImmutableList.builder();
    for (CcInfo ccInfo : deps) {
      contexts.add(ccInfo.getCcDebugInfoContext());
    }
    contexts.add(CcDebugInfoContext.from(compilationOutputs));
    return CcDebugInfoContext.merge(contexts.build());
  }

  public static ImmutableList<CcLinkingContext> getLinkingContextsFromDeps(
      ImmutableList<TransitiveInfoCollection> deps) {
    return Streams.stream(AnalysisUtils.getProviders(deps, CcInfo.PROVIDER))
        .map(CcInfo::getCcLinkingContext)
        .collect(ImmutableList.toImmutableList());
  }

  public static ImmutableList<CcDebugInfoContext> getDebugInfoContextsFromDeps(
      List<TransitiveInfoCollection> deps) {
    return Streams.stream(AnalysisUtils.getProviders(deps, CcInfo.PROVIDER))
        .map(CcInfo::getCcDebugInfoContext)
        .collect(ImmutableList.toImmutableList());
  }

  public static Artifact getGrepIncludes(RuleContext ruleContext) {
    return ruleContext.attributes().has("$grep_includes")
        ? ruleContext.getPrerequisiteArtifact("$grep_includes", Mode.HOST)
        : null;
  }

  public static boolean doNotSplitLinkingCmdLine(
      StarlarkSemantics starlarkSemantics, CcToolchainProvider ccToolchain) {
    return starlarkSemantics.incompatibleDoNotSplitLinkingCmdline()
        || ccToolchain.doNotSplitLinkingCmdline();
  }
}
