/** * 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 BuildRule createPreDexMergeRule(UberRDotJava uberRDotJava) { ImmutableSet.Builder<DexProducedFromJavaLibrary> preDexDeps = ImmutableSet.builder(); ImmutableSet<JavaLibrary> transitiveJavaDeps = Classpaths.getClasspathEntries(originalDeps).keySet(); for (JavaLibrary javaLibrary : transitiveJavaDeps) { // 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.getPathToOutputFile() == null) { continue; } // If the rule is in the no_dx list, then do not pre-dex it. if (buildRulesToExcludeFromDex.contains(javaLibrary.getBuildTarget())) { continue; } // See whether the corresponding IntermediateDexRule has already been added to the // ruleResolver. BuildTarget originalTarget = javaLibrary.getBuildTarget(); BuildTarget preDexTarget = new BuildTarget(originalTarget.getBaseName(), originalTarget.getShortName(), DEX_FLAVOR); BuildRule preDexRule = ruleResolver.get(preDexTarget); if (preDexRule != null) { preDexDeps.add((DexProducedFromJavaLibrary) preDexRule.getBuildable()); continue; } // Create the IntermediateDexRule and add it to both the ruleResolver and preDexDeps. DexProducedFromJavaLibrary preDex = new DexProducedFromJavaLibrary(preDexTarget, javaLibrary); buildRuleAndAddToIndex( preDex, BuildRuleType.PRE_DEX, preDexTarget, ImmutableSortedSet.of(ruleResolver.get(javaLibrary.getBuildTarget()))); preDexDeps.add(preDex); } ImmutableSet<DexProducedFromJavaLibrary> allPreDexDeps = preDexDeps.build(); BuildTarget buildTargetForDexMerge = createBuildTargetWithFlavor(DEX_MERGE_FLAVOR); PreDexMerge preDexMerge = new PreDexMerge( buildTargetForDexMerge, primaryDexPath, dexSplitMode, allPreDexDeps, uberRDotJava); BuildRule preDexMergeBuildRule = buildRuleAndAddToIndex( preDexMerge, BuildRuleType.DEX_MERGE, buildTargetForDexMerge, getDexMergeDeps(uberRDotJava, allPreDexDeps)); return preDexMergeBuildRule; }
/** * 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; }