// Copyright 2016 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.android;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.devtools.build.lib.actions.ParameterFile.ParameterFileType.UNQUOTED;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;
import static com.google.devtools.build.lib.packages.BuildType.NODEP_LABEL;
import static com.google.devtools.build.lib.packages.BuildType.TRISTATE;
import static com.google.devtools.build.lib.packages.StarlarkProviderIdentifier.forKey;
import static com.google.devtools.build.lib.packages.Type.INTEGER;
import static com.google.devtools.build.lib.rules.android.AndroidCommon.getAndroidConfig;
import static com.google.devtools.build.lib.rules.android.AndroidSdkProvider.ANDROID_SDK_TOOLCHAIN_TYPE_ATTRIBUTE_NAME;

import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import com.google.devtools.build.lib.actions.ActionConflictException;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ExecutionRequirements;
import com.google.devtools.build.lib.actions.ParamFileInfo;
import com.google.devtools.build.lib.analysis.Allowlist;
import com.google.devtools.build.lib.analysis.ConfiguredAspect;
import com.google.devtools.build.lib.analysis.ConfiguredAspectFactory;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
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.SpawnAction;
import com.google.devtools.build.lib.analysis.config.ExecutionTransitionFactory;
import com.google.devtools.build.lib.analysis.config.ToolchainTypeRequirement;
import com.google.devtools.build.lib.analysis.platform.ToolchainInfo;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.packages.AspectDefinition;
import com.google.devtools.build.lib.packages.AspectParameters;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.NativeAspectClass;
import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.packages.TriState;
import com.google.devtools.build.lib.rules.java.JavaCommon;
import com.google.devtools.build.lib.rules.java.JavaInfo;
import com.google.devtools.build.lib.rules.java.JavaRuleOutputJarsProvider.JavaOutput;
import com.google.devtools.build.lib.rules.proto.ProtoInfo;
import com.google.devtools.build.lib.rules.proto.ProtoLangToolchainProvider;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationConstant;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import javax.annotation.Nullable;

/** Aspect to {@link DexArchiveProvider build .dex Archives} from Jars. */
public class DexArchiveAspect extends NativeAspectClass implements ConfiguredAspectFactory {
  public static final String NAME = "DexArchiveAspect";

  /**
   * Function that returns a {@link Rule}'s {@code incremental_dexing} attribute for use by this
   * aspect. Must be provided when attaching this aspect to a target.
   */
  @SerializationConstant
  public static final Function<Rule, AspectParameters> PARAM_EXTRACTOR =
      (Rule rule) -> {
        AttributeMap attributes = NonconfigurableAttributeMapper.of(rule);
        AspectParameters.Builder result = new AspectParameters.Builder();
        TriState incrementalAttr = attributes.get("incremental_dexing", TRISTATE);
        result.addAttribute("incremental_dexing", incrementalAttr.name());
        result.addAttribute(
            "min_sdk_version", attributes.get("min_sdk_version", INTEGER).toString());
        result.addAttribute("toprule_kind", rule.getRuleClass());
        return result.build();
      };

  /**
   * Function that limits this aspect to Java 8 desugaring (disabling incremental dexing) when
   * attaching this aspect to a target. This is intended for implicit attributes like the stub APKs
   * for {@code bazel mobile-install}.
   */
  @SerializationConstant
  static final Function<Rule, AspectParameters> ONLY_DESUGAR_JAVA8 =
      (Rule rule) ->
          new AspectParameters.Builder()
              .addAttribute("incremental_dexing", TriState.NO.name())
              .build();
  /** Aspect-only label for dexbuidler executable, to avoid name clashes with labels on rules. */
  private static final String ASPECT_DEXBUILDER_PREREQ = "$dex_archive_dexbuilder";
  /** Aspect-only label for desugaring executable, to avoid name clashes with labels on rules. */
  private static final String ASPECT_DESUGAR_PREREQ = "$aspect_desugar";

  private static final ImmutableList<String> TRANSITIVE_ATTRIBUTES =
      ImmutableList.of(
          "deps",
          "exports",
          "runtime_deps",
          // Propagate the aspect down legacy toolchain dependencies. This won't work for platform-
          // based toolchains, which aren't connected to an attribute. See
          // propagateDownLegacyToolchain for how this distinction is handled.
          ":android_sdk",
          "aidl_lib", // for the aidl runtime in the android_sdk rule
          "$toolchain", // this is _toolchain in Starlark rules (b/78647825)
          "$build_stamp_deps", // for build stamp runtime class deps
          "$build_stamp_mergee_manifest_lib", // for empty build stamp Service class implementation
          // To get from proto_library through proto_lang_toolchain rule to proto runtime library.
          ":aspect_proto_toolchain_for_javalite",
          "runtime");

  private static final FlagMatcher DEXOPTS_SUPPORTED_IN_DEXBUILDER =
      new FlagMatcher(
          ImmutableList.of("--no-locals", "--no-optimize", "--no-warnings", "--positions"));

  private final RepositoryName toolsRepository;
  private final String sdkToolchainLabel;

  public DexArchiveAspect(RepositoryName toolsRepository, String sdkToolchainLabel) {
    this.toolsRepository = toolsRepository;
    this.sdkToolchainLabel = sdkToolchainLabel;
  }

  @Override
  public AspectDefinition getDefinition(AspectParameters params) {
    Label toolchainType = Label.parseCanonicalUnchecked(toolsRepository + sdkToolchainLabel);
    AspectDefinition.Builder result =
        new AspectDefinition.Builder(this)
            .requireStarlarkProviders(forKey(JavaInfo.PROVIDER.getKey()))
            // Latch onto Starlark toolchains in case they have a "runtime" (b/78647825)
            .requireStarlarkProviders(forKey(ToolchainInfo.PROVIDER.getKey()))
            // For android_sdk rules, where we just want to get at aidl runtime deps.
            .requireStarlarkProviders(forKey(AndroidSdkProvider.PROVIDER.getKey()))
            .requireStarlarkProviders(forKey(ProtoInfo.PROVIDER.getKey()))
            .requireStarlarkProviderSets(
                ImmutableList.of(
                    // For proto_lang_toolchain rules, where we just want to get at their runtime
                    // deps.
                    ImmutableSet.of(ProtoLangToolchainProvider.PROVIDER_ID)))
            .add(attr(ANDROID_SDK_TOOLCHAIN_TYPE_ATTRIBUTE_NAME, NODEP_LABEL).value(toolchainType))
            .addToolchainTypes(
                ToolchainTypeRequirement.builder(toolchainType).mandatory(true).build())
            // Parse labels since we don't have RuleDefinitionEnvironment.getLabel like in a rule
            .add(
                attr(ASPECT_DESUGAR_PREREQ, LABEL)
                    .cfg(ExecutionTransitionFactory.createFactory())
                    .exec()
                    .value(
                        Label.parseCanonicalUnchecked(
                            toolsRepository + "//tools/android:desugar_java8")))
            // Access to --android_sdk so we can stub in a bootclasspath for desugaring if missing
            // Remove this entirely when we remove --android_sdk support.
            .add(
                attr(":dex_archive_android_sdk", LABEL)
                    .allowedRuleClasses("android_sdk", "filegroup")
                    .value(
                        AndroidRuleClasses.getAndroidSdkLabel(
                            Label.parseCanonicalUnchecked(
                                toolsRepository + AndroidRuleClasses.DEFAULT_SDK))))
            .add(
                Allowlist.getAttributeFromAllowlistName("enable_starlark_dex_desugar_proguard")
                    .value(
                        Label.parseCanonicalUnchecked(
                            toolsRepository
                                + "//tools/allowlists/android_binary_allowlist:enable_starlark_dex_desugar_proguard")))
            .requiresConfigurationFragments(AndroidConfiguration.class)
            .requireAspectsWithProviders(
                ImmutableList.of(ImmutableSet.of(forKey(JavaInfo.PROVIDER.getKey()))));
    if (TriState.valueOf(params.getOnlyValueOfAttribute("incremental_dexing")) != TriState.NO) {
      // Marginally improves "query2" precision for targets that disable incremental dexing
      result.add(
          attr(ASPECT_DEXBUILDER_PREREQ, LABEL)
              .cfg(ExecutionTransitionFactory.createFactory())
              .exec()
              .value(
                  Label.parseCanonicalUnchecked(toolsRepository + "//tools/android:dexbuilder")));
    }
    for (String attr : TRANSITIVE_ATTRIBUTES) {
      result.propagateAlongAttribute(attr);
    }
    return result.build();
  }

  /**
   * Returns toolchain .jars that need dexing for platform-based toolchains.
   *
   * <p>Legacy toolchains handle these .jars recursively by propagating the aspect down the
   * ":android_sdk" attribute. So they don't need this method.
   */
  private static ImmutableList<Artifact> getPlatformBasedToolchainJars(RuleContext ruleContext)
      throws RuleErrorException {
    if (!ruleContext.attributes().has(":android_sdk")) {
      // If we're dexing a non-Android target (like a java_library), there's no Android toolchain to
      // include.
      return ImmutableList.of();
    }

    AndroidSdkProvider androidSdk = AndroidSdkProvider.fromRuleContext(ruleContext);
    if (androidSdk == null || androidSdk.getAidlLib() == null) {
      // If the Android SDK is null, we don't have a valid toolchain. Expect a rule error reported
      // from AndroidSdkProvider.
      return ImmutableList.of();
    }
    return ImmutableList.copyOf(
        JavaInfo.getJavaInfo(androidSdk.getAidlLib()).getDirectRuntimeJars());
  }

  @Override
  @Nullable
  public ConfiguredAspect create(
      Label targetLabel,
      ConfiguredTarget ct,
      RuleContext ruleContext,
      AspectParameters params,
      RepositoryName toolsRepository)
      throws InterruptedException, ActionConflictException {

    ConfiguredAspect.Builder result = new ConfiguredAspect.Builder(ruleContext);

    // No-op out of the aspect in the android_binary rule if the Starlark dex/desugar will execute
    // to avoid registering duplicate actions and bloating memory.
    if (!params.getAttribute("toprule_kind").isEmpty()
        && params.getOnlyValueOfAttribute("toprule_kind").equals("android_binary")
        && Allowlist.hasAllowlist(ruleContext, "enable_starlark_dex_desugar_proguard")
        && Allowlist.isAvailable(ruleContext, "enable_starlark_dex_desugar_proguard")) {
      return result.build();
    }

    int minSdkVersion = 0;
    if (!params.getAttribute("min_sdk_version").isEmpty()) {
      minSdkVersion = Integer.valueOf(params.getOnlyValueOfAttribute("min_sdk_version"));
    }

    Function<Artifact, Artifact> desugaredJars;
    ImmutableList<Artifact> extraToolchainJars;
    ImmutableCollection<Artifact> runtimeJars;
    try {
      extraToolchainJars = getPlatformBasedToolchainJars(ruleContext);
      desugaredJars =
          desugarJarsIfRequested(ct, ruleContext, minSdkVersion, result, extraToolchainJars);
      runtimeJars = getProducedRuntimeJars(ct, ruleContext, extraToolchainJars);
    } catch (RuleErrorException e) {
      ruleContext.ruleError(e.getMessage());
      return null;
    }

    TriState incrementalAttr =
        TriState.valueOf(params.getOnlyValueOfAttribute("incremental_dexing"));
    if (incrementalAttr == TriState.NO
        || (!getAndroidConfig(ruleContext).useIncrementalDexing()
            && incrementalAttr == TriState.AUTO)) {
      // Dex archives will never be used, so don't bother setting them up.
      return result.build();
    }

    if (JavaCommon.isNeverLink(ruleContext)) {
      return result.addProvider(DexArchiveProvider.NEVERLINK).build();
    }

    DexArchiveProvider.Builder dexArchives = new DexArchiveProvider.Builder();
    collectPrerequisites(
        ruleContext, DexArchiveProvider.class, dexArchives::addTransitiveProviders);
    if (runtimeJars != null) {
      boolean basenameClash = checkBasenameClash(runtimeJars);
      Set<Set<String>> aspectDexopts = aspectDexopts(ruleContext);
      String minSdkFilenamePart = minSdkVersion > 0 ? "--min_sdk_version=" + minSdkVersion : "";
      for (Artifact jar : runtimeJars) {
        Artifact desugaredJar = desugaredJars.apply(jar);
        for (Set<String> incrementalDexopts : aspectDexopts) {
          // Since we're potentially dexing the same jar multiple times with different flags, we
          // need to write unique artifacts for each flag combination. Here, it is convenient to
          // distinguish them by putting the flags that were used for creating the artifacts into
          // their filenames. Since min_sdk_version is a parameter to the aspect from the
          // android_binary target that the aspect originates from, it's handled separately so that
          // the correct min sdk value is used.
          String uniqueFilename =
              (basenameClash ? jar.getRootRelativePathString() : jar.getFilename())
                  + Joiner.on("").join(incrementalDexopts)
                  + minSdkFilenamePart
                  + ".dex.zip";
          Artifact dexArchive =
              createDexArchiveAction(
                  ruleContext,
                  ASPECT_DEXBUILDER_PREREQ,
                  desugaredJar,
                  incrementalDexopts,
                  minSdkVersion,
                  AndroidBinary.getDxArtifact(ruleContext, uniqueFilename));
          dexArchives.addDexArchive(incrementalDexopts, dexArchive, jar);
        }
      }
    }
    return result.addProvider(dexArchives.build()).build();
  }

  /**
   * Runs Jars in {@link JavaInfo#getDirectRuntimeJars()} through desugaring action if flag is set
   * and adds the result to {@code result}. Note that this cannot happen in a separate aspect
   * because aspects don't see providers added by other aspects executed on the same target.
   */
  private Function<Artifact, Artifact> desugarJarsIfRequested(
      ConfiguredTarget base,
      RuleContext ruleContext,
      int minSdkVersion,
      ConfiguredAspect.Builder result,
      Iterable<Artifact> extraToolchainJars)
      throws RuleErrorException {
    if (!getAndroidConfig(ruleContext).desugarJava8()) {
      return Functions.identity();
    }
    Map<Artifact, Artifact> newlyDesugared = new HashMap<>();
    if (JavaCommon.isNeverLink(ruleContext)) {
      result.addProvider(AndroidRuntimeJarProvider.NEVERLINK);
      return Functions.forMap(newlyDesugared);
    }
    AndroidRuntimeJarProvider.Builder desugaredJars = new AndroidRuntimeJarProvider.Builder();
    collectPrerequisites(
        ruleContext, AndroidRuntimeJarProvider.class, desugaredJars::addTransitiveProviders);
    if (isProtoLibrary(ruleContext)) {
      // TODO(b/33557068): Desugar protos if needed instead of assuming they don't need desugaring
      result.addProvider(desugaredJars.build());
      return Functions.identity();
    }

    JavaInfo javaInfo = JavaInfo.getJavaInfo(base);
    if (javaInfo != null) {
      // These are all transitive hjars of dependencies and hjar of the jar itself
      NestedSet<Artifact> compileTimeClasspath = JavaInfo.transitiveCompileTimeJars(base);
      ImmutableSet.Builder<Artifact> jars = ImmutableSet.builder();
      jars.addAll(javaInfo.getDirectRuntimeJars());

      Artifact rJar = getAndroidLibraryRJar(base);
      if (rJar != null) {
        // TODO(b/124540821): Disable R.jar desugaring (with a flag).
        jars.add(rJar);
      }

      Artifact buildStampJar = getAndroidBuildStampJar(base);
      if (buildStampJar != null) {
        jars.add(buildStampJar);
      }

      // For android_* targets we need to honor their bootclasspath (nicer in general to do so)
      NestedSet<Artifact> bootclasspath = getBootclasspath(base, ruleContext);

      jars.addAll(extraToolchainJars);
      ImmutableSet<Artifact> jarsToProcess = jars.build();
      boolean basenameClash = checkBasenameClash(jarsToProcess);
      for (Artifact jar : jarsToProcess) {
        Artifact desugared =
            createDesugarAction(
                ruleContext,
                basenameClash,
                jar,
                bootclasspath,
                compileTimeClasspath,
                minSdkVersion);
        newlyDesugared.put(jar, desugared);
        desugaredJars.addDesugaredJar(jar, desugared);
      }
    }
    result.addProvider(desugaredJars.build());

    return key -> {
      if (newlyDesugared.containsKey(key)) {
        return newlyDesugared.get(key);
      }
      // Fall back to the original un-desugared artifact.
      return key;
    };
  }

  @Nullable
  private static ImmutableCollection<Artifact> getProducedRuntimeJars(
      ConfiguredTarget base, RuleContext ruleContext, Iterable<Artifact> extraToolchainJars)
      throws RuleErrorException {
    if (isProtoLibrary(ruleContext)) {
      if (!ruleContext.getPrerequisites("srcs").isEmpty()) {
        JavaInfo javaInfo = JavaInfo.getJavaInfo(base);
        if (javaInfo != null) {
          return javaInfo.getJavaOutputs().stream()
              .map(JavaOutput::getClassJar)
              .collect(toImmutableList());
        }
      }
    } else {
      ImmutableSet.Builder<Artifact> jars = ImmutableSet.builder();
      JavaInfo javaInfo = JavaInfo.getJavaInfo(base);
      if (javaInfo != null) {
        jars.addAll(javaInfo.getDirectRuntimeJars());
      }

      Artifact rJar = getAndroidLibraryRJar(base);
      if (rJar != null) {
        jars.add(rJar);
      }

      Artifact buildStampJar = getAndroidBuildStampJar(base);
      if (buildStampJar != null) {
        jars.add(buildStampJar);
      }

      jars.addAll(extraToolchainJars);
      return jars.build();
    }
    return null;
  }

  private static boolean isProtoLibrary(RuleContext ruleContext) {
    return "proto_library".equals(ruleContext.getRule().getRuleClass());
  }

  @Nullable
  private static Artifact getAndroidLibraryRJar(ConfiguredTarget base) {
    AndroidIdeInfoProvider provider =
        (AndroidIdeInfoProvider) base.get(AndroidIdeInfoProvider.PROVIDER.getKey());
    if (provider != null && provider.getResourceJarJavaOutput() != null) {
      return provider.getResourceJarJavaOutput().getClassJar();
    }
    return null;
  }

  @Nullable
  private static Artifact getAndroidBuildStampJar(ConfiguredTarget base) {
    AndroidApplicationResourceInfo provider =
        (AndroidApplicationResourceInfo) base.get(AndroidApplicationResourceInfo.PROVIDER.getKey());
    if (provider != null && provider.getBuildStampJar() != null) {
      return provider.getBuildStampJar();
    }
    return null;
  }

  private static boolean checkBasenameClash(Iterable<Artifact> artifacts) {
    HashSet<String> seen = new HashSet<>();
    for (Artifact artifact : artifacts) {
      if (!seen.add(artifact.getFilename())) {
        return true;
      }
    }
    return false;
  }

  private static <T extends TransitiveInfoProvider> void collectPrerequisites(
      RuleContext ruleContext, Class<T> classType, Consumer<List<T>> sink) {
    for (String attr : TRANSITIVE_ATTRIBUTES) {
      if (ruleContext.attributes().getAttributeType(attr) != null) {
        sink.accept(ruleContext.getPrerequisites(attr, classType));
      }
    }
  }

  private NestedSet<Artifact> getBootclasspath(ConfiguredTarget base, RuleContext ruleContext)
      throws RuleErrorException {
    NestedSet<Artifact> bootClasspath = JavaInfo.bootClasspath(base);
    if (!bootClasspath.isEmpty()) {
      return bootClasspath;
    }
    Artifact androidJar = getAndroidJar(ruleContext);
    if (androidJar != null) {
      return NestedSetBuilder.<Artifact>naiveLinkOrder().add(androidJar).build();
    }
    // This shouldn't ever be reached, but if it is, we should be clear about the error.
    throw new IllegalStateException("no compilationInfo or androidJar");
  }

  @Nullable
  private Artifact getAndroidJar(RuleContext ruleContext) throws RuleErrorException {
    Label toolchainType = Label.parseCanonicalUnchecked(toolsRepository + sdkToolchainLabel);
    AndroidSdkProvider androidSdk = AndroidSdkProvider.fromRuleContext(ruleContext, toolchainType);
    if (androidSdk == null) {
      // If the Android SDK is null, we don't have a valid toolchain. Expect a rule error reported
      // from AndroidSdkProvider.
      return null;
    }
    return androidSdk.getAndroidJar();
  }

  private Artifact createDesugarAction(
      RuleContext ruleContext,
      boolean disambiguateBasenames,
      Artifact jar,
      NestedSet<Artifact> bootclasspath,
      NestedSet<Artifact> compileTimeClasspath,
      int minSdkVersion) {

    String minSdkFilenamePart = minSdkVersion > 0 ? "_minsdk=" + minSdkVersion : "";
    return createDesugarAction(
        ruleContext,
        ASPECT_DESUGAR_PREREQ,
        jar,
        bootclasspath,
        compileTimeClasspath,
        minSdkVersion,
        AndroidBinary.getDxArtifact(
            ruleContext,
            (disambiguateBasenames ? jar.getRootRelativePathString() : jar.getFilename())
                + minSdkFilenamePart
                + "_desugared.jar"));
  }

  private static Artifact createDesugarAction(
      RuleContext ruleContext,
      String desugarPrereqName,
      Artifact jar,
      NestedSet<Artifact> bootclasspath,
      NestedSet<Artifact> classpath,
      int minSdkVersion,
      Artifact result) {
    SpawnAction.Builder action =
        new SpawnAction.Builder()
            .useDefaultShellEnvironment()
            .setExecutable(ruleContext.getExecutablePrerequisite(desugarPrereqName))
            .addInput(jar)
            .addTransitiveInputs(bootclasspath)
            .addTransitiveInputs(classpath)
            .addOutput(result)
            .setMnemonic("Desugar")
            .setProgressMessage("Desugaring %s for Android", jar.prettyPrint())
            .setExecutionInfo(
                createDexingDesugaringExecRequirements(ruleContext)
                    .putAll(ExecutionRequirements.WORKER_MODE_ENABLED)
                    .buildKeepingLast());

    CustomCommandLine.Builder args =
        new CustomCommandLine.Builder()
            .addExecPath("--input", jar)
            .addExecPath("--output", result)
            .addExecPaths(VectorArg.addBefore("--classpath_entry").each(classpath))
            .addExecPaths(VectorArg.addBefore("--bootclasspath_entry").each(bootclasspath));
    if (getAndroidConfig(ruleContext).checkDesugarDeps()) {
      args.add("--emit_dependency_metadata_as_needed");
    }
    if (getAndroidConfig(ruleContext).desugarJava8Libs()) {
      args.add("--desugar_supported_core_libs");
    }
    if (minSdkVersion > 0) {
      args.add("--min_sdk_version", Integer.toString(minSdkVersion));
    }

    action.addCommandLine(
        // Always use params file, so we don't need to compute command line length first
        args.build(), ParamFileInfo.builder(UNQUOTED).setUseAlways(true).build());

    ruleContext.registerAction(action.build(ruleContext));
    return result;
  }

  /**
   * Desugars the given Jar using an executable prerequisite {@code "$desugar"}. Rules calling this
   * method must declare the appropriate prerequisite, similar to how {@link #getDefinition} does it
   * for {@link DexArchiveAspect} under a different name.
   *
   * <p>It's useful to have this action separately since callers need to look up classpath and
   * bootclasspath in a different way than this aspect does it.
   *
   * @return the artifact given as {@code result}, which can simplify calling code
   */
  static Artifact desugar(
      RuleContext ruleContext,
      Artifact jar,
      NestedSet<Artifact> bootclasspath,
      NestedSet<Artifact> classpath,
      int minSdkVersion,
      Artifact result) {
    return createDesugarAction(
        ruleContext, "$desugar", jar, bootclasspath, classpath, minSdkVersion, result);
  }

  /**
   * Creates a dexbuilder action with the given input, output, and flags. Flags must have been
   * filtered and normalized to a set that the dexbuilder tool can understand.
   *
   * @return the artifact given as {@code result}, which can simplify calling code
   */
  // Package-private method for use in AndroidBinary
  @CanIgnoreReturnValue
  static Artifact createDexArchiveAction(
      RuleContext ruleContext,
      String dexbuilderPrereq,
      Artifact jar,
      Set<String> incrementalDexopts,
      int minSdkVersion,
      Artifact dexArchive) {
    SpawnAction.Builder dexbuilder =
        new SpawnAction.Builder()
            .useDefaultShellEnvironment()
            .setExecutable(ruleContext.getExecutablePrerequisite(dexbuilderPrereq))
            .setExecutionInfo(
                createDexingDesugaringExecRequirements(ruleContext)
                    .putAll(
                        TargetUtils.getExecutionInfo(
                            ruleContext.getRule(), ruleContext.isAllowTagsPropagation()))
                    .buildKeepingLast())
            // WorkerSpawnStrategy expects the last argument to be @paramfile
            .addInput(jar)
            .addOutput(dexArchive)
            .setMnemonic("DexBuilder")
            .setProgressMessage(
                "Dexing %s with applicable dexopts %s", jar.prettyPrint(), incrementalDexopts);

    CustomCommandLine.Builder args =
        new CustomCommandLine.Builder()
            .addExecPath("--input_jar", jar)
            .addExecPath("--output_zip", dexArchive)
            .addAll(ImmutableList.copyOf(incrementalDexopts));
    if (minSdkVersion > 0) {
      args.add("--min_sdk_version", Integer.toString(minSdkVersion));
    }

    dexbuilder.addCommandLine(
        args.build(), ParamFileInfo.builder(UNQUOTED).setUseAlways(true).build());
    ruleContext.registerAction(dexbuilder.build(ruleContext));
    return dexArchive;
  }

  @CanIgnoreReturnValue
  static Artifact createShardedOptimizedDexArchiveAction(
      RuleContext ruleContext,
      Artifact jar,
      Set<String> incrementalDexopts,
      int minSdkVersion,
      Artifact dexArchive) {
    SpawnAction.Builder dexbuilder =
        new SpawnAction.Builder()
            .useDefaultShellEnvironment()
            .setExecutable(ruleContext.getExecutablePrerequisite(":optimizing_dexer"))
            .setExecutionInfo(
                createDexingDesugaringExecRequirements(ruleContext)
                    .putAll(
                        TargetUtils.getExecutionInfo(
                            ruleContext.getRule(), ruleContext.isAllowTagsPropagation()))
                    .buildKeepingLast())
            .addInput(jar)
            .addOutput(dexArchive)
            .setMnemonic("ShardedOptimizingDex")
            .setProgressMessage(
                "Optimized dexing %s with applicable dexopts %s",
                jar.prettyPrint(), incrementalDexopts);

    CustomCommandLine.Builder args =
        new CustomCommandLine.Builder()
            .add("--intermediate")
            .add("--release")
            .add("--no-desugaring")
            .addExecPath("--output", dexArchive)
            .addAll(ImmutableList.copyOf(incrementalDexopts))
            .addExecPath(jar);
    if (minSdkVersion > 0) {
      args.add("--min_sdk_version", Integer.toString(minSdkVersion));
    }

    dexbuilder.addCommandLine(args.build());
    ruleContext.registerAction(dexbuilder.build(ruleContext));
    return dexArchive;
  }

  private static Set<Set<String>> aspectDexopts(RuleContext ruleContext) {
    return Sets.powerSet(
        normalizeDexopts(getAndroidConfig(ruleContext).getDexoptsSupportedInIncrementalDexing()));
  }

  /** Creates the execution requires for the DexBuilder and Desugar actions */
  private static ImmutableMap.Builder<String, String> createDexingDesugaringExecRequirements(
      RuleContext ruleContext) {
    final ImmutableMap.Builder<String, String> executionInfo = ImmutableMap.builder();
    AndroidConfiguration androidConfiguration = getAndroidConfig(ruleContext);
    if (androidConfiguration.persistentDexDesugar()) {
      executionInfo.putAll(ExecutionRequirements.WORKER_MODE_ENABLED);
      if (androidConfiguration.persistentMultiplexDexDesugar()) {
        executionInfo.putAll(ExecutionRequirements.WORKER_MULTIPLEX_MODE_ENABLED);
      }
    }

    return executionInfo;
  }

  /**
   * Derives options to use in incremental dexing actions from the given context and dx flags, where
   * the latter typically come from a {@code dexopts} attribute on a top-level target. This method
   * only works reliably if the given dexopts were tokenized, e.g., using {@link
   * RuleContext#getTokenizedStringListAttr}.
   */
  static ImmutableSet<String> incrementalDexopts(
      RuleContext ruleContext, Iterable<String> tokenizedDexopts) {
    return normalizeDexopts(
        Iterables.filter(
            tokenizedDexopts,
            // dexopts have to match exactly since aspect only creates archives for listed ones
            Predicates.in(getAndroidConfig(ruleContext).getDexoptsSupportedInIncrementalDexing())));
  }

  /**
   * Returns the subset of the given dexopts that are forbidden from using incremental dexing by
   * default.
   */
  static Iterable<String> forbiddenDexopts(RuleContext ruleContext, List<String> dexopts) {
    return Iterables.filter(
        dexopts,
        new FlagMatcher(
            getAndroidConfig(ruleContext).getTargetDexoptsThatPreventIncrementalDexing()));
  }

  /**
   * Derives options to use in DexBuilder actions from the given context and dx flags, where the
   * latter typically come from a {@code dexopts} attribute on a top-level target. This should be a
   * superset of {@link #incrementalDexopts}.
   */
  static ImmutableSet<String> topLevelDexbuilderDexopts(Iterable<String> tokenizedDexopts) {
    // We don't need an ordered set but might as well.
    return normalizeDexopts(Iterables.filter(tokenizedDexopts, DEXOPTS_SUPPORTED_IN_DEXBUILDER));
  }

  /**
   * Derives options to use in DexFileMerger actions from the given context and dx flags, where the
   * latter typically come from a {@code dexopts} attribute on a top-level target.
   */
  static ImmutableSet<String> mergerDexopts(
      RuleContext ruleContext, Iterable<String> tokenizedDexopts) {
    // We don't need an ordered set but might as well.  Note we don't need to worry about coverage
    // builds since the merger doesn't use --no-locals.
    return normalizeDexopts(
        Iterables.filter(
            tokenizedDexopts,
            new FlagMatcher(getAndroidConfig(ruleContext).getDexoptsSupportedInDexMerger())));
  }

  /**
   * Derives options to use in DexFileSharder actions from the given context and dx flags, where the
   * latter typically come from a {@code dexopts} attribute on a top-level target.
   */
  static ImmutableSet<String> sharderDexopts(
      RuleContext ruleContext, Iterable<String> tokenizedDexopts) {
    // We don't need an ordered set but might as well.  Note we don't need to worry about coverage
    // builds since the merger doesn't use --no-locals.
    return normalizeDexopts(
        Iterables.filter(
            tokenizedDexopts,
            new FlagMatcher(getAndroidConfig(ruleContext).getDexoptsSupportedInDexSharder())));
  }

  private static ImmutableSet<String> normalizeDexopts(Iterable<String> tokenizedDexopts) {
    // Sort and use ImmutableSet to drop duplicates and get fixed (sorted) order.  Fixed order is
    // important so we generate one dex archive per set of flag in create() method, regardless of
    // how those flags are listed in all the top-level targets being built.
    return Streams.stream(tokenizedDexopts)
        .map(FlagConverter.DX_TO_DEXBUILDER)
        .sorted()
        .collect(ImmutableSet.toImmutableSet()); // collector with dedupe
  }

  private static class FlagMatcher implements Predicate<String> {
    private final ImmutableList<String> matching;

    FlagMatcher(ImmutableList<String> matching) {
      this.matching = matching;
    }

    @Override
    public boolean apply(String input) {
      for (String match : matching) {
        if (input.contains(match)) {
          return true;
        }
      }
      return false;
    }
  }

  private enum FlagConverter implements Function<String, String> {
    DX_TO_DEXBUILDER;

    @Override
    public String apply(String input) {
      return input.replace("--no-", "--no");
    }
  }
}
