aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2016-05-04 23:15:00 +0000
committerGravatar Kristina Chodorow <kchodorow@google.com>2016-05-05 19:10:24 +0000
commit88ccf0c9f490a5138719c3bb476b17eb1d8384e2 (patch)
treed5592d85c0f06d941b5f9dac26fccebf0190796f /src
parent1f2cb5c56291efab2989e6a342898560ebef3fca (diff)
[Android] Support aapt-generated main dex specs.
Add bazel support for using the "aapt -D" command to generate a proguard specification for components which need to be in the main dex. -- MOS_MIGRATED_REVID=121531584
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/google/devtools/build/lib/BUILD1
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidAaptActionHelper.java32
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java39
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java1
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java11
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidSdk.java16
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidSdkProvider.java9
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java23
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/ResourceApk.java15
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AaptCommandBuilder.java7
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java8
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java5
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java1
13 files changed, 142 insertions, 26 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD
index 71ca85b3bd..a2848fa67a 100644
--- a/src/main/java/com/google/devtools/build/lib/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/BUILD
@@ -774,6 +774,7 @@ java_library(
"//src/main/java/com/google/devtools/common/options",
"//src/main/protobuf:android_deploy_info_java_proto",
"//src/main/protobuf:apk_manifest_java_proto",
+ "//third_party:android_sdklib",
"//third_party:jsr305",
"//third_party/protobuf",
],
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidAaptActionHelper.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidAaptActionHelper.java
index 51587308b5..8442bbc968 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidAaptActionHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidAaptActionHelper.java
@@ -33,11 +33,13 @@ import com.google.devtools.build.lib.util.Preconditions;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
+import javax.annotation.Nullable;
+
/**
* Helper class to generate Android aapt actions.
*/
@@ -173,6 +175,12 @@ public final class AndroidAaptActionHelper {
private List<String> createAaptCommand(String actionKind, Artifact output,
Artifact rTxtOutput, boolean inlineConstants, String... outputArgs) {
+ return createAaptCommand(
+ actionKind, output, rTxtOutput, inlineConstants, Arrays.asList(outputArgs));
+ }
+
+ private List<String> createAaptCommand(String actionKind, Artifact output,
+ Artifact rTxtOutput, boolean inlineConstants, Collection<String> outputArgs) {
List<String> args = new ArrayList<>();
args.addAll(getArgs(output, actionKind, ResourceType.RESOURCES));
args.addAll(getArgs(output, actionKind, ResourceType.ASSETS));
@@ -181,7 +189,7 @@ public final class AndroidAaptActionHelper {
args.add(
AndroidSdkProvider.fromRuleContext(ruleContext).getAapt().getExecutable().getExecPathString());
args.add("package");
- Collections.addAll(args, outputArgs);
+ args.addAll(outputArgs);
// Allow overlay in case the same resource appears in more than one target,
// giving precedence to the order in which they are found. This is needed
// in order to support android library projects.
@@ -266,13 +274,25 @@ public final class AndroidAaptActionHelper {
"_" + resourceType.getAttribute() + "_" + actionKind));
}
- public void createGenerateProguardAction(Artifact outputSpec) {
- List<String> aaptCommand = createAaptCommand("proguard", outputSpec, null, true,
- "-G", outputSpec.getExecPathString());
+ public void createGenerateProguardAction(
+ Artifact outputSpec, @Nullable Artifact outputMainDexSpec) {
+ ImmutableList.Builder<Artifact> outputs = ImmutableList.builder();
+ ImmutableList.Builder<String> aaptArgs = ImmutableList.builder();
+
+ outputs.add(outputSpec);
+ aaptArgs.add("-G").add(outputSpec.getExecPathString());
+
+ if (outputMainDexSpec != null) {
+ aaptArgs.add("-D").add(outputMainDexSpec.getExecPathString());
+ outputs.add(outputMainDexSpec);
+ }
+
+ List<String> aaptCommand =
+ createAaptCommand("proguard", outputSpec, null, true, aaptArgs.build());
ruleContext.registerAction(new SpawnAction.Builder()
.addInputs(getInputs())
.addTool(AndroidSdkProvider.fromRuleContext(ruleContext).getAapt())
- .addOutput(outputSpec)
+ .addOutputs(outputs.build())
.setExecutable(
ruleContext.getExecutablePrerequisite("$android_aapt_apk_generator", Mode.HOST))
.setCommandLine(CommandLine.of(aaptCommand, false))
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 b8a2a9c828..ad773bcbe1 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
@@ -232,6 +232,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
versionName,
false, /* incremental */
ProguardHelper.getProguardConfigArtifact(ruleContext, ""),
+ createMainDexProguardSpec(ruleContext),
null, /* manifestOut */
ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_ZIP));
if (ruleContext.hasErrors()) {
@@ -254,6 +255,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
versionName,
true, /* incremental */
ProguardHelper.getProguardConfigArtifact(ruleContext, "incremental"),
+ null, /* mainDexProguardCfg */
null, /* manifestOut */
null /* mergedResourcesOut */);
if (ruleContext.hasErrors()) {
@@ -276,6 +278,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
versionName,
true, /* incremental */
ProguardHelper.getProguardConfigArtifact(ruleContext, "incremental_split"),
+ null, /* mainDexProguardCfg */
null, /* manifestOut */
null /* mergedResourcesOut */);
if (ruleContext.hasErrors()) {
@@ -302,10 +305,12 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
ruleContext,
resourceDeps,
true,
- ProguardHelper.getProguardConfigArtifact(ruleContext, ""));
+ ProguardHelper.getProguardConfigArtifact(ruleContext, ""),
+ createMainDexProguardSpec(ruleContext));
} else {
resourceApk = applicationManifest.useCurrentResources(ruleContext,
- ProguardHelper.getProguardConfigArtifact(ruleContext, ""));
+ ProguardHelper.getProguardConfigArtifact(ruleContext, ""),
+ createMainDexProguardSpec(ruleContext));
}
incrementalResourceApk = applicationManifest
.addStubApplication(ruleContext)
@@ -315,7 +320,8 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
ruleContext,
resourceDeps,
false,
- ProguardHelper.getProguardConfigArtifact(ruleContext, "incremental"));
+ ProguardHelper.getProguardConfigArtifact(ruleContext, "incremental"),
+ null /* mainDexProguardConfig */);
if (ruleContext.hasErrors()) {
return null;
}
@@ -326,7 +332,8 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
ruleContext,
resourceDeps,
false,
- ProguardHelper.getProguardConfigArtifact(ruleContext, "incremental_split"));
+ ProguardHelper.getProguardConfigArtifact(ruleContext, "incremental_split"),
+ null /* mainDexProguardConfig */);
if (ruleContext.hasErrors()) {
return null;
}
@@ -416,6 +423,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
jarToDex,
isBinaryJarFiltered,
androidCommon,
+ resourceApk.getMainDexProguardConfig(),
resourceClasses);
if (dexingOutput == null) {
return null;
@@ -1056,6 +1064,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
Artifact proguardedJar,
boolean isBinaryJarFiltered,
AndroidCommon common,
+ @Nullable Artifact mainDexProguardSpec,
JavaTargetAttributes attributes)
throws InterruptedException {
boolean finalJarIsDerived = isBinaryJarFiltered || binaryJar != proguardedJar;
@@ -1114,7 +1123,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
if (multidexMode == MultidexMode.LEGACY) {
// For legacy multidex, we need to generate a list for the dexer's --main-dex-list flag.
- mainDexList = createMainDexListAction(ruleContext, proguardedJar);
+ mainDexList = createMainDexListAction(ruleContext, proguardedJar, mainDexProguardSpec);
}
Artifact classesDex = getDxArtifact(ruleContext, "classes.dex.zip");
@@ -1351,7 +1360,8 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
* --main-dex-list flag (which specifies the classes that need to be directly in classes.dex).
* Returns the file containing the list.
*/
- static Artifact createMainDexListAction(RuleContext ruleContext, Artifact jar) {
+ static Artifact createMainDexListAction(
+ RuleContext ruleContext, Artifact jar, @Nullable Artifact mainDexProguardSpec) {
// Process the input jar through Proguard into an intermediate, streamlined jar.
Artifact strippedJar = AndroidBinary.getDxArtifact(ruleContext, "main_dex_intermediate.jar");
AndroidSdkProvider sdk = AndroidSdkProvider.fromRuleContext(ruleContext);
@@ -1373,10 +1383,14 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
.addArgument("-dontobfuscate")
.addArgument("-dontpreverify");
- List<Artifact> specs = ruleContext.getPrerequisiteArtifacts(
- "main_dex_proguard_specs", Mode.TARGET).list();
+ List<Artifact> specs = new ArrayList<>();
+ specs.addAll(
+ ruleContext.getPrerequisiteArtifacts("main_dex_proguard_specs", Mode.TARGET).list());
if (specs.isEmpty()) {
- specs = ImmutableList.of(sdk.getMainDexClasses());
+ specs.add(sdk.getMainDexClasses());
+ }
+ if (mainDexProguardSpec != null) {
+ specs.add(mainDexProguardSpec);
}
for (Artifact spec : specs) {
@@ -1424,6 +1438,13 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
return splitResources;
}
+ @Nullable
+ private static Artifact createMainDexProguardSpec(RuleContext ruleContext) {
+ return AndroidSdkProvider.fromRuleContext(ruleContext).getAaptSupportsMainDexGeneration()
+ ? ProguardHelper.getProguardConfigArtifact(ruleContext, "main_dex")
+ : null;
+ }
+
/**
* Builder class for {@link com.google.devtools.build.lib.analysis.actions.SpawnAction}s that
* generate APKs.
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 2e4e7756c4..ed5a839a27 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
@@ -96,6 +96,7 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory {
null /* versionName */,
false,
null /* proguardCfgOut */,
+ null, /* mainDexProguardCfg */
ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_LIBRARY_MANIFEST),
null /* mergedResourcesOut */);
if (ruleContext.hasErrors()) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java
index 2c3606f1e1..7967f92934 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java
@@ -58,6 +58,7 @@ public class AndroidResourcesProcessorBuilder {
private ResourceContainer primary;
private ResourceDependencies dependencies;
private Artifact proguardOut;
+ private Artifact mainDexProguardOut;
private Artifact rTxtOut;
private Artifact sourceJarOut;
private boolean debug = false;
@@ -134,6 +135,11 @@ public class AndroidResourcesProcessorBuilder {
return this;
}
+ public AndroidResourcesProcessorBuilder setMainDexProguardOut(Artifact mainDexProguardCfg) {
+ this.mainDexProguardOut = mainDexProguardCfg;
+ return this;
+ }
+
public AndroidResourcesProcessorBuilder setRTxtOut(Artifact rTxtOut) {
this.rTxtOut = rTxtOut;
return this;
@@ -308,6 +314,11 @@ public class AndroidResourcesProcessorBuilder {
outs.add(proguardOut);
}
+ if (mainDexProguardOut != null) {
+ builder.addExecPath("--mainDexProguardOutput", mainDexProguardOut);
+ outs.add(mainDexProguardOut);
+ }
+
if (manifestOut != null) {
builder.addExecPath("--manifestOutput", manifestOut);
outs.add(manifestOut);
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSdk.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSdk.java
index 016fedf990..a4d32e9ec4 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSdk.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSdk.java
@@ -13,6 +13,7 @@
// limitations under the License.
package com.google.devtools.build.lib.rules.android;
+import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
@@ -31,6 +32,8 @@ import com.google.devtools.build.lib.rules.java.JavaConfiguration;
import com.google.devtools.build.lib.rules.java.JavaToolchainProvider;
import com.google.devtools.build.lib.syntax.Type;
+import com.android.sdklib.repository.FullRevision;
+
import java.util.Collection;
/**
@@ -48,6 +51,18 @@ public class AndroidSdk implements RuleConfiguredTargetFactory {
String buildToolsVersion = AggregatingAttributeMapper.of(ruleContext.getRule())
.get("build_tools_version", Type.STRING);
+ FullRevision parsedBuildToolsVersion = null;
+ try {
+ parsedBuildToolsVersion =
+ Strings.isNullOrEmpty(buildToolsVersion)
+ ? null
+ : FullRevision.parseRevision(buildToolsVersion);
+ } catch (NumberFormatException nfe) {
+ ruleContext.attributeError("build_tools_version", "Invalid version: " + buildToolsVersion);
+ }
+ boolean aaptSupportsMainDexGeneration =
+ parsedBuildToolsVersion == null
+ || parsedBuildToolsVersion.compareTo(new FullRevision(24)) >= 0;
FilesToRunProvider aidl = ruleContext.getExecutablePrerequisite("aidl", Mode.HOST);
FilesToRunProvider aapt = ruleContext.getExecutablePrerequisite("aapt", Mode.HOST);
FilesToRunProvider apkBuilder = ruleContext.getExecutablePrerequisite(
@@ -91,6 +106,7 @@ public class AndroidSdk implements RuleConfiguredTargetFactory {
AndroidSdkProvider.class,
new AndroidSdkProvider(
buildToolsVersion,
+ aaptSupportsMainDexGeneration,
frameworkAidl,
androidJar,
shrinkedAndroidJar,
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSdkProvider.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSdkProvider.java
index 2a3065fc42..59efb5505c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSdkProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSdkProvider.java
@@ -29,6 +29,7 @@ import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
public final class AndroidSdkProvider implements TransitiveInfoProvider {
private final String buildToolsVersion;
+ private final boolean aaptSupportsMainDexGeneration;
private final Artifact frameworkAidl;
private final Artifact androidJar;
private final Artifact shrinkedAndroidJar;
@@ -50,6 +51,7 @@ public final class AndroidSdkProvider implements TransitiveInfoProvider {
public AndroidSdkProvider(
String buildToolsVersion,
+ boolean aaptSupportsMainDexGeneration,
Artifact frameworkAidl,
Artifact androidJar,
Artifact shrinkedAndroidJar,
@@ -70,6 +72,7 @@ public final class AndroidSdkProvider implements TransitiveInfoProvider {
FilesToRunProvider resourceExtractor) {
this.buildToolsVersion = buildToolsVersion;
+ this.aaptSupportsMainDexGeneration = aaptSupportsMainDexGeneration;
this.frameworkAidl = frameworkAidl;
this.androidJar = androidJar;
this.shrinkedAndroidJar = shrinkedAndroidJar;
@@ -122,7 +125,11 @@ public final class AndroidSdkProvider implements TransitiveInfoProvider {
public String getBuildToolsVersion() {
return buildToolsVersion;
}
-
+
+ public boolean getAaptSupportsMainDexGeneration() {
+ return aaptSupportsMainDexGeneration;
+ }
+
public Artifact getFrameworkAidl() {
return frameworkAidl;
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java b/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java
index c0f1d1ed54..252ed1e8e9 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java
@@ -34,6 +34,8 @@ import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.List;
import java.util.Map;
+import javax.annotation.Nullable;
+
/** Represents a AndroidManifest, that may have been merged from dependencies. */
public final class ApplicationManifest {
public static ApplicationManifest fromResourcesRule(RuleContext ruleContext) {
@@ -230,6 +232,7 @@ public final class ApplicationManifest {
incremental,
data,
proguardCfg,
+ null, /* Artifact mainDexProguardCfg */
null, /* Artifact manifestOut */
null /* Artifact mergedResources */);
}
@@ -253,6 +256,7 @@ public final class ApplicationManifest {
String versionName,
boolean incremental,
Artifact proguardCfg,
+ @Nullable Artifact mainDexProguardCfg,
Artifact manifestOut,
Artifact mergedResources) throws InterruptedException {
LocalResourceContainer data = new LocalResourceContainer.Builder(ruleContext)
@@ -287,6 +291,7 @@ public final class ApplicationManifest {
incremental,
data,
proguardCfg,
+ mainDexProguardCfg,
manifestOut,
mergedResources);
}
@@ -307,6 +312,7 @@ public final class ApplicationManifest {
boolean incremental,
LocalResourceContainer data,
Artifact proguardCfg,
+ @Nullable Artifact mainDexProguardCfg,
Artifact manifestOut,
Artifact mergedResources) throws InterruptedException {
ResourceContainer resourceContainer = checkForInlinedResources(
@@ -340,6 +346,7 @@ public final class ApplicationManifest {
.withDependencies(resourceDeps)
.setDensities(densities)
.setProguardOut(proguardCfg)
+ .setMainDexProguardOut(mainDexProguardCfg)
.setApplicationId(applicationId)
.setVersionCode(versionCode)
.setVersionName(versionName);
@@ -355,7 +362,7 @@ public final class ApplicationManifest {
return new ResourceApk(
resourceApk, processed.getJavaSourceJar(), resourceDeps, processed, manifest,
- proguardCfg, false);
+ proguardCfg, mainDexProguardCfg, false);
}
private static ResourceContainer checkForInlinedResources(ResourceContainer resourceContainer,
@@ -375,14 +382,16 @@ public final class ApplicationManifest {
}
/** Uses the resource apk from the resources attribute, as opposed to recompiling. */
- public ResourceApk useCurrentResources(RuleContext ruleContext, Artifact proguardCfg) {
+ public ResourceApk useCurrentResources(
+ RuleContext ruleContext, Artifact proguardCfg, @Nullable Artifact mainDexProguardCfg) {
ResourceContainer resourceContainer = Iterables.getOnlyElement(
AndroidCommon.getAndroidResources(ruleContext).getDirectAndroidResources());
new AndroidAaptActionHelper(
ruleContext,
resourceContainer.getManifest(),
- Lists.newArrayList(resourceContainer)).createGenerateProguardAction(proguardCfg);
+ Lists.newArrayList(resourceContainer))
+ .createGenerateProguardAction(proguardCfg, mainDexProguardCfg);
return new ResourceApk(
resourceContainer.getApk(),
@@ -391,6 +400,7 @@ public final class ApplicationManifest {
resourceContainer,
manifest,
proguardCfg,
+ mainDexProguardCfg,
false);
}
@@ -406,7 +416,8 @@ public final class ApplicationManifest {
RuleContext ruleContext,
ResourceDependencies resourceDeps,
boolean createSource,
- Artifact proguardCfg) throws InterruptedException {
+ Artifact proguardCfg,
+ @Nullable Artifact mainDexProguardCfg) throws InterruptedException {
TransitiveInfoCollection resourcesPrerequisite =
ruleContext.getPrerequisite("resources", Mode.TARGET);
@@ -478,10 +489,10 @@ public final class ApplicationManifest {
resourceContainer.isManifestExported(),
resourceContainer.getRTxt(), null);
- aaptActionHelper.createGenerateProguardAction(proguardCfg);
+ aaptActionHelper.createGenerateProguardAction(proguardCfg, mainDexProguardCfg);
return new ResourceApk(resourceApk, updatedResources.getJavaSourceJar(),
- resourceDeps, updatedResources, manifest, proguardCfg, true);
+ resourceDeps, updatedResources, manifest, proguardCfg, mainDexProguardCfg, true);
}
public Artifact getManifest() {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceApk.java b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceApk.java
index 0b7bbfc4fc..505be25d3a 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceApk.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceApk.java
@@ -26,15 +26,16 @@ import javax.annotation.Nullable;
*/
@Immutable
public final class ResourceApk {
- // TODO(bazel-team): The only field that is legitimately nullable is javaSrcJar. The rest is
- // marked as such due to .fromTransitiveResources(). It seems like there should be a better way
- // to do this.
+ // TODO(bazel-team): The only fields that are legitimately nullable are javaSrcJar and
+ // mainDexProguardConfig. The rest are marked as such due to .fromTransitiveResources().
+ // It seems like there should be a better way to do this.
@Nullable private final Artifact resourceApk; // The .ap_ file
@Nullable private final Artifact resourceJavaSrcJar; // Source jar containing R.java and friends
private final ResourceDependencies resourceDeps;
@Nullable private final ResourceContainer primaryResource;
@Nullable private final Artifact manifest; // The non-binary XML version of AndroidManifest.xml
@Nullable private final Artifact resourceProguardConfig;
+ @Nullable private final Artifact mainDexProguardConfig;
private final boolean legacy;
public ResourceApk(
@@ -44,6 +45,7 @@ public final class ResourceApk {
@Nullable ResourceContainer primaryResource,
@Nullable Artifact manifest,
@Nullable Artifact resourceProguardConfig,
+ @Nullable Artifact mainDexProguardConfig,
boolean legacy) {
this.resourceApk = resourceApk;
this.resourceJavaSrcJar = resourceJavaSrcJar;
@@ -51,6 +53,7 @@ public final class ResourceApk {
this.primaryResource = primaryResource;
this.manifest = manifest;
this.resourceProguardConfig = resourceProguardConfig;
+ this.mainDexProguardConfig = mainDexProguardConfig;
this.legacy = legacy;
}
@@ -76,13 +79,17 @@ public final class ResourceApk {
public static ResourceApk fromTransitiveResources(
ResourceDependencies resourceDeps) {
- return new ResourceApk(null, null, resourceDeps, null, null, null, false);
+ return new ResourceApk(null, null, resourceDeps, null, null, null, null, false);
}
public Artifact getResourceProguardConfig() {
return resourceProguardConfig;
}
+ public Artifact getMainDexProguardConfig() {
+ return mainDexProguardConfig;
+ }
+
public ResourceDependencies getResourceDependencies() {
return resourceDeps;
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/AaptCommandBuilder.java b/src/tools/android/java/com/google/devtools/build/android/AaptCommandBuilder.java
index 83591e73d5..d1f5a54dcb 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AaptCommandBuilder.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AaptCommandBuilder.java
@@ -83,6 +83,13 @@ class AaptCommandBuilder {
return this;
}
+ AaptCommandBuilder maybeAdd(String flag, @Nullable Path path, FullRevision requiredVersion) {
+ if (buildToolsVersion == null || buildToolsVersion.compareTo(requiredVersion) >= 0) {
+ add(flag, path);
+ }
+ return this;
+ }
+
AaptCommandBuilder maybeAdd(String flag, FullRevision requiredVersion) {
if (buildToolsVersion == null || buildToolsVersion.compareTo(requiredVersion) >= 0) {
add(flag);
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java
index ba8e557f62..29112c97ca 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessingAction.java
@@ -141,6 +141,13 @@ public class AndroidResourceProcessingAction {
help = "Path for the proguard file.")
public Path proguardOutput;
+ @Option(name = "mainDexProguardOutput",
+ defaultValue = "null",
+ converter = PathConverter.class,
+ category = "output",
+ help = "Path for the main dex proguard file.")
+ public Path mainDexProguardOutput;
+
@Option(name = "manifestOutput",
defaultValue = "null",
converter = PathConverter.class,
@@ -285,6 +292,7 @@ public class AndroidResourceProcessingAction {
generatedSources,
options.packagePath,
options.proguardOutput,
+ options.mainDexProguardOutput,
options.resourcesOutput != null
? processedManifestData.getResourceDir().resolve("values").resolve("public.xml")
: null);
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
index 714970b75f..97eedb18d0 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
@@ -329,6 +329,7 @@ public class AndroidResourceProcessor {
Path sourceOut,
Path packageOut,
Path proguardOut,
+ Path mainDexProguardOut,
Path publicResourcesOut)
throws IOException, InterruptedException, LoggedErrorException {
List<SymbolFileProvider> libraries = new ArrayList<>();
@@ -370,6 +371,7 @@ public class AndroidResourceProcessor {
.maybeAdd("--output-text-symbols", prepareOutputPath(sourceOut), sourceOut != null)
.add("-F", packageOut)
.add("-G", proguardOut)
+ .maybeAdd("-D", mainDexProguardOut, new FullRevision(24))
.add("-P", publicResourcesOut)
.maybeAdd("--debug-mode", debug)
.add("--custom-package", customPackageForR)
@@ -398,6 +400,9 @@ public class AndroidResourceProcessor {
if (proguardOut != null) {
Files.setLastModifiedTime(proguardOut, FileTime.fromMillis(0L));
}
+ if (mainDexProguardOut != null) {
+ Files.setLastModifiedTime(mainDexProguardOut, FileTime.fromMillis(0L));
+ }
if (packageOut != null) {
Files.setLastModifiedTime(packageOut, FileTime.fromMillis(0L));
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java b/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java
index d5b9774bf3..86ae74d81d 100644
--- a/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java
@@ -217,6 +217,7 @@ public class ResourceShrinkerAction {
null /* sourceOutputDir */,
options.shrunkApk,
null /* proguardOutput */,
+ null /* mainDexProguardOutput */,
null /* publicResourcesOut */);
if (options.shrunkResources != null) {
resourceProcessor.createResourcesZip(shrunkResources, resourceFiles.resolve("assets"),