// Copyright 2015 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.nativedeps;

import static com.google.devtools.build.lib.rules.cpp.CppRuleClasses.STATIC_LINKING_MODE;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.actions.ActionConstructionContext;
import com.google.devtools.build.lib.analysis.actions.SymlinkAction;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.rules.cpp.ArtifactCategory;
import com.google.devtools.build.lib.rules.cpp.CcCommon;
import com.google.devtools.build.lib.rules.cpp.CcInfo;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.rules.cpp.CcToolchainProvider;
import com.google.devtools.build.lib.rules.cpp.CppBuildInfo;
import com.google.devtools.build.lib.rules.cpp.CppConfiguration;
import com.google.devtools.build.lib.rules.cpp.CppHelper;
import com.google.devtools.build.lib.rules.cpp.CppLinkAction;
import com.google.devtools.build.lib.rules.cpp.CppLinkActionBuilder;
import com.google.devtools.build.lib.rules.cpp.CppRuleClasses;
import com.google.devtools.build.lib.rules.cpp.CppSemantics;
import com.google.devtools.build.lib.rules.cpp.FdoContext;
import com.google.devtools.build.lib.rules.cpp.LibraryToLink;
import com.google.devtools.build.lib.rules.cpp.LibraryToLink.CcLinkingContext;
import com.google.devtools.build.lib.rules.cpp.LibraryToLink.CcLinkingContext.Linkstamp;
import com.google.devtools.build.lib.rules.cpp.Link;
import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType;
import com.google.devtools.build.lib.rules.cpp.Link.LinkingMode;
import com.google.devtools.build.lib.rules.cpp.LtoCompilationContext;
import com.google.devtools.build.lib.util.Fingerprint;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

/**
 * Helper class to create a dynamic library for rules which support integration with native code.
 *
 * <p>This library gets created by the build system by linking all C++ libraries in the transitive
 * closure of the dependencies into a standalone dynamic library, with some exceptions. It usually
 * does not include neverlink libraries or C++ binaries (or their transitive dependencies). Note
 * that some rules are implicitly neverlink.
 */
public abstract class NativeDepsHelper {
  /**
   * An implementation of {@link
   * com.google.devtools.build.lib.rules.cpp.CppLinkAction.LinkArtifactFactory} that can create
   * artifacts anywhere.
   *
   * <p>Necessary because the actions of nativedeps libraries should be shareable, and thus cannot
   * be under the package directory.
   */
  private static final CppLinkAction.LinkArtifactFactory SHAREABLE_LINK_ARTIFACT_FACTORY =
      new CppLinkAction.LinkArtifactFactory() {
        @Override
        public Artifact create(
            ActionConstructionContext actionConstructionContext,
            RepositoryName repositoryName,
            BuildConfiguration configuration,
            PathFragment rootRelativePath) {
          return actionConstructionContext.getShareableArtifact(
              rootRelativePath, configuration.getBinDirectory(repositoryName));
        }
      };

  private NativeDepsHelper() {}

  private static final String ANDROID_UNIQUE_DIR = "nativedeps";

  /**
   * Creates an Action to create a dynamic library for Android by linking all native code (C/C++)
   * libraries in the transitive dependency closure of a rule.
   *
   * <p>We link the native deps in the equivalent of linkstatic=1, linkshared=1 mode.
   *
   * <p>linkstatic=1 means mostly-static mode, i.e. we select the ".a" (or ".pic.a") files, but we
   * don't include "-static" in linkopts.
   *
   * <p>linkshared=1 means we prefer the ".pic.a" files to the ".a" files, and the LinkTargetType is
   * set to DYNAMIC_LIBRARY which causes Link.java to include "-shared" in the linker options.
   *
   * <p>It is possible that this function may have no work to do if there are no native libraries in
   * the transitive closure, or if the only native libraries in the transitive closure are already
   * shared libraries. In this case, this function returns {@code null}.
   *
   * @param ruleContext the rule context to determine the native deps library
   * @param ccInfo the {@link CcInfo} for the rule, collected with linkstatic = 1 and linkshared = 1
   * @param cppSemantics to use for linkstamp compiles
   * @return the native deps library, or null if there was no code which needed to be linked in the
   *     transitive closure.
   */
  public static Artifact linkAndroidNativeDepsIfPresent(
      final RuleContext ruleContext,
      CcInfo ccInfo,
      final BuildConfiguration configuration,
      CcToolchainProvider toolchain,
      CppSemantics cppSemantics)
      throws InterruptedException, RuleErrorException {
    if (!containsCodeToLink(ccInfo.getCcLinkingContext().getLibraries())) {
      return null;
    }

    PathFragment labelName = PathFragment.create(ruleContext.getLabel().getName());
    String libraryIdentifier = ruleContext.getUniqueDirectory(ANDROID_UNIQUE_DIR)
        .getRelative(labelName.replaceName("lib" + labelName.getBaseName()))
        .getPathString();
    Artifact nativeDeps = ruleContext.getUniqueDirectoryArtifact(ANDROID_UNIQUE_DIR,
        labelName.replaceName("lib" + labelName.getBaseName() + ".so"),
        configuration.getBinDirectory(ruleContext.getRule().getRepository()));

    return createNativeDepsAction(
            ruleContext,
            ccInfo,
            /* extraLinkOpts= */ ImmutableList.of(),
            configuration,
            toolchain,
            nativeDeps,
            libraryIdentifier,
            configuration.getBinDirectory(ruleContext.getRule().getRepository()),
            /* useDynamicRuntime= */ false,
            cppSemantics)
        .getLibrary();
  }

  /** Determines if there is any code to be linked in the input iterable. */
  private static boolean containsCodeToLink(Iterable<LibraryToLink> libraries) {
    for (LibraryToLink library : libraries) {
      if (containsCodeToLink(library)) {
        return true;
      }
    }
    return false;
  }

  /** Determines if the input library is or contains an archive which must be linked. */
  private static boolean containsCodeToLink(LibraryToLink library) {
    if (library.getStaticLibrary() == null && library.getPicStaticLibrary() == null) {
      // this is a shared library so we're going to have to copy it
      return false;
    }
    Iterable<Artifact> objectFiles;
    if (library.getObjectFiles() != null) {
      objectFiles = library.getObjectFiles();
    } else if (library.getPicObjectFiles() != null) {
      objectFiles = library.getPicObjectFiles();
    } else {
      // this is an opaque library so we're going to have to link it
      return true;
    }
    for (Artifact object : objectFiles) {
      if (!Link.SHARED_LIBRARY_FILETYPES.matches(object.getFilename())) {
        // this library was built with a non-shared-library object so we should link it
        return true;
      }
    }
    // there weren't any artifacts besides shared libraries compiled in the library
    return false;
  }

  public static NativeDepsRunfiles createNativeDepsAction(
      final RuleContext ruleContext,
      CcInfo ccInfo,
      Collection<String> extraLinkOpts,
      BuildConfiguration configuration,
      CcToolchainProvider toolchain,
      Artifact nativeDeps,
      String libraryIdentifier,
      ArtifactRoot bindirIfShared,
      boolean useDynamicRuntime,
      CppSemantics cppSemantics)
      throws InterruptedException, RuleErrorException {
    CcLinkingContext ccLinkingContext = ccInfo.getCcLinkingContext();
    Preconditions.checkState(
        ruleContext.isLegalFragment(CppConfiguration.class),
        "%s does not have access to CppConfiguration",
        ruleContext.getRule().getRuleClass());
    List<String> linkopts = new ArrayList<>(extraLinkOpts);
    linkopts.addAll(ccLinkingContext.getFlattenedUserLinkFlags());

    CppHelper.checkLinkstampsUnique(ruleContext, ccLinkingContext.getLinkstamps());
    ImmutableSet<Linkstamp> linkstamps = ImmutableSet.copyOf(ccLinkingContext.getLinkstamps());
    List<Artifact> buildInfoArtifacts = linkstamps.isEmpty()
        ? ImmutableList.<Artifact>of()
        : ruleContext.getAnalysisEnvironment().getBuildInfo(
            ruleContext, CppBuildInfo.KEY, configuration);

    boolean shareNativeDeps = configuration.getFragment(CppConfiguration.class).shareNativeDeps();
    NestedSet<LibraryToLink> linkerInputs = ccLinkingContext.getLibraries();
    Artifact sharedLibrary;
    if (shareNativeDeps) {
      PathFragment sharedPath =
          getSharedNativeDepsPath(
              ccLinkingContext.getStaticModeParamsForDynamicLibraryLibraries(),
              linkopts,
              linkstamps.stream()
                  .map(CcLinkingContext.Linkstamp::getArtifact)
                  .collect(ImmutableList.toImmutableList()),
              buildInfoArtifacts,
              ruleContext.getFeatures());
      libraryIdentifier = sharedPath.getPathString();
      sharedLibrary = ruleContext.getShareableArtifact(
          sharedPath.replaceName(sharedPath.getBaseName() + ".so"),
          configuration.getBinDirectory(ruleContext.getRule().getRepository()));
    } else {
      sharedLibrary = nativeDeps;
    }
    FdoContext fdoContext = toolchain.getFdoContext();
    ImmutableSet.Builder<String> requestedFeatures =
        ImmutableSet.<String>builder().addAll(ruleContext.getFeatures()).add(STATIC_LINKING_MODE);
    if (!ruleContext.getDisabledFeatures().contains(CppRuleClasses.LEGACY_WHOLE_ARCHIVE)) {
      requestedFeatures.add(CppRuleClasses.LEGACY_WHOLE_ARCHIVE);
    }
    FeatureConfiguration featureConfiguration =
        CcCommon.configureFeaturesOrReportRuleError(
            ruleContext,
            /* requestedFeatures= */ requestedFeatures.build(),
            /* unsupportedFeatures= */ ruleContext.getDisabledFeatures(),
            toolchain);
    CppLinkActionBuilder builder =
        new CppLinkActionBuilder(
            ruleContext,
            sharedLibrary,
            configuration,
            toolchain,
            fdoContext,
            featureConfiguration,
            cppSemantics);
    if (useDynamicRuntime) {
      builder.setRuntimeInputs(
          ArtifactCategory.DYNAMIC_LIBRARY,
          toolchain.getDynamicRuntimeLinkMiddleman(ruleContext, featureConfiguration),
          toolchain.getDynamicRuntimeLinkInputs(ruleContext, featureConfiguration));
    } else {
      builder.setRuntimeInputs(
          ArtifactCategory.STATIC_LIBRARY,
          toolchain.getStaticRuntimeLinkMiddleman(ruleContext, featureConfiguration),
          toolchain.getStaticRuntimeLinkInputs(ruleContext, featureConfiguration));
    }
    LtoCompilationContext.Builder ltoCompilationContext = new LtoCompilationContext.Builder();
    for (LibraryToLink lib : linkerInputs) {
      if (lib.getPicLtoCompilationContext() != null
          && !lib.getPicLtoCompilationContext().isEmpty()) {
        ltoCompilationContext.addAll(lib.getPicLtoCompilationContext());
      } else if (lib.getLtoCompilationContext() != null
          && !lib.getLtoCompilationContext().isEmpty()) {
        ltoCompilationContext.addAll(lib.getLtoCompilationContext());
      }
    }

    Iterable<Artifact> nonCodeInputs = ccLinkingContext.getNonCodeInputs();
    if (nonCodeInputs == null) {
      nonCodeInputs = ImmutableList.of();
    }

    builder
        .setLinkArtifactFactory(SHAREABLE_LINK_ARTIFACT_FACTORY)
        .setLinkerFiles(toolchain.getLinkerFiles())
        .addLibrariesToLink(linkerInputs)
        .setLinkType(LinkTargetType.DYNAMIC_LIBRARY)
        .setLinkingMode(LinkingMode.STATIC)
        .setLibraryIdentifier(libraryIdentifier)
        .addLinkopts(linkopts)
        .setNativeDeps(true)
        .addLinkstamps(linkstamps)
        .addLtoCompilationContext(ltoCompilationContext.build())
        .addNonCodeInputs(nonCodeInputs);

    if (builder.hasLtoBitcodeInputs() && featureConfiguration.isEnabled(CppRuleClasses.THIN_LTO)) {
      builder.setLtoIndexing(true);
      builder.setUsePicForLtoBackendActions(
          toolchain.usePicForDynamicLibraries(featureConfiguration));
      CppLinkAction indexAction = builder.build();
      if (indexAction != null) {
        ruleContext.registerAction(indexAction);
      }
      builder.setLtoIndexing(false);
    }

    CppLinkAction linkAction = builder.build();
    ruleContext.registerAction(linkAction);
    Artifact linkerOutput = linkAction.getPrimaryOutput();

    if (shareNativeDeps) {
      // Collect dynamic-linker-resolvable symlinks for C++ runtime library dependencies.
      // Note we only need these symlinks when --share_native_deps is on, as shared native deps
      // mangle path names such that the library's conventional _solib RPATH entry
      // no longer resolves (because the target directory's relative depth gets lost).
      List<Artifact> runtimeSymlinks;
      if (useDynamicRuntime) {
        runtimeSymlinks = new LinkedList<>();
        for (final Artifact runtimeInput :
            toolchain.getDynamicRuntimeLinkInputs(ruleContext, featureConfiguration)) {
          final Artifact runtimeSymlink =
              ruleContext.getPackageRelativeArtifact(
                  getRuntimeLibraryPath(ruleContext, runtimeInput), bindirIfShared);
          // Since runtime library symlinks are underneath the target's output directory and
          // multiple targets may share the same output directory, we need to make sure this
          // symlink's generating action is only set once.
          ruleContext.registerAction(SymlinkAction.toArtifact(
              ruleContext.getActionOwner(), runtimeInput, runtimeSymlink, null));
          runtimeSymlinks.add(runtimeSymlink);
        }
      } else {
        runtimeSymlinks = ImmutableList.of();
      }

      ruleContext.registerAction(SymlinkAction.toArtifact(
          ruleContext.getActionOwner(), linkerOutput, nativeDeps, null));
      return new NativeDepsRunfiles(nativeDeps, runtimeSymlinks);
    }

    return new NativeDepsRunfiles(linkerOutput, ImmutableList.<Artifact>of());
  }

  /**
   * Returns the path, relative to the runfiles prefix, of a runtime library
   * symlink for the native library for the specified rule.
   */
  private static PathFragment getRuntimeLibraryPath(RuleContext ruleContext, Artifact lib) {
    PathFragment relativePath = PathFragment.create(ruleContext.getLabel().getName());
    PathFragment libParentDir =
        relativePath.replaceName(lib.getExecPath().getParentDirectory().getBaseName());
    String libName = lib.getExecPath().getBaseName();
    return libParentDir.getRelative(libName);
  }

  /**
   * Returns the path of the shared native library. The name must be
   * generated based on the rule-specific inputs to the link actions. At this
   * point this includes order-sensitive list of linker inputs and options
   * collected from the transitive closure and linkstamp-related artifacts that
   * are compiled during linking. All those inputs can be affected by modifying
   * target attributes (srcs/deps/stamp/etc). However, target build
   * configuration can be ignored since it will either change output directory
   * (in case of different configuration instances) or will not affect anything
   * (if two targets use same configuration). Final goal is for all native
   * libraries that use identical linker command to use same output name.
   *
   * <p>TODO(bazel-team): (2010) Currently process of identifying parameters that can
   * affect native library name is manual and should be kept in sync with the
   * code in the CppLinkAction.Builder/CppLinkAction/Link classes which are
   * responsible for generating linker command line. Ideally we should reuse
   * generated command line for both purposes - selecting a name of the
   * native library and using it as link action payload. For now, correctness
   * of the method below is only ensured by validations in the
   * CppLinkAction.Builder.build() method.
   */
  private static PathFragment getSharedNativeDepsPath(Iterable<Artifact> linkerInputs,
      Collection<String> linkopts, Iterable<Artifact> linkstamps,
      Iterable<Artifact> buildInfoArtifacts, Collection<String> features) {
    Fingerprint fp = new Fingerprint();
    int linkerInputsSize = 0;
    for (Artifact input : linkerInputs) {
      fp.addString(input.getExecPathString());
      linkerInputsSize++;
    }
    fp.addStrings(linkopts);
    int linkstampsSize = 0;
    for (Artifact input : linkstamps) {
      fp.addString(input.getExecPathString());
      linkstampsSize++;
    }
    // TODO(b/120206809): remove debugging info here (and in this whole filename construction).
    String linkstampsString = Integer.toString(linkstampsSize);
    if (linkstampsSize > 1) {
      Set<Artifact> identitySet = Sets.newIdentityHashSet();
      Iterables.addAll(identitySet, linkstamps);
      if (identitySet.size() < linkstampsSize) {
        linkstampsString += "_" + identitySet.size();
      }
      ImmutableSet<Artifact> uniqueLinkStamps = ImmutableSet.copyOf(linkstamps);
      if (uniqueLinkStamps.size() < linkstampsSize) {
        linkstampsString += "__" + uniqueLinkStamps.size();
      }
    }
    int buildInfoSize = 0;
    for (Artifact input : buildInfoArtifacts) {
      fp.addString(input.getExecPathString());
      buildInfoSize++;
    }
    for (String feature : features) {
      fp.addString(feature);
    }
    return PathFragment.create(
        "_nativedeps/"
            + linkerInputsSize
            + "_"
            + linkopts.size()
            + "_"
            + linkstampsString
            + "_"
            + buildInfoSize
            + "_"
            + features.size()
            + "_"
            + fp.hexDigestAndReset());
  }
}
