aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2016-10-14 01:15:45 +0000
committerGravatar Yue Gan <yueg@google.com>2016-10-14 09:33:36 +0000
commitf535f363b42817705166d0c135ce881157349788 (patch)
tree04a3b246c00e665e2129d70169b9b618b6548e38 /src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
parent322f531f12addfe2c4671eb5d3a0ea8b9f2843ac (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.java105
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);