Beispiel #1
0
  /**
   * Returns the ShellCommand object that is supposed to generate a code coverage report from data
   * obtained during the test run. This method will also generate a set of source paths to the class
   * files tested during the test run.
   */
  private static Step getReportCommand(
      ImmutableSet<JavaLibrary> rulesUnderTest,
      Optional<DefaultJavaPackageFinder> defaultJavaPackageFinderOptional,
      ProjectFilesystem filesystem,
      Path outputDirectory,
      CoverageReportFormat format) {
    ImmutableSet.Builder<String> srcDirectories = ImmutableSet.builder();
    ImmutableSet.Builder<Path> pathsToClasses = ImmutableSet.builder();

    // Add all source directories of java libraries that we are testing to -sourcepath.
    for (JavaLibrary rule : rulesUnderTest) {
      ImmutableSet<String> sourceFolderPath =
          getPathToSourceFolders(rule, defaultJavaPackageFinderOptional, filesystem);
      if (!sourceFolderPath.isEmpty()) {
        srcDirectories.addAll(sourceFolderPath);
      }
      Path pathToOutput = rule.getPathToOutput();
      if (pathToOutput == null) {
        continue;
      }
      pathsToClasses.add(pathToOutput);
    }

    return new GenerateCodeCoverageReportStep(
        srcDirectories.build(), pathsToClasses.build(), outputDirectory, format);
  }
  /**
   * Creates/finds the set of build rules that correspond to pre-dex'd artifacts that should be
   * merged to create the final classes.dex for the APK.
   *
   * <p>This method may modify {@code ruleResolver}, inserting new rules into its index.
   */
  @VisibleForTesting
  PreDexMerge createPreDexMergeRule(
      AaptPackageResources aaptPackageResources,
      Iterable<DexProducedFromJavaLibrary> preDexRulesNotInThePackageableCollection,
      AndroidPackageableCollection packageableCollection) {
    ImmutableSortedSet.Builder<JavaLibrary> javaLibraryDepsBuilder =
        ImmutableSortedSet.naturalOrder();
    ImmutableSet.Builder<DexProducedFromJavaLibrary> preDexDeps = ImmutableSet.builder();
    preDexDeps.addAll(preDexRulesNotInThePackageableCollection);
    for (BuildTarget buildTarget : packageableCollection.getJavaLibrariesToDex()) {
      Preconditions.checkState(
          !buildTargetsToExcludeFromDex.contains(buildTarget),
          "JavaLibrary should have been excluded from target to dex: %s",
          buildTarget);

      BuildRule libraryRule = ruleResolver.getRule(buildTarget);

      // Skip uber R.java since AaptPackageResources takes care of dexing.
      if (libraryRule.equals(aaptPackageResources)) {
        continue;
      }

      Preconditions.checkState(libraryRule instanceof JavaLibrary);
      JavaLibrary javaLibrary = (JavaLibrary) libraryRule;

      // If the rule has no output file (which happens when a java_library has no srcs or
      // resources, but export_deps is true), then there will not be anything to dx.
      if (javaLibrary.getPathToOutput() == null) {
        continue;
      }

      // Take note of the rule so we add it to the enhanced deps.
      javaLibraryDepsBuilder.add(javaLibrary);

      // See whether the corresponding IntermediateDexRule has already been added to the
      // ruleResolver.
      BuildTarget originalTarget = javaLibrary.getBuildTarget();
      BuildTarget preDexTarget = BuildTarget.builder(originalTarget).addFlavors(DEX_FLAVOR).build();
      Optional<BuildRule> preDexRule = ruleResolver.getRuleOptional(preDexTarget);
      if (preDexRule.isPresent()) {
        preDexDeps.add((DexProducedFromJavaLibrary) preDexRule.get());
        continue;
      }

      // Create the IntermediateDexRule and add it to both the ruleResolver and preDexDeps.
      BuildRuleParams paramsForPreDex =
          buildRuleParams.copyWithChanges(
              preDexTarget,
              Suppliers.ofInstance(
                  ImmutableSortedSet.of(ruleResolver.getRule(javaLibrary.getBuildTarget()))),
              /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()));
      DexProducedFromJavaLibrary preDex =
          new DexProducedFromJavaLibrary(paramsForPreDex, pathResolver, javaLibrary);
      ruleResolver.addToIndex(preDex);
      preDexDeps.add(preDex);
    }

    ImmutableSet<DexProducedFromJavaLibrary> allPreDexDeps = preDexDeps.build();

    BuildRuleParams paramsForPreDexMerge =
        buildRuleParams.copyWithChanges(
            createBuildTargetWithFlavor(DEX_MERGE_FLAVOR),
            Suppliers.ofInstance(
                ImmutableSortedSet.<BuildRule>naturalOrder()
                    .addAll(getDexMergeDeps(aaptPackageResources, allPreDexDeps))
                    .addAll(javaLibraryDepsBuilder.build())
                    .build()),
            /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()));
    PreDexMerge preDexMerge =
        new PreDexMerge(
            paramsForPreDexMerge,
            pathResolver,
            primaryDexPath,
            dexSplitMode,
            allPreDexDeps,
            aaptPackageResources,
            dxExecutorService,
            xzCompressionLevel);
    ruleResolver.addToIndex(preDexMerge);

    return preDexMerge;
  }
  /**
   * If the user specified any android_build_config() rules, then we must add some build rules to
   * generate the production {@code BuildConfig.class} files and ensure that they are included in
   * the list of {@link AndroidPackageableCollection#getClasspathEntriesToDex}.
   */
  private void addBuildConfigDeps(
      boolean shouldPreDex,
      AndroidPackageableCollection packageableCollection,
      ImmutableSortedSet.Builder<BuildRule> enhancedDeps,
      ImmutableList.Builder<DexProducedFromJavaLibrary> preDexRules,
      ImmutableList.Builder<Path> buildConfigJarFilesBuilder) {
    BuildConfigFields buildConfigConstants =
        BuildConfigFields.fromFields(
            ImmutableList.<BuildConfigFields.Field>of(
                BuildConfigFields.Field.of(
                    "boolean",
                    BuildConfigs.DEBUG_CONSTANT,
                    String.valueOf(packageType != AndroidBinary.PackageType.RELEASE)),
                BuildConfigFields.Field.of(
                    "boolean",
                    BuildConfigs.IS_EXO_CONSTANT,
                    String.valueOf(!exopackageModes.isEmpty())),
                BuildConfigFields.Field.of(
                    "int",
                    BuildConfigs.EXOPACKAGE_FLAGS,
                    String.valueOf(ExopackageMode.toBitmask(exopackageModes)))));
    for (Map.Entry<String, BuildConfigFields> entry :
        packageableCollection.getBuildConfigs().entrySet()) {
      // Merge the user-defined constants with the APK-specific overrides.
      BuildConfigFields totalBuildConfigValues =
          BuildConfigFields.empty()
              .putAll(entry.getValue())
              .putAll(buildConfigValues)
              .putAll(buildConfigConstants);

      // Each enhanced dep needs a unique build target, so we parameterize the build target by the
      // Java package.
      String javaPackage = entry.getKey();
      Flavor flavor = ImmutableFlavor.of("buildconfig_" + javaPackage.replace('.', '_'));
      BuildRuleParams buildConfigParams =
          new BuildRuleParams(
              createBuildTargetWithFlavor(flavor),
              /* declaredDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()),
              /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()),
              buildRuleParams.getProjectFilesystem(),
              buildRuleParams.getRuleKeyBuilderFactory());
      JavaLibrary buildConfigJavaLibrary =
          AndroidBuildConfigDescription.createBuildRule(
              buildConfigParams,
              javaPackage,
              totalBuildConfigValues,
              buildConfigValuesFile,
              /* useConstantExpressions */ true,
              javacOptions,
              ruleResolver);
      ruleResolver.addToIndex(buildConfigJavaLibrary);

      enhancedDeps.add(buildConfigJavaLibrary);
      Path buildConfigJar = buildConfigJavaLibrary.getPathToOutput();
      Preconditions.checkNotNull(
          buildConfigJar, "%s must have an output file.", buildConfigJavaLibrary);
      buildConfigJarFilesBuilder.add(buildConfigJar);

      if (shouldPreDex) {
        DexProducedFromJavaLibrary buildConfigDex =
            new DexProducedFromJavaLibrary(
                buildConfigParams.copyWithChanges(
                    createBuildTargetWithFlavor(ImmutableFlavor.of("dex_" + flavor.getName())),
                    Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of(buildConfigJavaLibrary)),
                    /* extraDeps */ Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of())),
                pathResolver,
                buildConfigJavaLibrary);
        ruleResolver.addToIndex(buildConfigDex);
        enhancedDeps.add(buildConfigDex);
        preDexRules.add(buildConfigDex);
      }
    }
  }