aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/android/java/com/google/devtools/build/android/dexer
diff options
context:
space:
mode:
authorGravatar kmb <kmb@google.com>2017-12-06 14:28:31 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2017-12-06 14:30:04 -0800
commit704d6ada9a17111879fec62bd7063a8a8a687b72 (patch)
tree25c86a62a181266abd1d21baab1661e3d19b2520 /src/tools/android/java/com/google/devtools/build/android/dexer
parent6ac92f9884ffd0bb46e4a5054ffd0311dc479571 (diff)
Support inclusion filter in DexFileSplitter, with the same semantics as in ../ziputils/DexMapper.
RELNOTES: None. PiperOrigin-RevId: 178153254
Diffstat (limited to 'src/tools/android/java/com/google/devtools/build/android/dexer')
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/dexer/DexFileSplitter.java50
1 files changed, 43 insertions, 7 deletions
diff --git a/src/tools/android/java/com/google/devtools/build/android/dexer/DexFileSplitter.java b/src/tools/android/java/com/google/devtools/build/android/dexer/DexFileSplitter.java
index 0ab70b46de..ffe3674b09 100644
--- a/src/tools/android/java/com/google/devtools/build/android/dexer/DexFileSplitter.java
+++ b/src/tools/android/java/com/google/devtools/build/android/dexer/DexFileSplitter.java
@@ -20,10 +20,10 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import com.android.dex.Dex;
import com.android.dex.DexFormat;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closer;
import com.google.devtools.build.android.Converters.ExistingPathConverter;
@@ -46,6 +46,8 @@ import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
@@ -118,6 +120,17 @@ class DexFileSplitter implements Closeable {
help = "Limit on fields and methods in a single dex file."
)
public int maxNumberOfIdxPerDex;
+
+ @Option(
+ name = "inclusion_filter_jar",
+ defaultValue = "null",
+ category = "input",
+ documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+ effectTags = {OptionEffectTag.UNKNOWN},
+ converter = ExistingPathConverter.class,
+ help = "If given, only classes in the given Jar are included in outputs."
+ )
+ public Path inclusionFilterJar;
}
public static void main(String[] args) throws Exception {
@@ -141,9 +154,12 @@ class DexFileSplitter implements Closeable {
Files.createDirectories(options.outputDirectory);
}
- ImmutableSet<String> classesInMainDex = options.mainDexListFile != null
- ? ImmutableSet.copyOf(Files.readAllLines(options.mainDexListFile, UTF_8))
- : null;
+ ImmutableSet<String> classesInMainDex =
+ options.mainDexListFile != null
+ ? ImmutableSet.copyOf(Files.readAllLines(options.mainDexListFile, UTF_8))
+ : null;
+ ImmutableSet<String> expected =
+ options.inclusionFilterJar != null ? expectedEntries(options.inclusionFilterJar) : null;
try (Closer closer = Closer.create();
DexFileSplitter out =
new DexFileSplitter(options.outputDirectory, options.maxNumberOfIdxPerDex)) {
@@ -152,11 +168,15 @@ class DexFileSplitter implements Closeable {
// if presented with a single jar containing all the given inputs.
// TODO(kmb): Abandon alphabetic sorting to process each input fully before moving on (still
// requires scanning inputs twice for main dex list).
+ Predicate<ZipEntry> inclusionFilter = ZipEntryPredicates.suffixes(".dex", ".class");
+ if (expected != null) {
+ inclusionFilter = inclusionFilter.and(e -> expected.contains(e.getName()));
+ }
LinkedHashMap<String, ZipFile> deduped = new LinkedHashMap<>();
for (Path inputArchive : options.inputArchives) {
ZipFile zip = closer.register(new ZipFile(inputArchive.toFile()));
zip.stream()
- .filter(ZipEntryPredicates.suffixes(".dex", ".class"))
+ .filter(inclusionFilter)
.forEach(e -> deduped.putIfAbsent(e.getName(), zip));
}
ImmutableList<Map.Entry<String, ZipFile>> files =
@@ -165,6 +185,13 @@ class DexFileSplitter implements Closeable {
.stream()
.sorted(Comparator.comparing(e -> e.getKey(), ZipEntryComparator::compareClassNames))
.collect(ImmutableList.toImmutableList());
+ if (expected != null) {
+ ImmutableSet<String> actual =
+ files.stream().map(e -> e.getKey()).collect(ImmutableSet.toImmutableSet());
+ Set<String> difference = Sets.difference(expected, actual);
+ checkState(difference.isEmpty(),
+ "--inclusion_filter_jar given but didn't find: %s", difference);
+ }
// 2. Process each class in desired order, rolling from shard to shard as needed.
if (classesInMainDex == null || classesInMainDex.isEmpty()) {
@@ -181,11 +208,20 @@ class DexFileSplitter implements Closeable {
if (options.minimalMainDex) {
out.nextShard(); // Start new .dex file if requested
}
- out.processDexFiles(files, Predicates.not(mainDexFilter));
+ out.processDexFiles(files, mainDexFilter.negate());
}
}
}
+ private static ImmutableSet<String> expectedEntries(Path filterJar) throws IOException {
+ try (ZipFile zip = new ZipFile(filterJar.toFile())) {
+ return zip.stream()
+ .filter(ZipEntryPredicates.suffixes(".class"))
+ .map(e -> e.getName() + ".dex")
+ .collect(ImmutableSet.toImmutableSet());
+ }
+ }
+
private final int maxNumberOfIdxPerDex;
private final Path outputDirectory;
@@ -235,7 +271,7 @@ class DexFileSplitter implements Closeable {
throws IOException {
for (Map.Entry<String, ZipFile> entry : filesToProcess) {
String filename = entry.getKey();
- if (filter.apply(filename)) {
+ if (filter.test(filename)) {
ZipFile zipFile = entry.getValue();
processDexEntry(zipFile, zipFile.getEntry(filename));
}