blob: 502471f52835c5d89142ee8e7aa0d7a3895403eb [file]
// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.retrace;
import static com.android.tools.r8.utils.ExceptionUtils.withMainProgramHandler;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.PartitionMapConsumer;
import com.android.tools.r8.Version;
import com.android.tools.r8.keepanno.annotations.KeepForApi;
import com.android.tools.r8.origin.CommandLineOrigin;
import com.android.tools.r8.retrace.internal.MappingPartitionImpl;
import com.android.tools.r8.retrace.internal.MappingPartitionMetadataInternal;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringUtils;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
/** A tool for creating a partition-map from a proguard map. */
@KeepForApi
public class Partition {
public static void run(String[] args) throws CompilationFailedException {
PartitionCommand command = PartitionCommand.parse(args, CommandLineOrigin.INSTANCE).build();
run(command);
}
/**
* The main entry point for partitioning a map.
*
* @param command The command that describes the desired behavior of this partition invocation.
*/
public static void run(PartitionCommand command) throws CompilationFailedException {
if (command.isPrintHelp()) {
System.out.println(PartitionCommandParser.getUsageMessage());
return;
}
if (command.isPrintVersion()) {
System.out.println("Partition " + Version.getVersionString());
return;
}
ExceptionUtils.withCompilationHandler(
command.getReporter(),
() -> {
if (command.getPartitionMapSuppliers().isEmpty()) {
runConvert(command);
} else {
runMerge(command);
}
});
}
private static void runConvert(PartitionCommand command) throws IOException {
command
.getPartitionMapConsumer()
.acceptMappingPartitionMetadata(
ProguardMapPartitioner.builder(command.getReporter())
.setProguardMapProducer(command.getProguardMapProducer())
.setPartitionConsumer(command.getPartitionMapConsumer()::acceptMappingPartition)
.setAllowEmptyMappedRanges(true)
.setAllowExperimentalMapping(false)
.build()
.run());
command.getPartitionMapConsumer().finished(command.getReporter());
}
private static void runMerge(PartitionCommand command) {
assert command.getProguardMapProducer() == null;
Reporter reporter = command.getReporter();
Map<String, byte[]> partitions = new LinkedHashMap<>();
// Process PartitionMapSuppliers
MappingPartitionMetadataInternal mergedMetadata = null;
for (PartitionMappingSupplier supplier : command.getPartitionMapSuppliers()) {
MappingPartitionMetadataInternal metadata = supplier.getMetadata(reporter);
if (mergedMetadata == null) {
mergedMetadata = metadata;
} else {
mergedMetadata = mergedMetadata.combineMetadata(metadata, command.getPartitionMapId());
}
for (String key : metadata.getPartitionKeys()) {
byte[] payload = supplier.getMappingPartitionFromKeySupplier().get(key);
byte[] previousPayload = partitions.put(key, payload);
if (previousPayload != null) {
throw new RetracePartitionException(
"Composition not supported, multiple payloads for same key (" + key + ") found");
}
}
}
// Output merged partitions
PartitionMapConsumer consumer = command.getPartitionMapConsumer();
for (Entry<String, byte[]> entry : partitions.entrySet()) {
consumer.acceptMappingPartition(new MappingPartitionImpl(entry.getKey(), entry.getValue()));
}
consumer.acceptMappingPartitionMetadata(mergedMetadata);
consumer.finished(reporter);
}
/**
* The main entry point for running a legacy proguard map to partition map from command line.
*
* @param args The argument that describes this command.
*/
public static void main(String... args) {
if (args.length == 0) {
throw new RuntimeException(
StringUtils.joinLines("Invalid invocation.", PartitionCommandParser.getUsageMessage()));
}
withMainProgramHandler(() -> run(args));
}
}