// 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.ImmutableMap;
import com.google.common.collect.ImmutableSet;
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.SymlinkAction;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
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.CcLinkParams;
import com.google.devtools.build.lib.rules.cpp.CcLinkParams.Linkstamp;
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.FdoSupportProvider;
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.LinkerInputs;
import com.google.devtools.build.lib.rules.cpp.LinkerInputs.LibraryToLink;
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;

/**
 * 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(RuleContext ruleContext, BuildConfiguration configuration,
            PathFragment rootRelativePath) {
          return ruleContext.getShareableArtifact(rootRelativePath,
              configuration.getBinDirectory(ruleContext.getRule().getRepository()));
        }
      };

  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 linkParams the {@link CcLinkParams} 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,
      CcLinkParams linkParams,
      final BuildConfiguration configuration,
      CcToolchainProvider toolchain,
      CppSemantics cppSemantics)
      throws InterruptedException {
    if (!containsCodeToLink(linkParams.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,
            linkParams,
            /* 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 (Link.SHARED_LIBRARY_FILETYPES.matches(library.getArtifact().getFilename())) {
      // this is a shared library so we're going to have to copy it
      return false;
    }
    if (!library.containsObjectFiles()) {
      // this is an opaque library so we're going to have to link it
      return true;
    }
    for (Artifact object : library.getObjectFiles()) {
      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,
      CcLinkParams linkParams,
      Collection<String> extraLinkOpts,
      BuildConfiguration configuration,
      CcToolchainProvider toolchain,
      Artifact nativeDeps,
      String libraryIdentifier,
      ArtifactRoot bindirIfShared,
      boolean useDynamicRuntime,
      CppSemantics cppSemantics)
      throws InterruptedException {
    Preconditions.checkState(
        ruleContext.isLegalFragment(CppConfiguration.class),
        "%s does not have access to CppConfiguration",
        ruleContext.getRule().getRuleClass());
    List<String> linkopts = new ArrayList<>(extraLinkOpts);
    linkopts.addAll(linkParams.flattenedLinkopts());

    CppHelper.checkLinkstampsUnique(ruleContext, linkParams);
    ImmutableSet<Linkstamp> linkstamps = ImmutableSet.copyOf(linkParams.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 = linkParams.getLibraries();
    Artifact sharedLibrary;
    if (shareNativeDeps) {
      PathFragment sharedPath =
          getSharedNativeDepsPath(
              LinkerInputs.toLibraryArtifacts(linkerInputs),
              linkopts,
              linkstamps
                  .stream()
                  .map(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;
    }
    FdoSupportProvider fdoSupport =
        CppHelper.getFdoSupportUsingDefaultCcToolchainAttribute(ruleContext);
    FeatureConfiguration featureConfiguration =
        CcCommon.configureFeaturesOrReportRuleError(
            ruleContext,
            /* requestedFeatures= */ ImmutableSet.<String>builder()
                .addAll(ruleContext.getFeatures())
                .add(STATIC_LINKING_MODE)
                .build(),
            /* unsupportedFeatures= */ ruleContext.getDisabledFeatures(),
            toolchain);
    CppLinkActionBuilder builder =
        new CppLinkActionBuilder(
            ruleContext,
            sharedLibrary,
            configuration,
            toolchain,
            fdoSupport,
            featureConfiguration,
            cppSemantics);
    if (useDynamicRuntime) {
      builder.setRuntimeInputs(
          ArtifactCategory.DYNAMIC_LIBRARY,
          toolchain.getDynamicRuntimeLinkMiddleman(featureConfiguration),
          toolchain.getDynamicRuntimeLinkInputs(featureConfiguration));
    } else {
      builder.setRuntimeInputs(
          ArtifactCategory.STATIC_LIBRARY,
          toolchain.getStaticRuntimeLinkMiddleman(featureConfiguration),
          toolchain.getStaticRuntimeLinkInputs(featureConfiguration));
    }
    ImmutableMap.Builder<Artifact, Artifact> ltoBitcodeFilesMap = new ImmutableMap.Builder<>();
    for (LibraryToLink lib : linkerInputs) {
      if (!lib.getLtoBitcodeFiles().isEmpty()) {
        ltoBitcodeFilesMap.putAll(lib.getLtoBitcodeFiles());
      }
    }

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

    builder
        .setLinkArtifactFactory(SHAREABLE_LINK_ARTIFACT_FACTORY)
        .setCrosstoolInputs(toolchain.getLink())
        .addLibraries(linkerInputs)
        .setLinkType(LinkTargetType.DYNAMIC_LIBRARY)
        .setLinkingMode(LinkingMode.STATIC)
        .setLibraryIdentifier(libraryIdentifier)
        .addLinkopts(linkopts)
        .setNativeDeps(true)
        .addLinkstamps(linkstamps)
        .addLtoBitcodeFiles(ltoBitcodeFilesMap.build())
        .addNonCodeInputs(nonCodeInputs);

    if (builder.hasLtoBitcodeInputs() && featureConfiguration.isEnabled(CppRuleClasses.THIN_LTO)) {
      builder.setLtoIndexing(true);
      builder.setUsePicForLtoBackendActions(
          CppHelper.usePicForDynamicLibraries(ruleContext, toolchain));
      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(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(
              new SymlinkAction(ruleContext.getActionOwner(), runtimeInput, runtimeSymlink, null));
          runtimeSymlinks.add(runtimeSymlink);
        }
      } else {
        runtimeSymlinks = ImmutableList.of();
      }

      ruleContext.registerAction(
          new SymlinkAction(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();
    for (Artifact input : linkerInputs) {
      fp.addString(input.getExecPathString());
    }
    fp.addStrings(linkopts);
    for (Artifact input : linkstamps) {
      fp.addString(input.getExecPathString());
    }
    for (Artifact input : buildInfoArtifacts) {
      fp.addString(input.getExecPathString());
    }
    for (String feature : features) {
      fp.addString(feature);
    }
    return PathFragment.create("_nativedeps/" + fp.hexDigestAndReset());
  }
}
