/** * 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); } } }