diff options
author | Googler <noreply@google.com> | 2016-10-14 01:15:45 +0000 |
---|---|---|
committer | Yue Gan <yueg@google.com> | 2016-10-14 09:33:36 +0000 |
commit | f535f363b42817705166d0c135ce881157349788 (patch) | |
tree | 04a3b246c00e665e2129d70169b9b618b6548e38 /src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java | |
parent | 322f531f12addfe2c4671eb5d3a0ea8b9f2843ac (diff) |
Desugar Java 8 for Android builds without incremental dexing.
This includes applying desugaring for mobile-install's stub apk.
--
MOS_MIGRATED_REVID=136111631
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java | 105 |
1 files changed, 82 insertions, 23 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java index 8a229275be..cd0a3c4bad 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java @@ -20,6 +20,7 @@ import static com.google.common.collect.Iterables.filter; import static com.google.devtools.build.lib.analysis.OutputGroupProvider.INTERNAL_SUFFIX; import com.google.common.base.Function; +import com.google.common.base.Functions; import com.google.common.base.Optional; import com.google.common.base.Predicate; import com.google.common.base.Predicates; @@ -346,8 +347,10 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { true /* isBinary */); ruleContext.assertNoErrors(); + Function<Artifact, Artifact> derivedJarFunction = + collectDesugaredJars(ruleContext, androidCommon, androidSemantics, resourceClasses); Artifact deployJar = createDeployJar(ruleContext, javaSemantics, androidCommon, resourceClasses, - ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_BINARY_DEPLOY_JAR)); + derivedJarFunction); Artifact proguardMapping = ruleContext.getPrerequisiteArtifact( "proguard_apply_mapping", Mode.TARGET); @@ -356,6 +359,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { ruleContext, filesBuilder, deployJar, + derivedJarFunction, /* isBinaryJarFiltered */ false, javaCommon, androidCommon, @@ -378,6 +382,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { RuleContext ruleContext, NestedSetBuilder<Artifact> filesBuilder, Artifact binaryJar, + Function<Artifact, Artifact> derivedJarFunction, boolean isBinaryJarFiltered, JavaCommon javaCommon, AndroidCommon androidCommon, @@ -429,7 +434,8 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { isBinaryJarFiltered, androidCommon, resourceApk.getMainDexProguardConfig(), - resourceClasses); + resourceClasses, + derivedJarFunction); Artifact finalDexes; Artifact finalProguardMap; @@ -842,11 +848,19 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { .addRuntimeClassPathEntries(provider.getJavaCompilationArgs().getRuntimeJars()) .build(); + Function<Artifact, Artifact> desugaredJars = Functions.identity(); + if (AndroidCommon.getAndroidConfig(ruleContext).desugarJava8()) { + desugaredJars = + collectDesugaredJarsFromAttributes(ruleContext, ImmutableList.of(attribute)) + .build() + .collapseToFunction(); + } Artifact stubDeployJar = getDxArtifact(ruleContext, split ? "split_stub_deploy.jar" : "stub_deploy.jar"); new DeployArchiveBuilder(javaSemantics, ruleContext) .setOutputJar(stubDeployJar) .setAttributes(attributes) + .setDerivedJarFunction(desugaredJars) .build(); Artifact stubDex = getDxArtifact(ruleContext, @@ -871,9 +885,10 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { ResourceApk resourceApk, NativeLibs nativeLibs, Artifact debugKeystore) { - + // TODO(bazel-team): Sufficient to use resourceClasses.getRuntimeClasspathForArchive? + // Deleting getArchiveInputs could simplify the implementation of DeployArchiveBuidler.build() Iterable<Artifact> jars = IterablesChain.concat( - resourceClasses.getArchiveInputs(true), androidCommon.getRuntimeJars()); + DeployArchiveBuilder.getArchiveInputs(resourceClasses), androidCommon.getRuntimeJars()); // The resources jars from android_library rules contain stub ids, so filter those out of the // transitive jars. @@ -911,12 +926,15 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { JavaSemantics javaSemantics, AndroidCommon common, JavaTargetAttributes attributes, - Artifact deployJar) + Function<Artifact, Artifact> derivedJarFunction) throws InterruptedException { + Artifact deployJar = + ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_BINARY_DEPLOY_JAR); new DeployArchiveBuilder(javaSemantics, ruleContext) .setOutputJar(deployJar) .setAttributes(attributes) .addRuntimeJars(common.getRuntimeJars()) + .setDerivedJarFunction(derivedJarFunction) .build(); return deployJar; } @@ -1092,7 +1110,8 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { boolean isBinaryJarFiltered, AndroidCommon common, @Nullable Artifact mainDexProguardSpec, - JavaTargetAttributes attributes) + JavaTargetAttributes attributes, + Function<Artifact, Artifact> derivedJarFunction) throws InterruptedException, RuleErrorException { List<String> dexopts = ruleContext.getTokenizedStringListAttr("dexopts"); MultidexMode multidexMode = getMultidexMode(ruleContext); @@ -1131,7 +1150,8 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { Artifact classesDex = getDxArtifact(ruleContext, "classes.dex.zip"); Artifact jarToDex = getDxArtifact(ruleContext, "classes.jar"); createShuffleJarAction(ruleContext, true, (Artifact) null, ImmutableList.of(jarToDex), - common, inclusionFilterJar, dexopts, androidSemantics, attributes, (Artifact) null); + common, inclusionFilterJar, dexopts, androidSemantics, attributes, derivedJarFunction, + (Artifact) null); createDexMergerAction(ruleContext, "off", jarToDex, classesDex, (Artifact) null, dexopts); return new DexingOutput(classesDex, binaryJar, ImmutableList.of(classesDex)); } else { @@ -1169,6 +1189,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { dexopts, androidSemantics, attributes, + derivedJarFunction, mainDexList); List<Artifact> shardDexes = new ArrayList<>(dexShards); @@ -1215,7 +1236,8 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { if (incrementalDexing.contains(AndroidBinaryType.MULTIDEX_UNSHARDED)) { Artifact jarToDex = AndroidBinary.getDxArtifact(ruleContext, "classes.jar"); createShuffleJarAction(ruleContext, true, (Artifact) null, ImmutableList.of(jarToDex), - common, inclusionFilterJar, dexopts, androidSemantics, attributes, (Artifact) null); + common, inclusionFilterJar, dexopts, androidSemantics, attributes, derivedJarFunction, + (Artifact) null); createDexMergerAction(ruleContext, "minimal", jarToDex, classesDex, mainDexList, dexopts); } else { // Because the dexer also places resources into this zip, we also need to create a cleanup @@ -1313,12 +1335,58 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { * Returns a {@link DexArchiveProvider} of all transitively generated dex archives as well as dex * archives for the Jars produced by the binary target itself. */ + public static Function<Artifact, Artifact> collectDesugaredJars( + RuleContext ruleContext, + AndroidCommon common, + AndroidSemantics semantics, + JavaTargetAttributes attributes) { + if (!AndroidCommon.getAndroidConfig(ruleContext).desugarJava8()) { + return Functions.identity(); + } + AndroidRuntimeJarProvider.Builder result = + collectDesugaredJarsFromAttributes( + ruleContext, semantics.getAttributesWithJavaRuntimeDeps(ruleContext)); + for (Artifact jar : common.getJarsProducedForRuntime()) { + // Create dex archives next to all Jars produced by AndroidCommon for this rule. We need to + // do this (instead of placing dex archives into the _dx subdirectory like DexArchiveAspect) + // because for "legacy" ResourceApks, AndroidCommon produces Jars per resource dependency that + // can theoretically have duplicate basenames, so they go into special directories, and we + // piggyback on that naming scheme here by placing dex archives into the same directories. + PathFragment jarPath = jar.getRootRelativePath(); + Artifact desugared = + DexArchiveAspect.desugar( + ruleContext, + jar, + attributes.getBootClassPath(), + attributes.getCompileTimeClassPath(), + ruleContext.getDerivedArtifact( + jarPath.replaceName(jarPath.getBaseName() + "_desugared.jar"), jar.getRoot())); + result.addDesugaredJar(jar, desugared); + } + return result.build().collapseToFunction(); + } + + private static AndroidRuntimeJarProvider.Builder collectDesugaredJarsFromAttributes( + RuleContext ruleContext, ImmutableList<String> attributes) { + AndroidRuntimeJarProvider.Builder result = new AndroidRuntimeJarProvider.Builder(); + for (String attr : attributes) { + // Use all available AndroidRuntimeJarProvider from attributes that carry runtime dependencies + result.addTransitiveProviders( + ruleContext.getPrerequisites(attr, Mode.TARGET, AndroidRuntimeJarProvider.class)); + } + return result; + } + + /** + * Returns a {@link DexArchiveProvider} of all transitively generated dex archives as well as dex + * archives for the Jars produced by the binary target itself. + */ private static Function<Artifact, Artifact> collectDexArchives( RuleContext ruleContext, AndroidCommon common, List<String> dexopts, AndroidSemantics semantics, - JavaTargetAttributes attributes) { + Function<Artifact, Artifact> derivedJarFunction) { DexArchiveProvider.Builder result = new DexArchiveProvider.Builder(); for (String attr : semantics.getAttributesWithJavaRuntimeDeps(ruleContext)) { // Use all available DexArchiveProviders from attributes that carry runtime dependencies @@ -1334,22 +1402,10 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { // can theoretically have duplicate basenames, so they go into special directories, and we // piggyback on that naming scheme here by placing dex archives into the same directories. PathFragment jarPath = jar.getRootRelativePath(); - Artifact jarToDex = jar; - if (AndroidCommon.getAndroidConfig(ruleContext).desugarJava8()) { - // desugar jars first if desired... - jarToDex = - DexArchiveAspect.desugar( - ruleContext, - jar, - attributes.getBootClassPath(), - attributes.getCompileTimeClassPath(), - ruleContext.getDerivedArtifact( - jarPath.replaceName(jarPath.getBaseName() + "_desugared.jar"), jar.getRoot())); - } Artifact dexArchive = DexArchiveAspect.createDexArchiveAction( ruleContext, - jarToDex, + derivedJarFunction.apply(jar), incrementalDexopts, ruleContext.getDerivedArtifact( jarPath.replaceName(jarPath.getBaseName() + ".dex.zip"), jar.getRoot())); @@ -1368,6 +1424,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { List<String> dexopts, AndroidSemantics semantics, JavaTargetAttributes attributes, + Function<Artifact, Artifact> derivedJarFunction, @Nullable Artifact mainDexList) throws InterruptedException { checkArgument(mainDexList == null || shards.size() > 1); @@ -1411,8 +1468,10 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory { // there should be very few or no Jar files that still end up in shards. The dexing // step below will have to deal with those in addition to merging .dex files together. classpath = Iterables.transform(classpath, - collectDexArchives(ruleContext, common, dexopts, semantics, attributes)); + collectDexArchives(ruleContext, common, dexopts, semantics, derivedJarFunction)); shardCommandLine.add("--split_dexed_classes"); + } else { + classpath = Iterables.transform(classpath, derivedJarFunction); } shardCommandLine.addBeforeEachExecPath("--input_jar", classpath); shardAction.addInputs(classpath); |