aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2017-04-14 18:57:42 +0200
committerGravatar Klaus Aehlig <aehlig@google.com>2017-04-18 11:26:51 +0200
commita45939bba2e85eb5f5941033e37dc2d6f8e87489 (patch)
treec4995030d7c0150b15ebaa16943bef6d626c183b
parent1341e3ed45045b85cda2c57c0623dae0d7149b16 (diff)
In android_library targets, R.class files should not be runtime dependencies
android_binary targets have their own R.java files (built from merging dependencies and any resources that belong directly to the target). As such, they don't need inherited R.java files at runtime. Taking these out makes for smaller APKs and less inheritance from the target's dependencies. Add a flag to control this behavior. Have it default to continue to include R.class files as runtime dependencies so we can control rollout of this behavior. Add tests of android_binary to ensure the JAR is filtered out as appropriate, and of android_robolectrictest to ensure that those tests still have access to the JARs. RELNOTES: none PiperOrigin-RevId: 153177074
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java3
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java24
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java15
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java6
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java80
5 files changed, 117 insertions, 11 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 29dad5109b..52c1b52a56 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
@@ -391,7 +391,8 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
resourceApk,
ruleContext.getConfiguration().isCodeCoverageEnabled(),
true /* collectJavaCompilationArgs */,
- true /* isBinary */);
+ true, /* isBinary */
+ androidConfig.includeLibraryResourceJars());
ruleContext.assertNoErrors();
Function<Artifact, Artifact> derivedJarFunction =
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
index e3f2417cd7..ab6878c824 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidCommon.java
@@ -378,8 +378,8 @@ public class AndroidCommon {
JavaCompilationArtifacts.Builder artifactsBuilder,
JavaTargetAttributes.Builder attributes,
NestedSetBuilder<Artifact> filesBuilder,
- NestedSetBuilder<Artifact> jarsProducedForRuntime,
- boolean useRClassGenerator) throws InterruptedException {
+ boolean useRClassGenerator)
+ throws InterruptedException {
compileResourceJar(javaSemantics, resourceApk, resourcesJar, useRClassGenerator);
// Add the compiled resource jar to the classpath of the main compilation.
attributes.addDirectJars(NestedSetBuilder.create(Order.STABLE_ORDER, resourceClassJar));
@@ -388,10 +388,7 @@ public class AndroidCommon {
// except for <clinit>, but it takes time to build and waiting for that to build would
// just delay building the rest of the library.
artifactsBuilder.addCompileTimeJar(resourceClassJar);
- // Combined resource constants needs to come even before our own classes that may contain
- // local resource constants.
- artifactsBuilder.addRuntimeJar(resourceClassJar);
- jarsProducedForRuntime.add(resourceClassJar);
+
// Add the compiled resource jar as a declared output of the rule.
filesBuilder.add(resourceSourceJar);
filesBuilder.add(resourceClassJar);
@@ -503,7 +500,8 @@ public class AndroidCommon {
ResourceApk resourceApk,
boolean addCoverageSupport,
boolean collectJavaCompilationArgs,
- boolean isBinary)
+ boolean isBinary,
+ boolean includeLibraryResourceJars)
throws InterruptedException {
classJar = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_LIBRARY_CLASS_JAR);
@@ -544,7 +542,17 @@ public class AndroidCommon {
// (the legacy srcjar requires the createJarJar step below).
boolean useRClassGenerator = isBinary && !resourceApk.isLegacy();
compileResources(javaSemantics, resourceApk, resourcesJar, artifactsBuilder, attributes,
- filesBuilder, jarsProducedForRuntime, useRClassGenerator);
+ filesBuilder, useRClassGenerator);
+
+ // In binary targets, add the resource jar as a runtime dependency. In libraries, the resource
+ // jar from the appropriate binary will be used, but add this jar anyway if requested.
+ if (isBinary || includeLibraryResourceJars) {
+ // Combined resource constants needs to come even before our own classes that may contain
+ // local resource constants.
+ artifactsBuilder.addRuntimeJar(resourceClassJar);
+ jarsProducedForRuntime.add(resourceClassJar);
+ }
+
if (resourceApk.isLegacy()) {
// Repackages the R.java for each dependency package and places the resultant jars before
// the dependency libraries to ensure that the generated resource ids are correct.
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java
index cf9c618d07..b7e543e83a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java
@@ -444,6 +444,15 @@ public class AndroidConfiguration extends BuildConfiguration.Fragment {
help = "Compress Java resources in APKs")
public boolean compressJavaResources;
+ @Option(name = "experimental_android_include_library_resource_jars",
+ defaultValue = "true",
+ category = "undocumented",
+ help = "Specifies whether resource JAR files for android_library targets should be included"
+ + " as runtime dependencies. Defaults to the old behavior, including them. These JARs"
+ + " are not nessecary for normal use as all required resources are included in the"
+ + " top-level android_binary resource JAR.")
+ public boolean includeLibraryResourceJars;
+
@Override
public void addAllLabels(Multimap<String, Label> labelMap) {
if (androidCrosstoolTop != null) {
@@ -528,6 +537,7 @@ public class AndroidConfiguration extends BuildConfiguration.Fragment {
private final ResourceFilter resourceFilter;
private final boolean useSingleJarForProguardLibraryJars;
private final boolean compressJavaResources;
+ private final boolean includeLibraryResourceJars;
AndroidConfiguration(Options options, Label androidSdk) throws InvalidConfigurationException {
this.sdk = androidSdk;
@@ -559,6 +569,7 @@ public class AndroidConfiguration extends BuildConfiguration.Fragment {
this.useRexToCompressDexFiles = options.useRexToCompressDexFiles;
this.resourceFilter = options.resourceFilter;
this.compressJavaResources = options.compressJavaResources;
+ this.includeLibraryResourceJars = options.includeLibraryResourceJars;
if (!dexoptsSupportedInIncrementalDexing.contains("--no-locals")) {
// TODO(bazel-team): Still needed? See DexArchiveAspect
@@ -671,6 +682,10 @@ public class AndroidConfiguration extends BuildConfiguration.Fragment {
return compressJavaResources;
}
+ public boolean includeLibraryResourceJars() {
+ return includeLibraryResourceJars;
+ }
+
@Override
public void addGlobalMakeVariables(ImmutableMap.Builder<String, String> globalMakeEnvBuilder) {
globalMakeEnvBuilder.put("ANDROID_CPU", cpu);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java
index 1f5e1a62b7..5f0da5fbc8 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java
@@ -116,7 +116,8 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory {
ResourceDependencies.fromRuleResourceAndDeps(ruleContext, false /* neverlink */));
}
- if (!ruleContext.getFragment(AndroidConfiguration.class).allowSrcsLessAndroidLibraryDeps()
+ AndroidConfiguration androidConfig = ruleContext.getFragment(AndroidConfiguration.class);
+ if (!androidConfig.allowSrcsLessAndroidLibraryDeps()
&& !definesLocalResources
&& ruleContext.attributes().get("srcs", BuildType.LABEL_LIST).isEmpty()
&& ruleContext.attributes().get("idl_srcs", BuildType.LABEL_LIST).isEmpty()
@@ -130,7 +131,8 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory {
resourceApk,
false /* addCoverageSupport */,
true /* collectJavaCompilationArgs */,
- false /* isBinary */);
+ false /* isBinary */,
+ androidConfig.includeLibraryResourceJars());
if (javaTargetAttributes == null) {
return null;
}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java
index 9a54de5bdb..6b366b418b 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidBinaryTest.java
@@ -1539,6 +1539,86 @@ public class AndroidBinaryTest extends AndroidBuildViewTestCase {
}
@Test
+ public void testInheritedRNotInRuntimeJars() throws Exception {
+ String dir = "java/r/android/";
+ scratch.file(
+ dir + "BUILD",
+ "android_library(name = 'sublib',",
+ " manifest = 'AndroidManifest.xml',",
+ " resource_files = glob(['res3/**']),",
+ " srcs =['sublib.java'],",
+ " )",
+ "android_library(name = 'lib',",
+ " manifest = 'AndroidManifest.xml',",
+ " resource_files = glob(['res2/**']),",
+ " deps = [':sublib'],",
+ " srcs =['lib.java'],",
+ " )",
+ "android_binary(name = 'bin',",
+ " manifest = 'AndroidManifest.xml',",
+ " resource_files = glob(['res/**']),",
+ " deps = [':lib'],",
+ " srcs =['bin.java'],",
+ " )");
+
+ // TODO(b/37087277): Remove this once this behavior is the default
+ useConfiguration("--noexperimental_android_include_library_resource_jars");
+
+ Action deployJarAction =
+ getGeneratingAction(
+ getFileConfiguredTarget("//java/r/android:bin_deploy.jar").getArtifact());
+ List<String> inputs = ActionsTestUtil.prettyArtifactNames(deployJarAction.getInputs());
+
+ assertThat(inputs)
+ .containsAllOf(
+ dir + "libsublib.jar",
+ dir + "liblib.jar",
+ dir + "libbin.jar",
+ dir + "bin_resources.jar");
+ assertThat(inputs).containsNoneOf(dir + "lib_resources.jar", dir + "sublib_resources.jar");
+ }
+
+ @Test
+ public void testInheritedRInRuntimeJarsWhenSpecified() throws Exception {
+ String dir = "java/r/android/";
+ scratch.file(
+ dir + "BUILD",
+ "android_library(name = 'sublib',",
+ " manifest = 'AndroidManifest.xml',",
+ " resource_files = glob(['res3/**']),",
+ " srcs =['sublib.java'],",
+ " )",
+ "android_library(name = 'lib',",
+ " manifest = 'AndroidManifest.xml',",
+ " resource_files = glob(['res2/**']),",
+ " deps = [':sublib'],",
+ " srcs =['lib.java'],",
+ " )",
+ "android_binary(name = 'bin',",
+ " manifest = 'AndroidManifest.xml',",
+ " resource_files = glob(['res/**']),",
+ " deps = [':lib'],",
+ " srcs =['bin.java'],",
+ " )");
+
+ // TODO(b/37087277): Add a configuration flag once this behavior is no longer the default.
+
+ Action deployJarAction =
+ getGeneratingAction(
+ getFileConfiguredTarget("//java/r/android:bin_deploy.jar").getArtifact());
+ List<String> inputs = ActionsTestUtil.prettyArtifactNames(deployJarAction.getInputs());
+
+ assertThat(inputs)
+ .containsAllOf(
+ dir + "libsublib.jar",
+ dir + "liblib.jar",
+ dir + "libbin.jar",
+ dir + "bin_resources.jar",
+ dir + "lib_resources.jar",
+ dir + "sublib_resources.jar");
+ }
+
+ @Test
public void testLocalResourcesUseRClassGenerator() throws Exception {
scratch.file("java/r/android/BUILD",
"android_library(name = 'lib',",