aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2017-02-23 17:39:16 +0000
committerGravatar Irina Iancu <elenairina@google.com>2017-02-24 08:29:39 +0000
commit4ae1f5df4a8e182763b1d01ed6c99b7232008b4c (patch)
tree5dcff0367a24be3ca6a7bdfc1d7829254cfbaf9c /src/main/java/com/google/devtools/build
parentbb4615c2fabe20121ed8ef5dd786cbf4d5f7c7d4 (diff)
Filter android_binary resources during analysis
Before this change, resource_configuration_filters were only used to filter resources out of android_binary targets during resource processing. Instead, we can filter these unwanted resources out during analysis. This means we won't have to copy these resources for use in execution, and that execution itself will have a smaller set of inputs. This should produce a speed-up in android_binary targets with resource_configuration_filters. Also add a flag that controls this behavior. Currently, the flag defaults to not doing this prefiltering. We'll change that after further testing. Also, do some related cleanup: - Replace repeated used of the constant "resource_configuration_filters" with references to the new class - Pass around instances of the new class rather that List<String> objects meant to represent ResourceConfigurationFilters -- PiperOrigin-RevId: 148353501 MOS_MIGRATED_REVID=148353501
Diffstat (limited to 'src/main/java/com/google/devtools/build')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java14
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinaryOnlyRule.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java16
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java18
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/ResourceConfigurationFilter.java203
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/ResourceContainer.java7
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/ResourceDependencies.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/android/ResourceShrinkerActionBuilder.java11
10 files changed, 264 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 30352944b3..7e683c74de 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
@@ -215,7 +215,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
resourceDeps,
ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_R_TXT),
null, /* Artifact symbolsTxt */
- ruleContext.getTokenizedStringListAttr("resource_configuration_filters"),
+ ResourceConfigurationFilter.fromRuleContext(ruleContext),
ruleContext.getTokenizedStringListAttr("nocompress_extensions"),
ruleContext.attributes().get("crunch_png", Type.BOOLEAN),
ruleContext.getTokenizedStringListAttr("densities"),
@@ -237,7 +237,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
resourceDeps,
null, /* Artifact rTxt */
null, /* Artifact symbolsTxt */
- ruleContext.getTokenizedStringListAttr("resource_configuration_filters"),
+ ResourceConfigurationFilter.fromRuleContext(ruleContext),
ruleContext.getTokenizedStringListAttr("nocompress_extensions"),
ruleContext.attributes().get("crunch_png", Type.BOOLEAN),
ruleContext.getTokenizedStringListAttr("densities"),
@@ -258,7 +258,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
resourceDeps,
null, /* Artifact rTxt */
null, /* Artifact symbolsTxt */
- ruleContext.getTokenizedStringListAttr("resource_configuration_filters"),
+ ResourceConfigurationFilter.fromRuleContext(ruleContext),
ruleContext.getTokenizedStringListAttr("nocompress_extensions"),
ruleContext.attributes().get("crunch_png", Type.BOOLEAN),
ruleContext.getTokenizedStringListAttr("densities"),
@@ -279,7 +279,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
resourceDeps,
null, /* Artifact rTxt */
null, /* Artifact symbolsTxt */
- ruleContext.getTokenizedStringListAttr("resource_configuration_filters"),
+ ResourceConfigurationFilter.fromRuleContext(ruleContext),
ruleContext.getTokenizedStringListAttr("nocompress_extensions"),
ruleContext.attributes().get("crunch_png", Type.BOOLEAN),
ruleContext.getTokenizedStringListAttr("densities"),
@@ -1131,8 +1131,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
.withProguardMapping(proguardOutput.getMapping())
.withPrimary(resourceApk.getPrimaryResource())
.withDependencies(resourceApk.getResourceDependencies())
- .setConfigurationFilters(
- ruleContext.getTokenizedStringListAttr("resource_configuration_filters"))
+ .setConfigurationFilters(ResourceConfigurationFilter.fromRuleContext(ruleContext))
.setUncompressedExtensions(
ruleContext.getTokenizedStringListAttr("nocompress_extensions"))
.build();
@@ -1731,8 +1730,7 @@ public abstract class AndroidBinary implements RuleConfiguredTargetFactory {
ResourceDependencies resourceDeps) {
return Iterables.size(resourceDeps.getResources()) > 1
|| ruleContext.attributes().isAttributeValueExplicitlySpecified("densities")
- || ruleContext.attributes().isAttributeValueExplicitlySpecified(
- "resource_configuration_filters")
+ || ResourceConfigurationFilter.hasFilters(ruleContext)
|| ruleContext.attributes().isAttributeValueExplicitlySpecified("nocompress_extensions");
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinaryOnlyRule.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinaryOnlyRule.java
index 63bce10067..d4bb19487f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinaryOnlyRule.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinaryOnlyRule.java
@@ -84,7 +84,7 @@ public final class AndroidBinaryOnlyRule implements RuleDefinition {
A list of resource configuration filters, such 'en' that will limit the resources in the
apk to only the ones in the 'en' configuration.
<!-- #END_BLAZE_RULE.ATTRIBUTE --> */
- .add(attr("resource_configuration_filters", STRING_LIST))
+ .add(attr(ResourceConfigurationFilter.ATTR_NAME, STRING_LIST))
/* <!-- #BLAZE_RULE(android_binary).ATTRIBUTE(shrink_resources) -->
Whether to perform resource shrinking. Resources that are not used by the binary will be
removed from the APK. This is only supported for rules using local resources (i.e. the
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 b6923579cf..785217716d 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
@@ -416,6 +416,16 @@ public class AndroidConfiguration extends BuildConfiguration.Fragment {
help = "Use SingleJar for multidex dex extraction.")
public boolean useSingleJarForMultidex;
+ @Option(name = "experimental_android_use_resource_prefiltering",
+ defaultValue = "false",
+ category = "undocumented",
+ help = "When building android_binary targets, apply resource_configuration_filters during"
+ + " the analysis phase. Normally, this filtering doesn't occur until near the end of "
+ + "resource processing in the execution phase. Prefiltering resources improves "
+ + "performance for binaries with resource_configuration_filters and lots of resources."
+ )
+ public boolean useResourcePrefiltering;
+
@Override
public void addAllLabels(Multimap<String, Label> labelMap) {
if (androidCrosstoolTop != null) {
@@ -495,6 +505,7 @@ public class AndroidConfiguration extends BuildConfiguration.Fragment {
private final ApkSigningMethod apkSigningMethod;
private final boolean useSingleJarApkBuilder;
private final boolean useSingleJarForMultidex;
+ private final boolean useResourcePrefiltering;
AndroidConfiguration(Options options, Label androidSdk) {
this.sdk = androidSdk;
@@ -523,6 +534,7 @@ public class AndroidConfiguration extends BuildConfiguration.Fragment {
this.useSingleJarApkBuilder = options.useSingleJarApkBuilder;
this.useSingleJarForMultidex = options.useSingleJarForMultidex;
this.useRexToCompressDexFiles = options.useRexToCompressDexFiles;
+ this.useResourcePrefiltering = options.useResourcePrefiltering;
}
public String getCpu() {
@@ -617,6 +629,10 @@ public class AndroidConfiguration extends BuildConfiguration.Fragment {
public boolean useSingleJarForMultidex() {
return useSingleJarForMultidex;
}
+
+ public boolean useResourcePrefiltering() {
+ return useResourcePrefiltering;
+ }
@Override
public void addGlobalMakeVariables(ImmutableMap.Builder<String, String> globalMakeEnvBuilder) {
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 529fe37ac3..a3ab7878b9 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
@@ -84,7 +84,7 @@ public abstract class AndroidLibrary implements RuleConfiguredTargetFactory {
ResourceDependencies.fromRuleDeps(ruleContext, JavaCommon.isNeverLink(ruleContext)),
ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_R_TXT),
ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_SYMBOLS),
- ImmutableList.<String>of(), /* configurationFilters */
+ ResourceConfigurationFilter.empty(ruleContext),
ImmutableList.<String>of(), /* uncompressedExtensions */
false, /* crunchPng */
ImmutableList.<String>of(), /* densities */
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 c10228c707..52dd4170b5 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
@@ -69,7 +69,7 @@ public class AndroidResourcesProcessorBuilder {
private Artifact rTxtOut;
private Artifact sourceJarOut;
private boolean debug = false;
- private List<String> resourceConfigs = Collections.emptyList();
+ private ResourceConfigurationFilter resourceConfigs;
private List<String> uncompressedExtensions = Collections.emptyList();
private Artifact apkOut;
private final AndroidSdkProvider sdk;
@@ -96,6 +96,7 @@ public class AndroidResourcesProcessorBuilder {
this.sdk = AndroidSdkProvider.fromRuleContext(ruleContext);
this.ruleContext = ruleContext;
this.spawnActionBuilder = new SpawnAction.Builder();
+ this.resourceConfigs = ResourceConfigurationFilter.empty(ruleContext);
}
/**
@@ -138,7 +139,8 @@ public class AndroidResourcesProcessorBuilder {
return this;
}
- public AndroidResourcesProcessorBuilder setConfigurationFilters(List<String> resourceConfigs) {
+ public AndroidResourcesProcessorBuilder setConfigurationFilters(
+ ResourceConfigurationFilter resourceConfigs) {
this.resourceConfigs = resourceConfigs;
return this;
}
@@ -272,7 +274,7 @@ public class AndroidResourcesProcessorBuilder {
outs.add(apkOut);
}
if (!resourceConfigs.isEmpty()) {
- builder.addJoinStrings("--resourceConfigs", ",", resourceConfigs);
+ builder.add("--resourceConfigs").add(resourceConfigs.getFilterString());
}
if (!densities.isEmpty()) {
builder.addJoinStrings("--densities", ",", densities);
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 019a85d8d7..4467c823c7 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
@@ -300,7 +300,7 @@ public final class ApplicationManifest {
ruleContext,
false, /* isLibrary */
resourceDeps,
- ImmutableList.<String>of(), /* configurationFilters */
+ ResourceConfigurationFilter.empty(ruleContext),
ImmutableList.<String>of(), /* uncompressedExtensions */
true, /* crunchPng */
ImmutableList.<String>of(), /* densities */
@@ -346,7 +346,7 @@ public final class ApplicationManifest {
ruleContext,
true, /* isLibrary */
resourceDeps,
- ImmutableList.<String>of(), /* List<String> configurationFilters */
+ ResourceConfigurationFilter.empty(ruleContext),
ImmutableList.<String>of(), /* List<String> uncompressedExtensions */
false, /* crunchPng */
ImmutableList.<String>of(), /* List<String> densities */
@@ -368,7 +368,7 @@ public final class ApplicationManifest {
ResourceDependencies resourceDeps,
Artifact rTxt,
Artifact symbols,
- List<String> configurationFilters,
+ ResourceConfigurationFilter configurationFilters,
List<String> uncompressedExtensions,
boolean crunchPng,
List<String> densities,
@@ -421,7 +421,7 @@ public final class ApplicationManifest {
RuleContext ruleContext,
boolean isLibrary,
ResourceDependencies resourceDeps,
- List<String> configurationFilters,
+ ResourceConfigurationFilter configurationFilters,
List<String> uncompressedExtensions,
boolean crunchPng,
List<String> densities,
@@ -443,6 +443,11 @@ public final class ApplicationManifest {
if (ruleContext.hasErrors()) {
return null;
}
+
+ // Filter the resources during analysis to prevent processing of and dependencies on unwanted
+ // resources during execution.
+ resourceContainer = resourceContainer.filter(configurationFilters);
+ resourceDeps = resourceDeps.filter(configurationFilters);
ResourceContainer processed;
if (isLibrary && AndroidCommon.getAndroidConfig(ruleContext).useParallelResourceProcessing()) {
@@ -599,8 +604,7 @@ public final class ApplicationManifest {
AndroidAaptActionHelper aaptActionHelper = new AndroidAaptActionHelper(ruleContext,
getManifest(), Lists.newArrayList(resourceContainers));
- List<String> resourceConfigurationFilters =
- ruleContext.getTokenizedStringListAttr("resource_configuration_filters");
+ String resourceConfigurationFilters = ResourceConfigurationFilter.extractFilters(ruleContext);
List<String> uncompressedExtensions =
ruleContext.getTokenizedStringListAttr("nocompress_extensions");
@@ -610,7 +614,7 @@ public final class ApplicationManifest {
additionalAaptOpts.add("-0").add(extension);
}
if (!resourceConfigurationFilters.isEmpty()) {
- additionalAaptOpts.add("-c").add(Joiner.on(",").join(resourceConfigurationFilters));
+ additionalAaptOpts.add("-c").add(resourceConfigurationFilters);
}
Artifact javaSourcesJar = null;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceConfigurationFilter.java b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceConfigurationFilter.java
new file mode 100644
index 0000000000..fb27cdd833
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceConfigurationFilter.java
@@ -0,0 +1,203 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.google.devtools.build.lib.rules.android;
+
+import com.android.ide.common.resources.configuration.FolderConfiguration;
+import com.android.ide.common.resources.configuration.VersionQualifier;
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+
+/** Filters resources based on their qualifiers. */
+public class ResourceConfigurationFilter {
+ public static final String ATTR_NAME = "resource_configuration_filters";
+
+ /** The current {@link RuleContext}, used for reporting errors. */
+ private final RuleContext ruleContext;
+
+ /**
+ * A list of filters that should be applied during the analysis phase. If resources should not be
+ * filtered in analysis (e.g., if prefilter_resources = 0), this list should be empty.
+ */
+ private final ImmutableList<FolderConfiguration> filters;
+
+ /**
+ * The raw value of the resource_configuration_filters attribute, as a string of comma-separated
+ * qualifier strings. This value is passed directly as input to resource processing utilities that
+ * run in the execution phase, so it may represent different qualifiers than those in {@link
+ * #filters} if resources should not be pre-filtered during analysis.
+ */
+ private final String filterString;
+
+ /**
+ * @param ruleContext the current {@link RuleContext}, used for reporting errors
+ * @param filters a list of filters that should be applied during analysis time. If resources
+ * should not be filtered in analysis (e.g., if prefilter_resources = 0), this list should be
+ * empty.
+ * @param filterString the raw value of the resource configuration filters, as a comma-seperated
+ * string
+ */
+ private ResourceConfigurationFilter(
+ RuleContext ruleContext, ImmutableList<FolderConfiguration> filters, String filterString) {
+ this.ruleContext = ruleContext;
+ this.filters = filters;
+ this.filterString = filterString;
+ }
+
+ static boolean hasFilters(RuleContext ruleContext) {
+ return ruleContext.attributes().isAttributeValueExplicitlySpecified(ATTR_NAME);
+ }
+
+ /**
+ * Extracts the filters from the current RuleContext, as a string.
+ *
+ * <p>In BUILD files, filters can be represented as a list of strings, a single comma-seperated
+ * string, or a combination of both. This method outputs a single comma-seperated string of
+ * filters, which can then be passed directly to resource processing actions.
+ *
+ * @param ruleContext the current {@link RuleContext}
+ * @return the resource configuration filters contained in the {@link RuleContext}, in a single
+ * comma-separated string, or an empty string if no filters exist.
+ */
+ static String extractFilters(RuleContext ruleContext) {
+ if (!hasFilters(ruleContext)) {
+ return "";
+ }
+
+ return Joiner.on(',').join(ruleContext.getTokenizedStringListAttr(ATTR_NAME));
+ }
+
+ static ResourceConfigurationFilter fromRuleContext(RuleContext ruleContext) {
+ Preconditions.checkNotNull(ruleContext);
+
+ String resourceConfigurationFilters = extractFilters(ruleContext);
+
+ if (resourceConfigurationFilters.isEmpty()) {
+ return empty(ruleContext);
+ }
+
+ boolean shouldPrefilter =
+ ruleContext.getFragment(AndroidConfiguration.class).useResourcePrefiltering();
+
+ if (!shouldPrefilter) {
+ return new ResourceConfigurationFilter(
+ ruleContext, ImmutableList.<FolderConfiguration>of(), resourceConfigurationFilters);
+ }
+
+ ImmutableList.Builder<FolderConfiguration> builder = ImmutableList.builder();
+
+ for (String filter : resourceConfigurationFilters.split(",")) {
+ FolderConfiguration folderConfig = FolderConfiguration.getConfigForQualifierString(filter);
+
+ if (folderConfig == null) {
+ ruleContext.attributeError(
+ ATTR_NAME, "String '" + filter + "' is not a valid resource configuration filter");
+ } else {
+ builder.add(folderConfig);
+ }
+ }
+
+ return new ResourceConfigurationFilter(
+ ruleContext, builder.build(), resourceConfigurationFilters);
+ }
+
+ static ResourceConfigurationFilter empty(RuleContext ruleContext) {
+ return new ResourceConfigurationFilter(
+ ruleContext, ImmutableList.<FolderConfiguration>of(), "");
+ }
+
+ NestedSet<ResourceContainer> filter(NestedSet<ResourceContainer> resources) {
+ if (filters.isEmpty()) {
+ /*
+ * If the filter is empty or resource prefiltering is disabled, just return the original,
+ * rather than make a copy.
+ *
+ * Resources should only be prefiltered in top-level android targets (such as android_binary).
+ * The output of resource processing, which includes the input NestedSet<ResourceContainer>
+ * returned by this method, is exposed to other actions via the AndroidResourcesProvider. If
+ * this method did a no-op copy and collapse in those cases, rather than just return the
+ * original NestedSet, we would lose all of the advantages around memory and time that
+ * NestedSets provide: each android_library target would have to copy the resources provided
+ * by its dependencies into a new NestedSet rather than just create a NestedSet pointing at
+ * its dependencies's NestedSets.
+ */
+ return resources;
+ }
+
+ NestedSetBuilder<ResourceContainer> builder = new NestedSetBuilder<>(resources.getOrder());
+
+ for (ResourceContainer resource : resources) {
+ builder.add(resource.filter(this));
+ }
+
+ return builder.build();
+ }
+
+ ImmutableList<Artifact> filter(ImmutableList<Artifact> artifacts) {
+ if (filters.isEmpty()) {
+ return artifacts;
+ }
+
+ ImmutableList.Builder<Artifact> builder = ImmutableList.builder();
+
+ for (Artifact artifact : artifacts) {
+ String containingFolder = artifact.getPath().getParentDirectory().getBaseName();
+ if (matches(containingFolder)) {
+ builder.add(artifact);
+ }
+ }
+
+ return builder.build();
+ }
+
+ private boolean matches(String containingFolder) {
+ FolderConfiguration config = FolderConfiguration.getConfigForFolder(containingFolder);
+
+ if (config == null) {
+ ruleContext.ruleError(
+ "Resource folder '" + containingFolder + "' has invalid resource qualifiers");
+
+ return true;
+ }
+
+ // aapt explicitly ignores the version qualifier; duplicate this behavior here.
+ config.setVersionQualifier(VersionQualifier.getQualifier(""));
+
+ for (FolderConfiguration filter : filters) {
+ if (config.isMatchFor(filter)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns if this object represents an empty filter.
+ *
+ * <p>Note that non-empty filters are not guaranteed to filter resources during the analysis
+ * phase.
+ */
+ boolean isEmpty() {
+ return filterString.isEmpty();
+ }
+
+ String getFilterString() {
+ return filterString;
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceContainer.java b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceContainer.java
index 7a488742bf..c89de68856 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceContainer.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceContainer.java
@@ -124,6 +124,13 @@ public abstract class ResourceContainer {
/** Converts this container back into a builder to create a modified copy. */
public abstract Builder toBuilder();
+
+ /**
+ * Returns a copy of this container with filtered resources. The original container is unchanged.
+ */
+ public ResourceContainer filter(ResourceConfigurationFilter filter) {
+ return toBuilder().setResources(filter.filter(getResources())).build();
+ }
/** Creates a new builder with default values. */
public static Builder builder() {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceDependencies.java b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceDependencies.java
index b64570a97c..03f85b3556 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceDependencies.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceDependencies.java
@@ -151,6 +151,12 @@ public final class ResourceDependencies {
this.transitiveResources = transitiveResources;
this.directResources = directResources;
}
+
+ /** Returns a copy of this instance with filtered resources. The original object is unchanged. */
+ public ResourceDependencies filter(ResourceConfigurationFilter filter) {
+ return new ResourceDependencies(
+ neverlink, filter.filter(transitiveResources), filter.filter(directResources));
+ }
/**
* Creates a new AndroidResourcesProvider with the supplied ResourceContainer as the direct dep.
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceShrinkerActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceShrinkerActionBuilder.java
index 861a98389b..f9f6ad2235 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceShrinkerActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceShrinkerActionBuilder.java
@@ -44,7 +44,7 @@ public class ResourceShrinkerActionBuilder {
private List<String> uncompressedExtensions = Collections.emptyList();
private List<String> assetsToIgnore = Collections.emptyList();
- private List<String> resourceConfigs = Collections.emptyList();
+ private ResourceConfigurationFilter resourceConfigs;
/**
* @param ruleContext The RuleContext of the owning rule.
@@ -53,6 +53,7 @@ public class ResourceShrinkerActionBuilder {
this.ruleContext = ruleContext;
this.spawnActionBuilder = new SpawnAction.Builder();
this.sdk = AndroidSdkProvider.fromRuleContext(ruleContext);
+ this.resourceConfigs = ResourceConfigurationFilter.empty(ruleContext);
}
public ResourceShrinkerActionBuilder setUncompressedExtensions(
@@ -66,7 +67,11 @@ public class ResourceShrinkerActionBuilder {
return this;
}
- public ResourceShrinkerActionBuilder setConfigurationFilters(List<String> resourceConfigs) {
+ /**
+ * @param resourceConfigs The configuration filters to apply to the resources.
+ */
+ public ResourceShrinkerActionBuilder setConfigurationFilters(
+ ResourceConfigurationFilter resourceConfigs) {
this.resourceConfigs = resourceConfigs;
return this;
}
@@ -172,7 +177,7 @@ public class ResourceShrinkerActionBuilder {
commandLine.add("--debug");
}
if (!resourceConfigs.isEmpty()) {
- commandLine.addJoinStrings("--resourceConfigs", ",", resourceConfigs);
+ commandLine.add("--resourceConfigs").add(resourceConfigs.getFilterString());
}
checkNotNull(resourceFilesZip);