// Copyright 2017 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.common.base.Preconditions.checkNotNull;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
import com.google.devtools.build.lib.actions.ActionExecutionContext;
import com.google.devtools.build.lib.actions.ActionExecutionException;
import com.google.devtools.build.lib.actions.ActionKeyCacher;
import com.google.devtools.build.lib.actions.ActionKeyContext;
import com.google.devtools.build.lib.actions.ActionLookupKey;
import com.google.devtools.build.lib.actions.ActionOwner;
import com.google.devtools.build.lib.actions.ActionTemplate;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
import com.google.devtools.build.lib.actions.CommandLineExpansionException;
import com.google.devtools.build.lib.actions.MiddlemanType;
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.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.server.FailureDetails;
import com.google.devtools.build.lib.util.DetailedExitCode;
import com.google.devtools.build.lib.util.FileType;
import com.google.devtools.build.lib.util.Fingerprint;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.PathFragment;
import javax.annotation.Nullable;

/**
 * An {@link ActionTemplate} that expands into {@link LtoBackendAction}s at execution time. Is is
 * similar to {@link com.google.devtools.build.lib.analysis.actions.SpawnActionTemplate}.
 */
public final class LtoBackendActionTemplate extends ActionKeyCacher
    implements ActionTemplate<LtoBackendAction> {
  private final LtoBackendAction.Builder ltoBackendActionbuilder;
  private final CcToolchainVariables buildVariables;

  // An input tree artifact containing the full bitcode. It is never null.
  private final SpecialArtifact fullBitcodeTreeArtifact;

  // An input tree artifact containing ".thinlto.bc" and ".imports" files, generated together with
  // It will be null when this is a shared non-lto backend.
  @Nullable private final SpecialArtifact indexAndImportsTreeArtifact;

  // An output tree artifact that will contain the native objects. In a sibling directory to
  // indexTreeArtifact. The objects will be generated in the same location as defined in the .param
  // file created during the lto indexing step.
  private final SpecialArtifact objectFileTreeArtifact;

  // The corresponding dwoFile if fission is used.
  private final SpecialArtifact dwoFileTreeArtifact;

  private final FeatureConfiguration featureConfiguration;

  private final boolean usePic;

  private final BitcodeFiles bitcodeFiles;

  private final ActionOwner actionOwner;
  private final NestedSet<Artifact> mandatoryInputs;
  private final NestedSet<Artifact> allInputs;

  /**
   * Creates an LtoBackendActionTemplate.
   *
   * @param indexAndImportsTreeArtifact the TreeArtifact that contains .thinlto.bc. and .imports
   *     files.
   * @param fullBitcodeTreeArtifact the TreeArtifact that contains .pic.o files.
   * @param objectFileTreeArtifact the TreeArtifact that contains .pic.o files.
   * @param dwoFileTreeArtifact the TreeArtifact that contains .dwo files.
   * @param featureConfiguration the feature configuration.
   * @param ltoBackendActionbuilder An almost completely configured {@link LtoBackendAction.Builder}
   *     without the input and output files set. It is used as a template to instantiate expanded
   *     {@link LtoBackendAction}s.
   * @param buildVariables the building variables.
   * @param usePic whether to use PIC or not.
   * @param actionOwner the owner of this {@link ActionTemplate}.
   */
  LtoBackendActionTemplate(
      SpecialArtifact indexAndImportsTreeArtifact,
      SpecialArtifact fullBitcodeTreeArtifact,
      SpecialArtifact objectFileTreeArtifact,
      SpecialArtifact dwoFileTreeArtifact,
      FeatureConfiguration featureConfiguration,
      LtoBackendAction.Builder ltoBackendActionbuilder,
      CcToolchainVariables buildVariables,
      boolean usePic,
      BitcodeFiles bitcodeFiles,
      ActionOwner actionOwner) {
    this.ltoBackendActionbuilder = ltoBackendActionbuilder;
    this.buildVariables = buildVariables;
    this.indexAndImportsTreeArtifact = indexAndImportsTreeArtifact;
    this.fullBitcodeTreeArtifact = fullBitcodeTreeArtifact;
    this.objectFileTreeArtifact = objectFileTreeArtifact;
    this.dwoFileTreeArtifact = dwoFileTreeArtifact;
    this.actionOwner = checkNotNull(actionOwner, objectFileTreeArtifact);
    this.featureConfiguration = featureConfiguration;
    this.usePic = usePic;
    this.bitcodeFiles = bitcodeFiles;

    NestedSetBuilder<Artifact> mandatoryInputsBuilder =
        NestedSetBuilder.<Artifact>compileOrder()
            .add(fullBitcodeTreeArtifact)
            .addTransitive(ltoBackendActionbuilder.getInputsAndTools());
    if (indexAndImportsTreeArtifact != null) {
      mandatoryInputsBuilder.add(indexAndImportsTreeArtifact);
    }
    this.mandatoryInputs = mandatoryInputsBuilder.build();
    this.allInputs = mandatoryInputs;
  }

  /** Helper functions for generateActionsForInputArtifacts */
  private String pathFragmentToRelativePath(PathFragment parentPath, PathFragment path) {
    return path.relativeTo(parentPath).getSafePathString();
  }

  private String removeImportsExtension(String path) {
    return FileSystemUtils.removeExtension(path);
  }

  private String removeThinltoBcExtension(String path) {
    return FileSystemUtils.removeExtension(FileSystemUtils.removeExtension(path));
  }

  /**
   * Given all the files inside indexAndImportsTreeArtifact, we find the corresponding index and
   * imports files. Then we use their path together with the fullBitcodeTreeArtifact path to derive
   * the path of the original full bitcode file. Then for each imports file, we create an lto
   * backend action that depends on that import file, on the corresponding index file, and on the
   * whole fullBitcodeTreeArtifact, which it uses to find the full bitcode file. TODO(antunesi):
   * make the generated action depend only on the corresponding full bitcode file rather than depend
   * on the whole tree artifact that contains the full bitcode file.
   */
  @Override
  public ImmutableList<LtoBackendAction> generateActionsForInputArtifacts(
      ImmutableSet<TreeFileArtifact> inputTreeFileArtifacts, ActionLookupKey artifactOwner)
      throws ActionExecutionException {
    ImmutableList.Builder<LtoBackendAction> expandedActions = new ImmutableList.Builder<>();

    final FileType thinltoBcSourceType = CppFileTypes.LTO_INDEXING_ANALYSIS_FILE;
    final FileType importsType = CppFileTypes.LTO_IMPORTS_FILE;

    ImmutableList.Builder<TreeFileArtifact> importsBuilder = ImmutableList.builder();
    ImmutableMap.Builder<String, TreeFileArtifact> nameToThinLtoBuilder =
        new ImmutableMap.Builder<>();

    PathFragment indexAndImportParentPath = indexAndImportsTreeArtifact.getExecPath();

    for (TreeFileArtifact inputTreeFileArtifact : inputTreeFileArtifacts) {
      PathFragment path = inputTreeFileArtifact.getExecPath();
      boolean isThinLto = thinltoBcSourceType.matches(path);
      boolean isImport = importsType.matches(path);

      if (isThinLto) {
        String thinLtoNoExtension =
            removeThinltoBcExtension(pathFragmentToRelativePath(indexAndImportParentPath, path));
        nameToThinLtoBuilder.put(thinLtoNoExtension, inputTreeFileArtifact);
      } else if (isImport) {
        importsBuilder.add(inputTreeFileArtifact);
      } else {
        String message =
            String.format(
                "Artifact '%s' expanded from the directory artifact '%s' is neither imports nor"
                    + " thinlto .",
                inputTreeFileArtifact.getExecPathString(),
                fullBitcodeTreeArtifact.getExecPathString()); // kinda wrong, should be index
        throw new ActionExecutionException(
            message, this, /* catastrophe= */ false, makeDetailedExitCode(message));
      }
    }

    // Maps each imports to a .bc file
    ImmutableList<TreeFileArtifact> imports = importsBuilder.build();
    ImmutableMap<String, TreeFileArtifact> nameToThinLto = nameToThinLtoBuilder.buildOrThrow();
    if (imports.size() != nameToThinLto.size()) {
      String message =
          String.format(
              "Either both or neither bitcodeFiles and imports files should be null. %s %s" + ".",
              inputTreeFileArtifacts,
              fullBitcodeTreeArtifact.getExecPathString()); // kinda wrong, should be index
      throw new ActionExecutionException(
          message, this, /* catastrophe= */ false, makeDetailedExitCode(message));
    }

    for (TreeFileArtifact importFile : imports) {
      PathFragment path = importFile.getExecPath();
      String relativePathNoExtension =
          removeImportsExtension(pathFragmentToRelativePath(indexAndImportParentPath, path));
      TreeFileArtifact thinLtoFile = nameToThinLto.get(relativePathNoExtension);
      PathFragment fullBitcodePath =
          fullBitcodeTreeArtifact.getExecPath().getRelative(relativePathNoExtension);
      String outputName = relativePathNoExtension;
      TreeFileArtifact objTreeFileArtifact =
          TreeFileArtifact.createTemplateExpansionOutput(
              objectFileTreeArtifact, outputName, artifactOwner);
      TreeFileArtifact dwoFileArtifact = null;
      if (dwoFileTreeArtifact != null) {
        dwoFileArtifact =
            TreeFileArtifact.createTemplateExpansionOutput(
                dwoFileTreeArtifact,
                FileSystemUtils.replaceExtension(
                    PathFragment.create(relativePathNoExtension), ".dwo"),
                artifactOwner);
      }
      LtoBackendAction.Builder builderCopy = new LtoBackendAction.Builder(ltoBackendActionbuilder);

      LtoBackendArtifacts.addArtifactsLtoBackendAction(
          builderCopy,
          buildVariables,
          featureConfiguration,
          thinLtoFile,
          importFile,
          fullBitcodeTreeArtifact,
          objTreeFileArtifact,
          bitcodeFiles,
          dwoFileArtifact,
          usePic,
          fullBitcodePath.toString(),
          /* isDummyAction= */ false);
      expandedActions.add((LtoBackendAction) builderCopy.buildForActionTemplate(actionOwner));
    }

    return expandedActions.build();
  }

  @Override
  protected void computeKey(
      ActionKeyContext actionKeyContext,
      @Nullable Artifact.ArtifactExpander artifactExpander,
      Fingerprint fp)
      throws CommandLineExpansionException, InterruptedException {

    LtoBackendAction dummyAction = getDummyAction();
    dummyAction.computeKey(actionKeyContext, artifactExpander, fp);
  }

  /**
   * This is an action that is not valid, because its input bitcode file is a TreeArtifact rather
   * than a specific file. It is useful for calculating keys and inputs of the Action Template by
   * reusing functionality from LtoBackendAction.
   */
  private LtoBackendAction getDummyAction() {
    LtoBackendAction.Builder builderCopy = new LtoBackendAction.Builder(ltoBackendActionbuilder);
    // This is a dummy action that would not work, because the bitcode file path is a directory
    // rather than a file.
    LtoBackendArtifacts.addArtifactsLtoBackendAction(
        builderCopy,
        buildVariables,
        featureConfiguration,
        indexAndImportsTreeArtifact,
        indexAndImportsTreeArtifact,
        fullBitcodeTreeArtifact,
        objectFileTreeArtifact,
        bitcodeFiles,
        dwoFileTreeArtifact,
        usePic,
        null,
        /* isDummyAction= */ true);

    return (LtoBackendAction) builderCopy.buildForActionTemplate(actionOwner);
  }

  @Override
  public SpecialArtifact getInputTreeArtifact() {
    return indexAndImportsTreeArtifact;
  }

  @Override
  public SpecialArtifact getOutputTreeArtifact() {
    return objectFileTreeArtifact;
  }

  @Override
  public ActionOwner getOwner() {
    return actionOwner;
  }

  @Override
  public boolean isShareable() {
    return false;
  }

  @Override
  public String getMnemonic() {
    return "LtoBackendActionTemplate";
  }

  @Override
  public NestedSet<Artifact> getMandatoryInputs() {
    return mandatoryInputs;
  }

  @Override
  public NestedSet<Artifact> getInputFilesForExtraAction(
      ActionExecutionContext actionExecutionContext) {
    return NestedSetBuilder.emptySet(Order.STABLE_ORDER);
  }

  @Override
  public ImmutableSet<Artifact> getMandatoryOutputs() {
    return ImmutableSet.of();
  }

  @Override
  public NestedSet<Artifact> getTools() {
    return NestedSetBuilder.emptySet(Order.STABLE_ORDER);
  }

  @Override
  public NestedSet<Artifact> getInputs() {
    return allInputs;
  }

  @Override
  public ImmutableSet<Artifact> getOutputs() {
    ImmutableSet.Builder<Artifact> builder = ImmutableSet.builder();
    builder.add(objectFileTreeArtifact);
    if (dwoFileTreeArtifact != null) {
      builder.add(dwoFileTreeArtifact);
    }
    return builder.build();
  }

  @Override
  public ImmutableList<String> getClientEnvironmentVariables() {
    return ImmutableList.of();
  }

  @Override
  public NestedSet<Artifact> getSchedulingDependencies() {
    return NestedSetBuilder.emptySet(Order.STABLE_ORDER);
  }

  @Override
  public boolean shouldReportPathPrefixConflict(ActionAnalysisMetadata action) {
    return this != action;
  }

  @Override
  public MiddlemanType getActionType() {
    return MiddlemanType.NORMAL;
  }

  @Override
  public String prettyPrint() {
    return "LtoBackendActionTemplate compiling " + fullBitcodeTreeArtifact.getExecPathString();
  }

  @Override
  public String describe() {
    return "Lto backend compiling all C++ files in " + fullBitcodeTreeArtifact.prettyPrint();
  }

  @Override
  public String toString() {
    return prettyPrint();
  }

  private static DetailedExitCode makeDetailedExitCode(String message) {
    return DetailedExitCode.of(
        FailureDetails.FailureDetail.newBuilder()
            .setMessage(message)
            .setExecution(
                FailureDetails.Execution.newBuilder()
                    .setCode(
                        FailureDetails.Execution.Code
                            .PERSISTENT_ACTION_OUTPUT_DIRECTORY_CREATION_FAILURE))
            .build());
  }
}
