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

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

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.ArtifactExpander;
import com.google.devtools.build.lib.actions.CommandLine;
import com.google.devtools.build.lib.actions.CommandLineExpansionException;
import com.google.devtools.build.lib.actions.PathMapper;
import com.google.devtools.build.lib.collect.CollectionUtils;
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.concurrent.ThreadSafety.Immutable;
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.Link.LinkTargetType;
import com.google.devtools.build.lib.rules.cpp.Link.LinkerOrArchiver;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;

/**
 * Represents the command line of a linker invocation. It supports executables and dynamic libraries
 * as well as static libraries.
 */
@Immutable
public final class LinkCommandLine extends CommandLine {
  private final String actionName;
  private final String forcedToolPath;
  private final CcToolchainVariables variables;
  // The feature config can be null for tests.
  @Nullable private final FeatureConfiguration featureConfiguration;
  private final NestedSet<Artifact> linkerInputArtifacts;
  private final LinkTargetType linkTargetType;
  private final Link.LinkingMode linkingMode;
  @Nullable private final PathFragment toolchainLibrariesSolibDir;
  private final boolean nativeDeps;
  private final boolean useTestOnlyFlags;

  @Nullable private final Artifact paramFile;

  private LinkCommandLine(
      String actionName,
      String forcedToolPath,
      NestedSet<Artifact> linkerInputArtifacts,
      LinkTargetType linkTargetType,
      Link.LinkingMode linkingMode,
      @Nullable PathFragment toolchainLibrariesSolibDir,
      boolean nativeDeps,
      boolean useTestOnlyFlags,
      @Nullable Artifact paramFile,
      CcToolchainVariables variables,
      @Nullable FeatureConfiguration featureConfiguration) {

    this.actionName = actionName;
    this.forcedToolPath = forcedToolPath;
    this.variables = variables;
    this.featureConfiguration = featureConfiguration;
    this.linkerInputArtifacts = Preconditions.checkNotNull(linkerInputArtifacts);
    this.linkTargetType = Preconditions.checkNotNull(linkTargetType);
    this.linkingMode = Preconditions.checkNotNull(linkingMode);
    this.toolchainLibrariesSolibDir = toolchainLibrariesSolibDir;
    this.nativeDeps = nativeDeps;
    this.useTestOnlyFlags = useTestOnlyFlags;
    this.paramFile = paramFile;
  }

  @Nullable
  public Artifact getParamFile() {
    return paramFile;
  }

  /** Returns the (ordered, immutable) list of paths to the linker's input files. */
  public NestedSet<Artifact> getLinkerInputArtifacts() {
    return linkerInputArtifacts;
  }

  @Nullable
  @VisibleForTesting
  public FeatureConfiguration getFeatureConfiguration() {
    return featureConfiguration;
  }

  public String getActionName() {
    return actionName;
  }

  /** Returns the current type of link target set. */
  public LinkTargetType getLinkTargetType() {
    return linkTargetType;
  }

  /** Returns the "staticness" of the link. */
  public Link.LinkingMode getLinkingMode() {
    return linkingMode;
  }

  /** Returns the path to the linker. */
  public String getLinkerPathString() {
    return featureConfiguration.getToolPathForAction(linkTargetType.getActionName());
  }

  /**
   * Returns the location of the C++ runtime solib symlinks. If null, the C++ dynamic runtime
   * libraries either do not exist (because they do not come from the depot) or they are in the
   * regular solib directory.
   */
  @Nullable
  public PathFragment getToolchainLibrariesSolibDir() {
    return toolchainLibrariesSolibDir;
  }

  /** Returns true for libraries linked as native dependencies for other languages. */
  public boolean isNativeDeps() {
    return nativeDeps;
  }

  /**
   * Returns true if this link should use test-specific flags (e.g. $EXEC_ORIGIN as the root for
   * finding shared libraries or lazy binding); false by default. See bug "Please use $EXEC_ORIGIN
   * instead of $ORIGIN when linking cc_tests" for further context.
   */
  public boolean useTestOnlyFlags() {
    return useTestOnlyFlags;
  }

  /** Returns the build variables used to template the crosstool for this linker invocation. */
  @VisibleForTesting
  public CcToolchainVariables getBuildVariables() {
    return this.variables;
  }

  /**
   * Splits the link command-line into a part to be written to a parameter file, and the remaining
   * actual command line to be executed (which references the parameter file). Should only be used
   * if getParamFile() is not null.
   */
  @VisibleForTesting
  final Pair<List<String>, List<String>> splitCommandline() throws CommandLineExpansionException {
    return splitCommandline(paramFile, getRawLinkArgv(null), linkTargetType);
  }

  @VisibleForTesting
  final Pair<List<String>, List<String>> splitCommandline(@Nullable ArtifactExpander expander)
      throws CommandLineExpansionException {
    return splitCommandline(paramFile, getRawLinkArgv(expander), linkTargetType);
  }

  private static Pair<List<String>, List<String>> splitCommandline(
      Artifact paramFile, List<String> args, LinkTargetType linkTargetType) {
    Preconditions.checkNotNull(paramFile);
    if (linkTargetType.linkerOrArchiver() == LinkerOrArchiver.ARCHIVER) {
      // Ar link commands can also generate huge command lines.
      List<String> paramFileArgs = new ArrayList<>();
      List<String> commandlineArgs = new ArrayList<>();
      extractArgumentsForStaticLinkParamFile(args, commandlineArgs, paramFileArgs);
      return Pair.of(commandlineArgs, paramFileArgs);
    } else {
      // Gcc link commands tend to generate humongous commandlines for some targets, which may
      // not fit on some remote execution machines. To work around this we will employ the help of
      // a parameter file and pass any linker options through it.
      List<String> paramFileArgs = new ArrayList<>();
      List<String> commandlineArgs = new ArrayList<>();
      extractArgumentsForDynamicLinkParamFile(args, commandlineArgs, paramFileArgs);
      return Pair.of(commandlineArgs, paramFileArgs);
    }
  }

  public CommandLine getCommandLineForStarlark() {
    return new CommandLine() {
      @Override
      public Iterable<String> arguments() throws CommandLineExpansionException {
        return arguments(/* artifactExpander= */ null, PathMapper.NOOP);
      }

      @Override
      public ImmutableList<String> arguments(
          ArtifactExpander artifactExpander, PathMapper pathMapper)
          throws CommandLineExpansionException {
        if (paramFile == null) {
          return ImmutableList.copyOf(getRawLinkArgv(artifactExpander));
        } else {
          return ImmutableList.<String>builder()
              .add(getLinkerPathString())
              .addAll(splitCommandline(artifactExpander).getSecond())
              .build();
        }
      }
    };
  }

  /**
   * A {@link CommandLine} implementation that returns the command line args pertaining to the
   * .params file.
   */
  private static class ParamFileCommandLine extends CommandLine {
    private final Artifact paramsFile;
    private final LinkTargetType linkTargetType;
    private final String forcedToolPath;
    private final FeatureConfiguration featureConfiguration;
    private final String actionName;
    private final CcToolchainVariables variables;

    ParamFileCommandLine(
        Artifact paramsFile,
        LinkTargetType linkTargetType,
        String forcedToolPath,
        FeatureConfiguration featureConfiguration,
        String actionName,
        CcToolchainVariables variables) {
      this.paramsFile = paramsFile;
      this.linkTargetType = linkTargetType;
      this.forcedToolPath = forcedToolPath;
      this.featureConfiguration = featureConfiguration;
      this.actionName = actionName;
      this.variables = variables;
    }

    @Override
    public Iterable<String> arguments() throws CommandLineExpansionException {
      List<String> argv =
          getRawLinkArgv(
              null, forcedToolPath, featureConfiguration, actionName, linkTargetType, variables);
      return splitCommandline(paramsFile, argv, linkTargetType).getSecond();
    }

    @Override
    public Iterable<String> arguments(ArtifactExpander expander, PathMapper pathMapper)
        throws CommandLineExpansionException {
      List<String> argv =
          getRawLinkArgv(
              expander,
              forcedToolPath,
              featureConfiguration,
              actionName,
              linkTargetType,
              variables);
      return splitCommandline(paramsFile, argv, linkTargetType).getSecond();
    }
  }

  /** Returns just the .params file portion of the command-line as a {@link CommandLine}. */
  CommandLine paramCmdLine() {
    Preconditions.checkNotNull(paramFile);
    return new ParamFileCommandLine(
        paramFile, linkTargetType, forcedToolPath, featureConfiguration, actionName, variables);
  }

  private static void extractArgumentsForStaticLinkParamFile(
      List<String> args, List<String> commandlineArgs, List<String> paramFileArgs) {
    commandlineArgs.add(args.get(0)); // ar command, must not be moved!
    int argsSize = args.size();
    for (int i = 1; i < argsSize; i++) {
      String arg = args.get(i);
      if (isLikelyParamFile(arg)) {
        commandlineArgs.add(arg); // params file, keep it in the command line
      } else {
        paramFileArgs.add(arg); // the rest goes to the params file
      }
    }
  }

  private static void extractArgumentsForDynamicLinkParamFile(
      List<String> args, List<String> commandlineArgs, List<String> paramFileArgs) {
    // Note, that it is not important that all linker arguments are extracted so that
    // they can be moved into a parameter file, but the vast majority should.
    commandlineArgs.add(args.get(0)); // gcc command, must not be moved!
    int argsSize = args.size();
    for (int i = 1; i < argsSize; i++) {
      String arg = args.get(i);
      if (isLikelyParamFile(arg)) {
        commandlineArgs.add(arg); // params file, keep it in the command line
      } else {
        paramFileArgs.add(arg); // the rest goes to the params file
      }
    }
  }

  private static boolean isLikelyParamFile(String arg) {
    return arg.startsWith("@")
        && !arg.startsWith("@rpath")
        && !arg.startsWith("@loader_path")
        && !arg.startsWith("@executable_path");
  }

  /**
   * Returns a raw link command for the given link invocation, including both command and arguments
   * (argv). The version that uses the expander is preferred, but that one can't be used during
   * analysis.
   *
   * @return raw link command line.
   */
  public List<String> getRawLinkArgv() throws CommandLineExpansionException {
    return getRawLinkArgv(null);
  }

  /**
   * Returns a raw link command for the given link invocation, including both command and arguments
   * (argv).
   *
   * @param expander ArtifactExpander for expanding TreeArtifacts.
   * @return raw link command line.
   */
  public List<String> getRawLinkArgv(@Nullable ArtifactExpander expander)
      throws CommandLineExpansionException {
    return getRawLinkArgv(
        expander, forcedToolPath, featureConfiguration, actionName, linkTargetType, variables);
  }

  private static List<String> getRawLinkArgv(
      @Nullable ArtifactExpander expander,
      String forcedToolPath,
      FeatureConfiguration featureConfiguration,
      String actionName,
      LinkTargetType linkTargetType,
      CcToolchainVariables variables)
      throws CommandLineExpansionException {
    List<String> argv = new ArrayList<>();
    if (forcedToolPath != null) {
      argv.add(forcedToolPath);
    } else {
      Preconditions.checkArgument(
          featureConfiguration.actionIsConfigured(actionName),
          String.format("Expected action_config for '%s' to be configured", actionName));
      argv.add(featureConfiguration.getToolPathForAction(linkTargetType.getActionName()));
    }
    try {
      argv.addAll(featureConfiguration.getCommandLine(actionName, variables, expander));
    } catch (ExpansionException e) {
      throw new CommandLineExpansionException(e.getMessage());
    }
    return argv;
  }

  List<String> getCommandLine(@Nullable ArtifactExpander expander)
      throws CommandLineExpansionException {
    // Try to shorten the command line by use of a parameter file.
    // This makes the output with --subcommands (et al) more readable.
    if (paramFile != null) {
      Pair<List<String>, List<String>> split = splitCommandline(expander);
      return split.first;
    } else {
      return getRawLinkArgv(expander);
    }
  }

  @Override
  public List<String> arguments() throws CommandLineExpansionException {
    return getRawLinkArgv(null);
  }

  @Override
  public List<String> arguments(ArtifactExpander artifactExpander, PathMapper pathMapper)
      throws CommandLineExpansionException {
    return getRawLinkArgv(artifactExpander);
  }

  /** A builder for a {@link LinkCommandLine}. */
  public static final class Builder {

    private String forcedToolPath;
    private NestedSet<Artifact> linkerInputArtifacts =
        NestedSetBuilder.emptySet(Order.STABLE_ORDER);
    @Nullable private LinkTargetType linkTargetType;
    private Link.LinkingMode linkingMode = Link.LinkingMode.STATIC;
    @Nullable private PathFragment toolchainLibrariesSolibDir;
    private boolean nativeDeps;
    private boolean useTestOnlyFlags;
    @Nullable private Artifact paramFile;
    private CcToolchainVariables variables;
    private FeatureConfiguration featureConfiguration;
    private String actionName;

    public LinkCommandLine build() {
      if (variables == null) {
        variables = CcToolchainVariables.EMPTY;
      }

      return new LinkCommandLine(
          actionName,
          forcedToolPath,
          linkerInputArtifacts,
          linkTargetType,
          linkingMode,
          toolchainLibrariesSolibDir,
          nativeDeps,
          useTestOnlyFlags,
          paramFile,
          variables,
          featureConfiguration);
    }

    /** Use given tool path instead of the one from feature configuration */
    @CanIgnoreReturnValue
    public Builder forceToolPath(String forcedToolPath) {
      this.forcedToolPath = forcedToolPath;
      return this;
    }

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

    /**
     * Sets the type of the link. It is an error to try to set this to {@link
     * LinkTargetType#INTERFACE_DYNAMIC_LIBRARY}. Note that all the static target types (see {@link
     * LinkTargetType#linkerOrArchiver}) are equivalent, and there is no check that the output
     * artifact matches the target type extension.
     */
    @CanIgnoreReturnValue
    public Builder setLinkTargetType(LinkTargetType linkTargetType) {
      Preconditions.checkArgument(linkTargetType != LinkTargetType.INTERFACE_DYNAMIC_LIBRARY);
      this.linkTargetType = linkTargetType;
      return this;
    }

    /**
     * Sets a list of linker input artifacts. These get turned into linker options depending on the
     * staticness and the target type. This call makes an immutable copy of the inputs, if the
     * provided Iterable isn't already immutable (see {@link CollectionUtils#makeImmutable}).
     */
    @CanIgnoreReturnValue
    public Builder setLinkerInputArtifacts(NestedSet<Artifact> linkerInputArtifacts) {
      this.linkerInputArtifacts = linkerInputArtifacts;
      return this;
    }

    /**
     * Sets how static the link is supposed to be. For static target types (see {@link
     * LinkTargetType#linkerOrArchiver()}}), the {@link #build} method throws an exception if this
     * is not {@link LinkingMode#STATIC}. The default setting is {@link LinkingMode#STATIC}.
     */
    @CanIgnoreReturnValue
    public Builder setLinkingMode(Link.LinkingMode linkingMode) {
      this.linkingMode = linkingMode;
      return this;
    }

    /**
     * Whether the resulting library is intended to be used as a native library from another
     * programming language. This influences the rpath. The {@link #build} method throws an
     * exception if this is true for a static link (see {@link LinkTargetType#linkerOrArchiver()}}).
     */
    @CanIgnoreReturnValue
    public Builder setNativeDeps(boolean nativeDeps) {
      this.nativeDeps = nativeDeps;
      return this;
    }

    /**
     * Sets whether to use test-specific linker flags, e.g. {@code $EXEC_ORIGIN} instead of {@code
     * $ORIGIN} in the rpath or lazy binding.
     */
    @CanIgnoreReturnValue
    public Builder setUseTestOnlyFlags(boolean useTestOnlyFlags) {
      this.useTestOnlyFlags = useTestOnlyFlags;
      return this;
    }

    @CanIgnoreReturnValue
    public Builder setParamFile(Artifact paramFile) {
      this.paramFile = paramFile;
      return this;
    }

    @CanIgnoreReturnValue
    public Builder setBuildVariables(CcToolchainVariables variables) {
      this.variables = variables;
      return this;
    }

    @CanIgnoreReturnValue
    public Builder setToolchainLibrariesSolibDir(PathFragment toolchainLibrariesSolibDir) {
      this.toolchainLibrariesSolibDir = toolchainLibrariesSolibDir;
      return this;
    }

    @CanIgnoreReturnValue
    public Builder setActionName(String actionName) {
      this.actionName = actionName;
      return this;
    }
  }
}
