// 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.objc;

import static com.google.common.base.Preconditions.checkState;
import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.STRIP;
import static java.nio.charset.StandardCharsets.ISO_8859_1;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableCollection;
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.CommandLine;
import com.google.devtools.build.lib.actions.ParamFileInfo;
import com.google.devtools.build.lib.actions.ParameterFile;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine.VectorArg;
import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.collect.nestedset.Depset;
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.BuildType;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.packages.StarlarkInfo;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.rules.apple.AppleConfiguration;
import com.google.devtools.build.lib.rules.apple.XcodeConfigInfo;
import com.google.devtools.build.lib.rules.cpp.CcCommon;
import com.google.devtools.build.lib.rules.cpp.CcCommon.Language;
import com.google.devtools.build.lib.rules.cpp.CcCompilationContext;
import com.google.devtools.build.lib.rules.cpp.CcCompilationOutputs;
import com.google.devtools.build.lib.rules.cpp.CcInfo;
import com.google.devtools.build.lib.rules.cpp.CcLinkingContext;
import com.google.devtools.build.lib.rules.cpp.CcLinkingContext.LinkOptions;
import com.google.devtools.build.lib.rules.cpp.CcLinkingContext.LinkerInput;
import com.google.devtools.build.lib.rules.cpp.CcLinkingHelper;
import com.google.devtools.build.lib.rules.cpp.CcToolchain;
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.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.CppSemantics;
import com.google.devtools.build.lib.rules.cpp.LibraryToLink;
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.UserVariablesExtension;
import com.google.devtools.build.lib.rules.objc.ObjcVariablesExtension.VariableCategory;
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.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.annotation.Nullable;
import net.starlark.java.annot.StarlarkMethod;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.StarlarkValue;

/**
 * Support for rules that compile sources. Provides ways to determine files that should be output,
 * registering Xcode settings and generating the various actions that might be needed for
 * compilation.
 *
 * <p>A subclass should express a particular strategy for compile and link action registration.
 * Subclasses should implement the API without adding new visible methods - rule implementations
 * should be able to use a {@link CompilationSupport} instance to compile and link source without
 * knowing the subclass being used.
 *
 * <p>Methods on this class can be called in any order without impacting the result.
 */
public class CompilationSupport implements StarlarkValue {

  @VisibleForTesting static final String OBJC_MODULE_CACHE_DIR_NAME = "_objc_module_cache";

  @VisibleForTesting
  static final String ABSOLUTE_INCLUDES_PATH_FORMAT =
      "The path '%s' is absolute, but only relative paths are allowed.";

  // Flags for clang 6.1(xcode 6.4)
  @VisibleForTesting
  static final ImmutableList<String> CLANG_GCOV_COVERAGE_FLAGS =
      ImmutableList.of("-fprofile-arcs", "-ftest-coverage");

  @VisibleForTesting
  static final ImmutableList<String> CLANG_LLVM_COVERAGE_FLAGS =
      ImmutableList.of("-fprofile-instr-generate", "-fcoverage-mapping");

  // These are added by Xcode when building, because the simulator is built on OSX
  // frameworks so we aim compile to match the OSX objc runtime.
  @VisibleForTesting
  static final ImmutableList<String> SIMULATOR_COMPILE_FLAGS =
      ImmutableList.of(
          "-fexceptions", "-fasm-blocks", "-fobjc-abi-version=2", "-fobjc-legacy-dispatch");

  /**
   * Frameworks implicitly linked to iOS, watchOS, and tvOS binaries when using legacy compilation.
   */
  @VisibleForTesting
  static final NestedSet<String> AUTOMATIC_SDK_FRAMEWORKS =
      NestedSetBuilder.create(Order.STABLE_ORDER, "Foundation", "UIKit");

  /** Iterable wrapper providing strong type safety for arguments to binary linking. */
  static final class ExtraLinkArgs extends IterableWrapper<String> {
    ExtraLinkArgs(String... args) {
      super(args);
    }

    ExtraLinkArgs(Iterable<String> args) {
      super(args);
    }
  }

  /** Iterable wrapper providing strong type safety for extra compile flags. */
  static final class ExtraCompileArgs extends IterableWrapper<String> {
    static final ExtraCompileArgs NONE = new ExtraCompileArgs();

    ExtraCompileArgs(String... args) {
      super(args);
    }
  }

  @VisibleForTesting
  static final String FILE_IN_SRCS_AND_HDRS_WARNING_FORMAT = "File '%s' is in both srcs and hdrs.";

  @VisibleForTesting
  static final String FILE_IN_SRCS_AND_NON_ARC_SRCS_ERROR_FORMAT =
      "File '%s' is present in both srcs and non_arc_srcs which is forbidden.";

  @VisibleForTesting
  static final String BOTH_MODULE_NAME_AND_MODULE_MAP_SPECIFIED =
      "Specifying both module_name and module_map is invalid, please remove one of them.";

  static final ImmutableList<String> DEFAULT_COMPILER_FLAGS = ImmutableList.of("-DOS_IOS");

  /** Returns information about the given rule's compilation artifacts. */
  // TODO(bazel-team): Remove this information from ObjcCommon and move it internal to this class.
  static CompilationArtifacts compilationArtifacts(RuleContext ruleContext) {
    return compilationArtifacts(ruleContext, new IntermediateArtifacts(ruleContext));
  }

  /**
   * Returns information about the given rule's compilation artifacts. Dependencies specified in the
   * current rule's attributes are obtained via {@code ruleContext}. Output locations are determined
   * using the given {@code intermediateArtifacts} object. The fact that these are distinct objects
   * allows the caller to generate compilation actions pertaining to a configuration separate from
   * the current rule's configuration.
   */
  static CompilationArtifacts compilationArtifacts(
      RuleContext ruleContext, IntermediateArtifacts intermediateArtifacts) {
    return new CompilationArtifacts(ruleContext, intermediateArtifacts);
  }

  private final RuleContext ruleContext;
  private final BuildConfigurationValue buildConfiguration;
  private final AppleConfiguration appleConfiguration;
  private final CppSemantics cppSemantics;
  private final CompilationAttributes attributes;
  private final IntermediateArtifacts intermediateArtifacts;
  private final CcToolchainProvider toolchain;
  private Optional<CcCompilationContext> ccCompilationContext;

  @StarlarkMethod(name = "compilation_context", documented = false, structField = true)
  public CcCompilationContext getCcCompilationContext() {
    checkState(ccCompilationContext.isPresent());
    return ccCompilationContext.get();
  }

  /**
   * Creates a new compilation support for the given rule and build configuration.
   *
   * <p>All actions will be created under the given build configuration, which may be different than
   * the current rule context configuration.
   *
   * <p>The compilation and linking flags will be retrieved from the given compilation attributes.
   * The names of the generated artifacts will be retrieved from the given intermediate artifacts.
   *
   * <p>By instantiating multiple compilation supports for the same rule but with intermediate
   * artifacts with different output prefixes, multiple archives can be compiled for the same rule
   * context.
   */
  private CompilationSupport(
      RuleContext ruleContext,
      BuildConfigurationValue buildConfiguration,
      CppSemantics cppSemantics,
      IntermediateArtifacts intermediateArtifacts,
      CompilationAttributes compilationAttributes,
      CcToolchainProvider toolchain)
      throws RuleErrorException {
    this.ruleContext = ruleContext;
    this.buildConfiguration = buildConfiguration;
    this.appleConfiguration = buildConfiguration.getFragment(AppleConfiguration.class);
    this.cppSemantics = cppSemantics;
    this.attributes = compilationAttributes;
    this.intermediateArtifacts = intermediateArtifacts;
    this.ccCompilationContext = Optional.absent();
    if (toolchain == null
        && (ruleContext
                .attributes()
                .has(CcToolchain.CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME, BuildType.LABEL)
            || ruleContext
                .attributes()
                .has(
                    CcToolchain.CC_TOOLCHAIN_DEFAULT_ATTRIBUTE_NAME_FOR_STARLARK,
                    BuildType.LABEL))) {
      toolchain = CppHelper.getToolchainUsingDefaultCcToolchainAttribute(ruleContext);
    }

    this.toolchain = toolchain;
  }

  /** Builder for {@link CompilationSupport} */
  public static class Builder {
    private final RuleContext ruleContext;
    private final CppSemantics cppSemantics;
    private BuildConfigurationValue buildConfiguration;
    private IntermediateArtifacts intermediateArtifacts;
    private CompilationAttributes compilationAttributes;
    private CcToolchainProvider toolchain;

    public Builder(RuleContext ruleContext, CppSemantics cppSemantics) {
      this.ruleContext = ruleContext;
      this.cppSemantics = cppSemantics;
    }

    /** Sets the {@link BuildConfigurationValue} for the calling target. */
    @CanIgnoreReturnValue
    public Builder setConfig(BuildConfigurationValue buildConfiguration) {
      this.buildConfiguration = buildConfiguration;
      return this;
    }

    /** Sets {@link IntermediateArtifacts} for deriving artifact paths. */
    @CanIgnoreReturnValue
    public Builder setIntermediateArtifacts(IntermediateArtifacts intermediateArtifacts) {
      this.intermediateArtifacts = intermediateArtifacts;
      return this;
    }

    /** Sets {@link CompilationAttributes} for the calling target. */
    @CanIgnoreReturnValue
    public Builder setCompilationAttributes(CompilationAttributes compilationAttributes) {
      this.compilationAttributes = compilationAttributes;
      return this;
    }

    /**
     * Sets {@link CcToolchainProvider} for the calling target.
     *
     * <p>This is needed if it can't correctly be inferred directly from the rule context. Setting
     * to null causes the default to be used as if this was never called.
     */
    @CanIgnoreReturnValue
    public Builder setToolchainProvider(CcToolchainProvider toolchain) {
      this.toolchain = toolchain;
      return this;
    }

    /** Returns a {@link CompilationSupport} instance. */
    public CompilationSupport build() throws InterruptedException, RuleErrorException {
      if (buildConfiguration == null) {
        buildConfiguration = ruleContext.getConfiguration();
      }

      if (intermediateArtifacts == null) {
        intermediateArtifacts = new IntermediateArtifacts(ruleContext, buildConfiguration);
      }

      if (compilationAttributes == null) {
        compilationAttributes = CompilationAttributes.Builder.fromRuleContext(ruleContext).build();
      }

      return new CompilationSupport(
          ruleContext,
          buildConfiguration,
          cppSemantics,
          intermediateArtifacts,
          compilationAttributes,
          toolchain);
    }
  }

  /**
   * Validates compilation-related attributes on this rule.
   *
   * @return this compilation support
   * @throws RuleErrorException if there are attribute errors
   */
  @CanIgnoreReturnValue
  CompilationSupport validateAttributes() throws RuleErrorException {
    for (PathFragment absoluteInclude :
        Iterables.filter(attributes.includes().toList(), PathFragment::isAbsolute)) {
      ruleContext.attributeError(
          "includes", String.format(ABSOLUTE_INCLUDES_PATH_FORMAT, absoluteInclude));
    }

    if (ruleContext.attributes().has("srcs", BuildType.LABEL_LIST)) {
      ImmutableSet<Artifact> hdrsSet = attributes.hdrs().toSet();
      ImmutableSet<Artifact> srcsSet =
          ImmutableSet.copyOf(ruleContext.getPrerequisiteArtifacts("srcs").list());

      // Check for overlap between srcs and hdrs.
      for (Artifact header : Sets.intersection(hdrsSet, srcsSet)) {
        String path = header.getRootRelativePath().toString();
        ruleContext.attributeWarning(
            "srcs", String.format(FILE_IN_SRCS_AND_HDRS_WARNING_FORMAT, path));
      }

      // Check for overlap between srcs and non_arc_srcs.
      ImmutableSet<Artifact> nonArcSrcsSet =
          ImmutableSet.copyOf(ruleContext.getPrerequisiteArtifacts("non_arc_srcs").list());
      for (Artifact conflict : Sets.intersection(nonArcSrcsSet, srcsSet)) {
        String path = conflict.getRootRelativePath().toString();
        ruleContext.attributeError(
            "srcs", String.format(FILE_IN_SRCS_AND_NON_ARC_SRCS_ERROR_FORMAT, path));
      }
    }

    if (ruleContext.attributes().isAttributeValueExplicitlySpecified("module_name")
        && ruleContext.attributes().isAttributeValueExplicitlySpecified("module_map")) {
      ruleContext.attributeError("module_name", BOTH_MODULE_NAME_AND_MODULE_MAP_SPECIFIED);
    }

    ruleContext.assertNoErrors();
    return this;
  }

  private StrippingType getStrippingType(
      ExtraLinkArgs extraLinkArgs, FeatureConfiguration featureConfiguration) {
    if (Iterables.contains(extraLinkArgs, "-dynamiclib")
        || featureConfiguration.isEnabled(ObjcRuleClasses.LINK_DYLIB_FEATURE)) {
      return StrippingType.DYNAMIC_LIB;
    }
    if (Iterables.contains(extraLinkArgs, "-bundle")
        || featureConfiguration.isEnabled(ObjcRuleClasses.LINK_BUNDLE_FEATURE)) {
      return StrippingType.LOADABLE_BUNDLE;
    }
    if (Iterables.contains(extraLinkArgs, "-kext")) {
      return StrippingType.KERNEL_EXTENSION;
    }
    return StrippingType.DEFAULT;
  }

  /**
   * Returns the preferred static library for linking, or {@code null} if there is no static
   * library.
   *
   * @param library the input library.
   */
  @Nullable
  public static Artifact getStaticLibraryForLinking(LibraryToLink library) {
    if (library.getStaticLibrary() != null) {
      return library.getStaticLibrary();
    } else if (library.getPicStaticLibrary() != null) {
      return library.getPicStaticLibrary();
    } else {
      return null;
    }
  }

  /**
   * Returns the preferred variant of the library for linking.
   *
   * @param library the input library.
   */
  public static Artifact getLibraryForLinking(LibraryToLink library) {
    if (library.getStaticLibrary() != null) {
      return library.getStaticLibrary();
    } else if (library.getPicStaticLibrary() != null) {
      return library.getPicStaticLibrary();
    } else if (library.getInterfaceLibrary() != null) {
      return library.getInterfaceLibrary();
    } else {
      return library.getDynamicLibrary();
    }
  }

  private static Pair<ImmutableSet<Artifact>, ImmutableSet<Artifact>>
      classifyLibrariesFromCcLinkingContext(CcLinkingContext ccLinkingContext) {
    ImmutableList<LinkerInput> linkerInputs = ccLinkingContext.getLinkerInputs().toList();
    ImmutableSet.Builder<Artifact> alwaysLinkLibrariesBuilder = ImmutableSet.builder();
    for (LinkerInput linkerInput : linkerInputs) {
      for (LibraryToLink libraryToLink : linkerInput.getLibraries()) {
        if (libraryToLink.getAlwayslink()) {
          Artifact library = getLibraryForLinking(libraryToLink);
          alwaysLinkLibrariesBuilder.add(library);
        }
      }
    }
    ImmutableSet<Artifact> alwaysLinkLibraries = alwaysLinkLibrariesBuilder.build();

    ImmutableSet.Builder<Artifact> asNeededlibrariesBuilder = ImmutableSet.builder();
    for (LinkerInput linkerInput : linkerInputs) {
      for (LibraryToLink libraryToLink : linkerInput.getLibraries()) {
        if (!libraryToLink.getAlwayslink()) {
          Artifact library = getLibraryForLinking(libraryToLink);
          if (!alwaysLinkLibraries.contains(library)) {
            asNeededlibrariesBuilder.add(library);
          }
        }
      }
    }
    return Pair.of(asNeededlibrariesBuilder.build(), alwaysLinkLibraries);
  }

  private static ImmutableList<String> dedupSdkLinkopts(NestedSet<LinkOptions> linkopts) {
    HashSet<String> duplicates = new HashSet<>();
    ImmutableList.Builder<String> finalLinkopts = ImmutableList.builder();

    for (LinkOptions linkOptions : linkopts.toList()) {
      ImmutableList<String> args = linkOptions.get();
      for (Iterator<String> iterator = args.iterator(); iterator.hasNext(); ) {
        String arg = iterator.next();
        if (iterator.hasNext() && (arg.equals("-framework") || arg.equals("-weak_framework"))) {
          String framework = iterator.next();
          String key = arg.charAt(1) + framework;
          if (!duplicates.contains(key)) {
            finalLinkopts.add(arg, framework);
            duplicates.add(key);
          }
        } else if (arg.startsWith("-Wl,-framework,") || arg.startsWith("-Wl,-weak_framework,")) {
          String framework = arg.split(",", -1)[2];
          String key = arg.charAt(5) + framework;
          if (!duplicates.contains(key)) {
            finalLinkopts.add(arg.split(",", -1)[1], framework);
            duplicates.add(key);
          }
        } else if (arg.startsWith("-l")) {
          if (!duplicates.contains(arg)) {
            finalLinkopts.add(arg);
            duplicates.add(arg);
          }
        } else {
          finalLinkopts.add(arg);
        }
      }
    }

    return finalLinkopts.build();
  }

  /**
   * Registers any actions necessary to link this rule and its dependencies. Automatically infers
   * the toolchain from the configuration of this CompilationSupport.
   *
   * <p>Dsym bundle is generated if {@link CppConfiguration#appleGenerateDsym()} is set.
   *
   * <p>When Bazel flags {@code --compilation_mode=opt} and {@code --objc_enable_binary_stripping}
   * are specified, additional optimizations will be performed on the linked binary: all-symbol
   * stripping (using {@code /usr/bin/strip}) and dead-code stripping (using linker flags: {@code
   * -dead_strip}).
   *
   * @param linkingInfoProvider the CcLinkingContext with most of the dependency information
   *     required for linking.
   * @param secondaryObjcProvider the ObjcProvider that provides secondary linking info.
   * @param j2ObjcMappingFileProvider contains mapping files for j2objc transpilation
   * @param j2ObjcEntryClassProvider contains j2objc entry class information for dead code removal
   * @param extraLinkArgs any additional arguments to pass to the linker
   * @param extraLinkInputs any additional input artifacts to pass to the link action
   * @param userVariablesExtension the UserVariablesExtension to pass to the linker action
   * @return this compilation support
   */
  @CanIgnoreReturnValue
  public CompilationSupport registerLinkActions(
      CcLinkingContext linkingInfoProvider,
      ObjcProvider secondaryLinkingInfoProvider,
      StarlarkInfo j2ObjcMappingFileProvider,
      StarlarkInfo j2ObjcEntryClassProvider,
      ExtraLinkArgs extraLinkArgs,
      Iterable<Artifact> extraLinkInputs,
      Iterable<String> extraRequestedFeatures,
      Iterable<String> extraDisabledFeatures,
      boolean isStampingEnabled,
      UserVariablesExtension userVariablesExtension)
      throws InterruptedException, RuleErrorException, EvalException {
    // We need to split input libraries into those that require -force_load and those that don't.
    // Clang loads archives specified in filelists and also specified as -force_load twice,
    // resulting in duplicate symbol errors unless they are deduped.
    Pair<ImmutableSet<Artifact>, ImmutableSet<Artifact>> inputLibrarySet =
        classifyLibrariesFromCcLinkingContext(linkingInfoProvider);

    ImmutableSet<Artifact> asNeededLibrarySet = inputLibrarySet.first;
    ImmutableSet<Artifact> alwaysLinkLibrarySet = inputLibrarySet.second;

    if (stripJ2ObjcDeadCode(j2ObjcEntryClassProvider)
        && !secondaryLinkingInfoProvider.get(ObjcProvider.J2OBJC_LIBRARY).toList().isEmpty()) {
      registerJ2ObjcDeadCodeRemovalActions(
          secondaryLinkingInfoProvider, j2ObjcMappingFileProvider, j2ObjcEntryClassProvider);

      asNeededLibrarySet =
          substituteJ2ObjcPrunedLibraries(asNeededLibrarySet, secondaryLinkingInfoProvider);
      alwaysLinkLibrarySet =
          substituteJ2ObjcPrunedLibraries(alwaysLinkLibrarySet, secondaryLinkingInfoProvider);
    }

    ImmutableList<Artifact> asNeededLibraryList = asNeededLibrarySet.asList();
    ImmutableList<Artifact> alwaysLinkLibraryList = alwaysLinkLibrarySet.asList();

    // Passing large numbers of inputs on the command line triggers a bug in Apple's Clang
    // (b/29094356), so we'll create an input list manually and pass -filelist path/to/input/list.
    // We can't populate this list yet--it needs to contain any linkstamp objects, which we won't
    // know about until we actually create the CppLinkAction--but it needs to go into the
    // CppLinkAction too, so create it now.
    Artifact inputFileList = intermediateArtifacts.linkerObjList();

    ImmutableSet<String> allRequestedFeatures =
        new ImmutableSet.Builder<String>()
            .addAll(ruleContext.getFeatures())
            .addAll(extraRequestedFeatures)
            .build();
    ImmutableSet<String> allDisabledFeatures =
        new ImmutableSet.Builder<String>()
            .addAll(ruleContext.getDisabledFeatures())
            .addAll(extraDisabledFeatures)
            .build();
    FeatureConfiguration featureConfiguration =
        CcCommon.configureFeaturesOrReportRuleError(
            ruleContext,
            buildConfiguration,
            allRequestedFeatures,
            allDisabledFeatures,
            Language.OBJC,
            toolchain,
            cppSemantics);

    ImmutableList<Artifact> staticRuntimes;
    try {
      staticRuntimes = toolchain.getStaticRuntimeLinkInputs(featureConfiguration).toList();
    } catch (EvalException e) {
      throw ruleContext.throwWithRuleError(e);
    }

    ObjcVariablesExtension.Builder extensionBuilder =
        new ObjcVariablesExtension.Builder()
            .setRuleContext(ruleContext)
            .setIntermediateArtifacts(intermediateArtifacts)
            .setForceLoadArtifacts(alwaysLinkLibrarySet)
            .setAttributeLinkopts(attributes.linkopts())
            .setDepLinkopts(dedupSdkLinkopts(linkingInfoProvider.getUserLinkFlags()))
            .addVariableCategory(VariableCategory.EXECUTABLE_LINKING_VARIABLES);

    Artifact binaryToLink = getBinaryToLink();

    Label binaryLabel = null;
    try {
      binaryLabel =
          Label.create(ruleContext.getLabel().getPackageIdentifier(), binaryToLink.getFilename());
    } catch (LabelSyntaxException e) {
      // Formed from existing label, just replacing name with artifact name.
    }

    CppConfiguration cppConfiguration = buildConfiguration.getFragment(CppConfiguration.class);
    CcLinkingHelper executableLinkingHelper =
        new CcLinkingHelper(
                ruleContext,
                binaryLabel,
                ruleContext,
                ruleContext,
                cppSemantics,
                featureConfiguration,
                toolchain,
                toolchain.getFdoContext(),
                buildConfiguration,
                cppConfiguration,
                ruleContext.getSymbolGenerator(),
                TargetUtils.getExecutionInfo(
                    ruleContext.getRule(), ruleContext.isAllowTagsPropagation()))
            .setIsStampingEnabled(isStampingEnabled)
            .setTestOrTestOnlyTarget(ruleContext.isTestOnlyTarget() || ruleContext.isTestTarget())
            .addNonCodeLinkerInputs(asNeededLibraryList)
            .addNonCodeLinkerInputs(alwaysLinkLibraryList)
            .addNonCodeLinkerInputs(linkingInfoProvider.getNonCodeInputs().toList())
            .addNonCodeLinkerInputs(ImmutableList.copyOf(extraLinkInputs))
            .addNonCodeLinkerInputs(ImmutableList.copyOf(attributes.linkInputs()))
            .addNonCodeLinkerInputs(ImmutableList.of(inputFileList))
            .addVariableExtension(userVariablesExtension)
            .setShouldCreateStaticLibraries(false)
            .setDynamicLinkType(LinkTargetType.OBJC_EXECUTABLE)
            .setLinkingMode(LinkingMode.STATIC)
            .addLinkopts(ImmutableList.copyOf(extraLinkArgs));

    ImmutableList.Builder<Artifact> linkerOutputs = ImmutableList.builder();

    if (cppConfiguration.appleGenerateDsym()) {
      Artifact dsymSymbol =
          cppConfiguration.objcShouldStripBinary()
              ? intermediateArtifacts.dsymSymbolForUnstrippedBinary()
              : intermediateArtifacts.dsymSymbolForStrippedBinary();
      extensionBuilder
          .setDsymSymbol(dsymSymbol)
          .addVariableCategory(VariableCategory.DSYM_VARIABLES);
      linkerOutputs.add(dsymSymbol);
    }

    if (cppConfiguration.objcGenerateLinkmap()) {
      Artifact linkmap = intermediateArtifacts.linkmap();
      extensionBuilder.setLinkmap(linkmap).addVariableCategory(VariableCategory.LINKMAP_VARIABLES);
      linkerOutputs.add(linkmap);
    }

    executableLinkingHelper.addVariableExtension(extensionBuilder.build());

    executableLinkingHelper.addLinkerOutputs(linkerOutputs.build());

    CcLinkingContext linkstamps =
        CcLinkingContext.builder()
            .addLinkstamps(linkingInfoProvider.getLinkstamps().toList())
            .build();
    executableLinkingHelper.addCcLinkingContexts(ImmutableList.of(linkstamps));

    executableLinkingHelper.link(CcCompilationOutputs.EMPTY);

    ImmutableCollection<Artifact> linkstampValues =
        CppLinkActionBuilder.mapLinkstampsToOutputs(
                linkstamps.getLinkstamps().toSet(),
                ruleContext,
                ruleContext.getRepository(),
                buildConfiguration,
                binaryToLink,
                CppLinkAction.DEFAULT_ARTIFACT_FACTORY)
            .values();

    // Populate the input file list with both the compiled object files and any linkstamp object
    // files.
    registerObjFilelistAction(
        ImmutableSet.<Artifact>builder()
            .addAll(asNeededLibraryList)
            .addAll(staticRuntimes)
            .addAll(linkstampValues)
            .build(),
        inputFileList);

    if (cppConfiguration.objcShouldStripBinary()) {
      registerBinaryStripAction(
          binaryToLink, getStrippingType(extraLinkArgs, featureConfiguration));
    }

    return this;
  }

  /**
   * Registers an action that writes given set of object files to the given objList. This objList is
   * suitable to signal symbols to archive in a libtool archiving invocation.
   */
  // TODO(ulfjack): Use NestedSet for objFiles.
  @CanIgnoreReturnValue
  private CompilationSupport registerObjFilelistAction(
      ImmutableSet<Artifact> objFiles, Artifact objList) {
    CustomCommandLine.Builder objFilesToLinkParam = new CustomCommandLine.Builder();
    NestedSetBuilder<Artifact> treeObjFiles = NestedSetBuilder.stableOrder();

    for (Artifact objFile : objFiles) {
      // If the obj file is a tree artifact, we need to expand it into the contained individual
      // files properly.
      if (objFile.isTreeArtifact()) {
        treeObjFiles.add(objFile);
        objFilesToLinkParam.addExpandedTreeArtifactExecPaths(objFile);
      } else {
        objFilesToLinkParam.addPath(objFile.getExecPath());
      }
    }

    ruleContext.registerAction(
        new ParameterFileWriteAction(
            ruleContext.getActionOwner(),
            treeObjFiles.build(),
            objList,
            objFilesToLinkParam.build(),
            ParameterFile.ParameterFileType.UNQUOTED));
    return this;
  }

  private <T> NestedSet<T> getField(StarlarkInfo provider, String fieldName, Class<T> type)
      throws EvalException {
    return Depset.cast(provider.getValue(fieldName), type, fieldName);
  }

  /** Returns true if this build should strip J2Objc dead code. */
  private boolean stripJ2ObjcDeadCode(StarlarkInfo j2ObjcEntryClassProvider) throws EvalException {
    J2ObjcConfiguration j2objcConfiguration =
        buildConfiguration.getFragment(J2ObjcConfiguration.class);
    NestedSet<String> entryClasses =
        getField(j2ObjcEntryClassProvider, "entry_classes", String.class);

    // Only perform J2ObjC dead code stripping if flag --j2objc_dead_code_removal is specified and
    // users have specified entry classes.
    return j2objcConfiguration.removeDeadCode() && !entryClasses.isEmpty();
  }

  /** Registers actions to perform J2Objc dead code removal. */
  private void registerJ2ObjcDeadCodeRemovalActions(
      ObjcProvider objcProvider,
      StarlarkInfo j2ObjcMappingFileProvider,
      StarlarkInfo j2ObjcEntryClassProvider)
      throws EvalException {
    NestedSet<String> entryClasses =
        getField(j2ObjcEntryClassProvider, "entry_classes", String.class);
    NestedSet<Artifact> j2ObjcDependencyMappingFiles =
        getField(j2ObjcMappingFileProvider, "dependency_mapping_files", Artifact.class);
    NestedSet<Artifact> j2ObjcHeaderMappingFiles =
        getField(j2ObjcMappingFileProvider, "header_mapping_files", Artifact.class);
    NestedSet<Artifact> j2ObjcArchiveSourceMappingFiles =
        getField(j2ObjcMappingFileProvider, "archive_source_mapping_files", Artifact.class);

    for (Artifact j2objcArchive : objcProvider.get(ObjcProvider.J2OBJC_LIBRARY).toList()) {
      Artifact prunedJ2ObjcArchive = intermediateArtifacts.j2objcPrunedArchive(j2objcArchive);
      Artifact dummyArchive =
          getLibraryForLinking(
              ruleContext
                  .getPrerequisite("$dummy_lib", CcInfo.PROVIDER)
                  .getCcLinkingContext()
                  .getLibraries()
                  .getSingleton());

      CustomCommandLine commandLine =
          CustomCommandLine.builder()
              .addExecPath("--input_archive", j2objcArchive)
              .addExecPath("--output_archive", prunedJ2ObjcArchive)
              .addExecPath("--dummy_archive", dummyArchive)
              .addExecPaths(
                  "--dependency_mapping_files",
                  VectorArg.join(",").each(j2ObjcDependencyMappingFiles))
              .addExecPaths(
                  "--header_mapping_files", VectorArg.join(",").each(j2ObjcHeaderMappingFiles))
              .addExecPaths(
                  "--archive_source_mapping_files",
                  VectorArg.join(",").each(j2ObjcArchiveSourceMappingFiles))
              .add("--entry_classes")
              .addAll(VectorArg.join(",").each(entryClasses))
              .build();

      ruleContext.registerAction(
          new SpawnAction.Builder()
              .setMnemonic("DummyPruner")
              .setExecutable(ruleContext.getExecutablePrerequisite("$j2objc_dead_code_pruner"))
              .addInput(dummyArchive)
              .addInput(j2objcArchive)
              .addTransitiveInputs(j2ObjcDependencyMappingFiles)
              .addTransitiveInputs(j2ObjcHeaderMappingFiles)
              .addTransitiveInputs(j2ObjcArchiveSourceMappingFiles)
              .addCommandLine(
                  commandLine,
                  ParamFileInfo.builder(ParameterFile.ParameterFileType.UNQUOTED)
                      .setCharset(ISO_8859_1)
                      .setUseAlways(true)
                      .build())
              .addOutput(prunedJ2ObjcArchive)
              .setExecGroup("j2objc")
              .build(ruleContext));
    }
  }

  /** Returns a set of libraries with all unpruned J2ObjC libraries substituted with pruned ones. */
  private ImmutableSet<Artifact> substituteJ2ObjcPrunedLibraries(
      ImmutableSet<Artifact> originalLibraries, ObjcProvider objcProvider) {
    ImmutableSet.Builder<Artifact> libraries = new ImmutableSet.Builder<>();

    Set<Artifact> unprunedJ2ObjcLibs = objcProvider.get(ObjcProvider.J2OBJC_LIBRARY).toSet();
    for (Artifact library : originalLibraries) {
      // If we match an unpruned J2ObjC library, add the pruned version of the J2ObjC static library
      // instead.
      if (unprunedJ2ObjcLibs.contains(library)) {
        libraries.add(intermediateArtifacts.j2objcPrunedArchive(library));
      } else {
        libraries.add(library);
      }
    }
    return libraries.build();
  }

  /** Returns the artifact that should be the outcome of this build's link action */
  private Artifact getBinaryToLink() {

    // When compilation_mode=opt and objc_enable_binary_stripping are specified, the unstripped
    // binary containing debug symbols is generated by the linker, which also needs the debug
    // symbols for dead-code removal. The binary is also used to generate dSYM bundle if
    // --apple_generate_dsym is specified. A symbol strip action is later registered to strip
    // the symbol table from the unstripped binary.
    CppConfiguration cppConfiguration = buildConfiguration.getFragment(CppConfiguration.class);
    return cppConfiguration.objcShouldStripBinary()
        ? intermediateArtifacts.unstrippedSingleArchitectureBinary()
        : intermediateArtifacts.strippedSingleArchitectureBinary();
  }

  private static CommandLine symbolStripCommandLine(
      ImmutableList<String> extraFlags, Artifact unstrippedArtifact, Artifact strippedArtifact) {
    return CustomCommandLine.builder()
        .add("/usr/bin/xcrun")
        .add(STRIP)
        .addAll(extraFlags)
        .addExecPath("-o", strippedArtifact)
        .addPath(unstrippedArtifact.getExecPath())
        .build();
  }

  /** Signals if stripping should include options for dynamic libraries. */
  private enum StrippingType {
    DEFAULT,
    DYNAMIC_LIB,
    LOADABLE_BUNDLE,
    KERNEL_EXTENSION
  }

  /**
   * Registers an action that uses the 'strip' tool to perform binary stripping on the given binary
   * subject to the given {@link StrippingType}.
   */
  private void registerBinaryStripAction(Artifact binaryToLink, StrippingType strippingType) {
    final ImmutableList<String> stripArgs;
    switch (strippingType) {
      case DYNAMIC_LIB:
      case LOADABLE_BUNDLE:
      case KERNEL_EXTENSION:
        // For dylibs, loadable bundles, and kexts, must strip only local symbols.
        stripArgs = ImmutableList.of("-x");
        break;
      case DEFAULT:
        stripArgs = ImmutableList.<String>of();
        break;
      default:
        throw new IllegalArgumentException("Unsupported stripping type " + strippingType);
    }

    Artifact strippedBinary = intermediateArtifacts.strippedSingleArchitectureBinary();

    ruleContext.registerAction(
        ObjcRuleClasses.spawnAppleEnvActionBuilder(
                XcodeConfigInfo.fromRuleContext(ruleContext),
                appleConfiguration.getSingleArchPlatform())
            .setMnemonic("ObjcBinarySymbolStrip")
            .addCommandLine(symbolStripCommandLine(stripArgs, binaryToLink, strippedBinary))
            .addOutput(strippedBinary)
            .addInput(binaryToLink)
            .build(ruleContext));
  }

  public static Optional<Artifact> getCustomModuleMap(RuleContext ruleContext) {
    if (ruleContext.attributes().has("module_map", BuildType.LABEL)) {
      return Optional.fromNullable(ruleContext.getPrerequisiteArtifact("module_map"));
    }
    return Optional.absent();
  }
}
